8729b41d4050d7d385589dd3e65d61e9f97a06b5
[lcr.git] / apppbx.cpp
1 /*****************************************************************************\
2 **                                                                           **
3 ** Linux Call Router                                                         **
4 **                                                                           **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg                                              **
7 **                                                                           **
8 ** The EndpointAppPBX implements PBX4Linux                                   **
9 **                                                                           **
10 \*****************************************************************************/ 
11
12
13 #include <stdio.h>
14 #include <sys/stat.h>
15 #include <sys/types.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <poll.h>
21 #include "main.h"
22
23 class EndpointAppPBX *apppbx_first = NULL;
24
25 /*
26  * EndpointAppPBX constructor
27  */
28 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint) : EndpointApp(epoint)
29 {
30         class EndpointAppPBX **apppointer;
31
32         /* add application to chain */
33         next = NULL;
34         apppointer = &apppbx_first;
35         while(*apppointer)
36                 apppointer = &((*apppointer)->next);
37         *apppointer = this;
38
39         /* initialize */
40         memset(&e_ext, 0, sizeof(struct extension));
41         e_ext.rights = 4; /* international */
42         e_ext.rxvol = e_ext.txvol = 256;
43         e_state = EPOINT_STATE_IDLE;
44         e_ext.number[0] = '\0';
45         e_extension_interface[0] = '\0';
46         memset(&e_callerinfo, 0, sizeof(struct caller_info));
47         memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
48         memset(&e_connectinfo, 0, sizeof(struct connect_info));
49         memset(&e_redirinfo, 0, sizeof(struct redir_info));
50         memset(&e_capainfo, 0, sizeof(struct capa_info));
51         e_start = e_stop = 0;
52 //      e_origin = 0;
53         e_ruleset = ruleset_main;
54         if (e_ruleset)
55                 e_rule = e_ruleset->rule_first;
56         e_rule_nesting = 0;
57         e_action = NULL;
58         e_action_timeout = 0;
59         e_match_timeout = 0;
60         e_match_to_action = NULL;
61         e_select = 0;
62         e_extdialing = e_dialinginfo.id;
63 //        e_knocking = 0;
64 //        e_knocktime = 0;
65         e_hold = 0;
66 //        e_join_tone[0] = e_hold_tone[0] = '\0';
67         e_join_pattern /*= e_hold_pattern*/ = 0;
68         e_redial = 0;
69         e_tone[0] = '\0';
70         e_adminid = 0; // will be set, if call was initiated via admin socket
71         e_powerdialing = 0;
72         e_powerdelay = 0;
73         e_powerlimit = 0;
74         e_callback = 0;
75         e_cbdialing[0] = '\0';
76         e_cbcaller[0] = '\0';
77         e_cbto[0] = '\0';
78         memset(&e_callbackinfo, 0, sizeof(struct caller_info));
79         e_connectedmode = 0;
80         e_dtmf = 0;
81         e_dtmf_time = 0;
82         e_dtmf_last = 0;
83         e_cfnr_release = 0;
84         e_cfnr_call = 0;
85         e_password_timeout = 0;
86         e_multipoint_cause = 0;
87         e_multipoint_location = 0;
88         e_dialing_queue[0] = '\0';
89         e_crypt = CRYPT_OFF;
90         e_crypt_state = CM_ST_NULL;
91         e_crypt_keyengine_busy = 0;
92         e_crypt_info[0] = '\0'; 
93         e_overlap = 0;
94         e_vbox[0] = '\0';
95         e_tx_state = NOTIFY_STATE_ACTIVE;
96         e_rx_state = NOTIFY_STATE_ACTIVE;
97         e_join_cause = e_join_location = 0;
98 /*********************************
99  *********************************
100  ********* ATTENTION *************
101  *********************************
102  *********************************/
103 /* if you add new values, that must be initialized, also check if they must
104  * be initialized when doing callback
105  */
106
107 }
108
109 /*
110  * EpointAppPBX destructor
111  */
112 EndpointAppPBX::~EndpointAppPBX(void)
113 {
114         class EndpointAppPBX *temp, **tempp;
115
116         /* detach */
117         temp =apppbx_first;
118         tempp = &apppbx_first;
119         while(temp)
120         {
121                 if (temp == this)
122                         break;
123
124                 tempp = &temp->next;
125                 temp = temp->next;
126         }
127         if (temp == 0)
128                 FATAL("Endpoint not in endpoint's list.\n");
129         *tempp = next;
130
131 }
132
133
134 /*
135  * trace header for application
136  */
137 void EndpointAppPBX::trace_header(char *name, int direction)
138 {
139         struct trace _trace;
140
141         char msgtext[sizeof(_trace.name)];
142
143         SCPY(msgtext, name);
144
145         /* init trace with given values */
146         start_trace(0,
147                     NULL,
148                     numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype),
149                     e_dialinginfo.id,
150                     direction,
151                     CATEGORY_EP,
152                     ea_endpoint->ep_serial,
153                     msgtext);
154 }
155
156
157 EPOINT_STATE_NAMES
158
159 /* set new endpoint state
160  */
161 void EndpointAppPBX::new_state(int state)
162 {
163 #if 0
164         if (e_state != state)
165         {
166                 trace_header("NEW STATE", DIRECTION_NONE);
167                 add_trace("state", "old", "%s", state_name[e_state]);
168                 add_trace("state", "new", "%s", state_name[state]);
169                 end_trace();
170         }
171 #endif
172         e_state = state;
173 }
174
175
176 /* screen caller id
177  * out==0: incomming caller id, out==1: outgoing caller id
178  */
179 void EndpointAppPBX::screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
180 {
181         char                    *msn1;
182         struct interface_msn    *ifmsn;
183         struct interface_screen *ifscreen;
184         char suffix[64];
185
186         /* screen incoming caller id */
187         if (!out)
188         {
189                 /* check for MSN numbers, use first MSN if no match */
190                 msn1 = NULL;
191                 ifmsn = interface->ifmsn;
192                 while(ifmsn)
193                 {
194                         if (!msn1)
195                                 msn1 = ifmsn->msn;
196                         if (!strcmp(ifmsn->msn, id))
197                         {
198                                 break;
199                         }
200                         ifmsn = ifmsn->next;
201                 }
202                 if (ifmsn)
203                 {
204                         trace_header("SCREEN (found in MSN list)", DIRECTION_IN);
205                         add_trace("msn", NULL, "%s", id);
206                         end_trace();
207                 }
208                 if (!ifmsn && msn1) // not in list, first msn given
209                 {
210                         trace_header("SCREEN (not found MSN in list)", DIRECTION_IN);
211                         add_trace("msn", "given", "%s", id);
212                         add_trace("msn", "used", "%s", msn1);
213                         end_trace();
214                         UNCPY(id, msn1, idsize);
215                         id[idsize-1] = '\0';
216                 }
217         }
218
219         /* check screen list */
220         if (out)
221                 ifscreen = interface->ifscreen_out;
222         else
223                 ifscreen = interface->ifscreen_in;
224         while (ifscreen)
225         {
226                 if (ifscreen->match_type==-1 || ifscreen->match_type==*type)
227                 if (ifscreen->match_present==-1 || ifscreen->match_present==*present)
228                 {
229                         if (strchr(ifscreen->match,'%'))
230                         {
231                                 if (!strncmp(ifscreen->match, id, strchr(ifscreen->match,'%')-ifscreen->match))
232                                         break;
233                         } else
234                         {
235                                 if (!strcmp(ifscreen->match, id))
236                                         break;
237                         }
238                 }
239                 ifscreen = ifscreen->next;
240         }
241         if (ifscreen) // match
242         {
243                 trace_header("SCREEN (found in screen list)", out?DIRECTION_OUT:DIRECTION_IN);
244                 switch(*type)
245                 {
246                         case INFO_NTYPE_UNKNOWN:
247                         add_trace("given", "type", "unknown");
248                         break;
249                         case INFO_NTYPE_SUBSCRIBER:
250                         add_trace("given", "type", "subscriber");
251                         break;
252                         case INFO_NTYPE_NATIONAL:
253                         add_trace("given", "type", "national");
254                         break;
255                         case INFO_NTYPE_INTERNATIONAL:
256                         add_trace("given", "type", "international");
257                         break;
258                 }
259                 switch(*present)
260                 {
261                         case INFO_PRESENT_ALLOWED:
262                         add_trace("given", "present", "allowed");
263                         break;
264                         case INFO_PRESENT_RESTRICTED:
265                         add_trace("given", "present", "restricted");
266                         break;
267                         case INFO_PRESENT_NOTAVAIL:
268                         add_trace("given", "present", "not available");
269                         break;
270                 }
271                 add_trace("given", "id", "%s", id[0]?id:"<empty>");
272                 if (ifscreen->result_type != -1)
273                 {
274                         *type = ifscreen->result_type;
275                         switch(*type)
276                         {
277                                 case INFO_NTYPE_UNKNOWN:
278                                 add_trace("used", "type", "unknown");
279                                 break;
280                                 case INFO_NTYPE_SUBSCRIBER:
281                                 add_trace("used", "type", "subscriber");
282                                 break;
283                                 case INFO_NTYPE_NATIONAL:
284                                 add_trace("used", "type", "national");
285                                 break;
286                                 case INFO_NTYPE_INTERNATIONAL:
287                                 add_trace("used", "type", "international");
288                                 break;
289                         }
290                 }
291                 if (ifscreen->result_present != -1)
292                 {
293                         *present = ifscreen->result_present;
294                         switch(*present)
295                         {
296                                 case INFO_PRESENT_ALLOWED:
297                                 add_trace("used", "present", "allowed");
298                                 break;
299                                 case INFO_PRESENT_RESTRICTED:
300                                 add_trace("used", "present", "restricted");
301                                 break;
302                                 case INFO_PRESENT_NOTAVAIL:
303                                 add_trace("used", "present", "not available");
304                                 break;
305                         }
306                 }
307                 if (strchr(ifscreen->match,'%'))
308                 {
309                         SCPY(suffix, strchr(ifscreen->match,'%') - ifscreen->match + id);
310                         UNCPY(id, ifscreen->result, idsize);
311                         id[idsize-1] = '\0';
312                         if (strchr(id,'%'))
313                         {
314                                 *strchr(id,'%') = '\0';
315                                 UNCAT(id, suffix, idsize);
316                                 id[idsize-1] = '\0';
317                         }
318                 } else
319                 {
320                         UNCPY(id, ifscreen->result, idsize);
321                         id[idsize-1] = '\0';
322                 }
323                 add_trace("used", "id", "%s", id[0]?id:"<empty>");
324                 end_trace();
325         }
326 }
327
328 /* release join and port (as specified)
329  */
330 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
331 {
332         struct port_list *portlist;
333         struct message *message;
334         char cause[16];
335
336         /* message to test call */
337         admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
338
339         /* if a release is pending */
340         if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
341         {
342                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
343                 if (ea_endpoint->ep_join_id)
344                 {
345                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
346                         message->param.disconnectinfo.cause = joincause;
347                         message->param.disconnectinfo.location = joinlocation;
348                         message_put(message);
349                         ea_endpoint->ep_join_id = 0;
350                 }
351                 e_join_pattern = 0;
352 #if 0
353                 if (release != RELEASE_PORT_JOINONLY)
354                 {
355                         if (e_hold_id)
356                                 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
357                         e_hold_id = 0;
358                 }
359 #endif
360         }
361         if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY)
362         {
363                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
364                 while((portlist = ea_endpoint->ep_portlist))
365                 {
366                         if (portlist->port_id)
367                         {
368                                 SPRINT(cause, "cause_%02x", portcause);
369                                 set_tone(portlist, cause);
370                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
371                                 message->param.disconnectinfo.cause = portcause;
372                                 message->param.disconnectinfo.location = portlocation;
373                                 message_put(message);
374                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
375                         }
376                         ea_endpoint->free_portlist(portlist);
377                 }
378
379                 /* if callback is enabled, call back with the given caller id */
380                 if (e_callback)
381                 {
382                         /* reset some stuff */
383                         new_state(EPOINT_STATE_IDLE);
384                         memset(&e_connectinfo, 0, sizeof(struct connect_info));
385                         memset(&e_redirinfo, 0, sizeof(struct redir_info));
386                         e_start = e_stop = 0;
387                         e_ruleset = ruleset_main;
388                         if (e_ruleset)
389                                 e_rule = e_ruleset->rule_first;
390                         e_action = NULL;
391                         e_action_timeout = 0;
392                         e_match_timeout = 0;
393                         e_match_to_action = NULL;
394                         //e_select = 0;
395                         e_extdialing = e_dialinginfo.id;
396                         e_connectedmode = 0;
397                         e_dtmf = 0;
398                         e_dtmf_time = 0;
399                         e_dtmf_last = 0;
400                         e_cfnr_release = 0;
401                         e_cfnr_call = 0;
402                         e_multipoint_cause = 0;
403                         e_multipoint_location = 0;
404                         e_dialing_queue[0] = '\0';
405                         e_crypt = 0;
406                         e_crypt_state = CM_ST_NULL;
407                         e_crypt_keyengine_busy = 0;
408                         e_crypt_info[0] = '\0'; 
409                         e_tone[0] = '\0';
410                         e_overlap = 0;
411                         e_vbox[0] = '\0';
412                         e_tx_state = NOTIFY_STATE_ACTIVE;
413                         e_rx_state = NOTIFY_STATE_ACTIVE;
414                         e_join_cause = e_join_location = 0;
415                         e_rule_nesting = 0;
416                         /* the caller info of the callback user */
417                         memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
418                         memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
419                         /* create dialing by callerinfo */
420                         if (e_ext.number[0] && e_extension_interface[0])
421                         {
422                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
423                                 /* create callback to the current terminal */
424                                 SCPY(e_dialinginfo.id, e_ext.number);
425                                 SCPY(e_dialinginfo.interfaces, e_extension_interface);
426                                 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
427                                 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
428                         } else
429                         {
430                                 if (e_cbto[0])
431                                 {
432                                         SCPY(e_dialinginfo.id, e_cbto);
433                                 } else
434                                 {
435                                         /* numberrize caller id and use it to dial to the callback */
436                                         SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
437                                 }
438                                 e_dialinginfo.itype = INFO_ITYPE_ISDN;
439                                 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
440                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
441                         }
442                         return;
443                 }
444
445                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
446                 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
447                 return;
448         }
449 }
450
451
452 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
453 void apply_callerid_restriction(int anon_ignore, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
454 {
455         PDEBUG(DEBUG_EPOINT, "id='%s' ntype=%d present=%d screen=%d extension='%s' name='%s'\n", (id)?id:"NULL", (ntype)?*ntype:-1, (present)?*present:-1, (screen)?*screen:-1, (extension)?extension:"NULL", (name)?name:"NULL");
456
457         /* caller id is not restricted, so we do nothing */
458         if (*present != INFO_PRESENT_RESTRICTED)
459                 return;
460
461         /* only extensions are restricted */
462         if (!extension)
463                 return;
464         if (!extension[0])
465                 return;
466
467         /* if we enabled anonymouse ignore */
468         if (anon_ignore)
469                 return;
470
471         /* else we remove the caller id */
472         if (id)
473                 id[0] = '\0';
474         if (ntype)
475                 *ntype = INFO_NTYPE_UNKNOWN;
476 //      if (screen)
477 //              *screen = INFO_SCREEN_USER;
478 // maybe we should not make voip address anonymous
479 //      if (voip)
480 //              voip[0] = '\0';
481 // maybe it's no fraud to present extension id
482 //      if (extension)
483 //              extension[0] = '\0';
484         if (name)
485                 name[0] = '\0';
486 }
487
488 /* used display message to display callerid as available */
489 char *EndpointAppPBX::apply_callerid_display(char *id, int itype, int ntype, int present, int screen, char *extension, char *name)
490 {
491         static char display[81];
492
493         display[0] = '\0';
494         char *cid = numberrize_callerinfo(id, ntype);
495
496         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) id='%s' itype=%d ntype=%d present=%d screen=%d extension='%s' name='%s'\n", ea_endpoint->ep_serial, (id)?id:"NULL", itype, ntype, present, screen, (extension)?extension:"NULL", (name)?name:"NULL");
497
498         if (!id)
499                 id = "";
500         if (!extension)
501                 extension = "";
502         if (!name)
503                 name = "";
504
505         /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
506
507         /* internal extension's caller id */
508         if (extension[0] && e_ext.display_int)
509         {
510                 if (!display[0])
511                         SCAT(display, extension);
512                 if (display[0])
513                         SCAT(display, " ");
514                 if (itype == INFO_ITYPE_VBOX)
515                         SCAT(display, "(vbox)");
516                 else
517                         SCAT(display, "(int)");
518         }
519
520         /* external caller id */
521         if (!extension[0] && e_ext.display_ext)
522         {
523                 if (!display[0])
524                 {
525                         if (!cid[0])
526                         {
527                                 if (present == INFO_PRESENT_RESTRICTED)
528                                         SCAT(display, "anonymous");
529                                 else
530                                         SCAT(display, "unknown");
531                         }
532                         else
533                                 SCAT(display, cid);
534                 }
535         }
536
537         /* display if callerid is anonymouse but available due anon-ignore */
538         if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED)
539         {
540                 if (!cid[0])
541                         SCAT(display, "unknown");
542                 else 
543                         SCAT(display, cid);
544                 SCAT(display, " anon");
545         }
546
547         /* display if callerid is anonymouse but available due anon-ignore */
548         if (e_ext.display_fake && screen==INFO_SCREEN_USER && present!=INFO_PRESENT_NULL)
549         {
550                 if (!display[0])
551                 {
552                         if (!id[0])
553                         {
554                                 if (present == INFO_PRESENT_RESTRICTED)
555                                         SCAT(display, "anonymous");
556                                 else
557                                         SCAT(display, "unknown");
558                         }
559                         else
560                                 SCAT(display, cid);
561                 }
562                 SCAT(display, " fake");
563         }
564
565         /* caller name */
566         if (name[0] && e_ext.display_name)
567         {
568                 if (!display[0] && cid[0])
569                                 SCAT(display, cid);
570                 if (display[0])
571                                 SCAT(display, " ");
572                 SCAT(display, name);
573         }
574
575         return(display);
576 }
577
578 /*
579  * uses the current state to notify activity
580  */
581 void EndpointAppPBX::notify_active(void)
582 {
583         struct port_list *portlist = ea_endpoint->ep_portlist;
584         struct message *message;
585         int notify = 0;
586
587         switch(e_tx_state)
588         {
589                 case NOTIFY_STATE_ACTIVE:
590                 /* we are already active, so we don't do anything */
591                 break;
592
593                 case NOTIFY_STATE_SUSPEND:
594                 notify = INFO_NOTIFY_USER_RESUMED;
595                 while(portlist)
596                 {
597                         set_tone(portlist, NULL);
598                         portlist = portlist->next;
599                 }
600                 portlist = ea_endpoint->ep_portlist;
601                 break;
602
603                 case NOTIFY_STATE_HOLD:
604                 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
605                 while(portlist)
606                 {
607                         set_tone(portlist, NULL);
608                         portlist = portlist->next;
609                 }
610                 portlist = ea_endpoint->ep_portlist;
611                 break;
612
613                 case NOTIFY_STATE_CONFERENCE:
614                 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
615                 while(portlist)
616                 {
617                         set_tone(portlist, NULL);
618                         portlist = portlist->next;
619                 }
620                 portlist = ea_endpoint->ep_portlist;
621                 break;
622
623                 default:
624                 PERROR("unknown e_tx_state = %d\n", e_tx_state);
625         }
626
627         if (notify)
628         while(portlist)
629         {
630                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
631                 message->param.notifyinfo.notify = notify;
632                 message_put(message);
633                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
634                 portlist = portlist->next;
635         }
636 }
637
638
639 /*
640  * keypad functions during call. one example to use this is to put a call on hold or start a conference
641  */
642 void EndpointAppPBX::keypad_function(char digit)
643 {
644
645         /* we must be in a call, in order to send messages to the call */
646         if (e_ext.number[0] == '\0')
647         {
648                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
649                 return;
650         }
651
652         switch(digit)
653         {
654                 /* join conference */
655                 case '3':
656                 if (ea_endpoint->ep_join_id == 0)
657                 {
658                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
659                         break;
660                 }
661                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
662                 join_join();
663                 break;
664
665                 /* crypt shared */
666                 case '7':
667                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
668                 encrypt_shared();
669                 break;
670
671                 /* crypt key-exchange */
672                 case '8':
673                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
674                 encrypt_keyex();
675                 break;
676
677                 /* crypt off */
678                 case '9':
679                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
680                 encrypt_off();
681                 break;
682
683                 default:        
684                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
685         }
686 }
687
688
689 /* set tone pattern for port */
690 void EndpointAppPBX::set_tone(struct port_list *portlist, char *tone)
691 {
692         struct message *message;
693
694         if (!tone)
695                 tone = "";
696
697         /* store for suspended processes */
698         SCPY(e_tone, tone);
699
700
701         if (e_join_pattern /* pattern are provided */
702          && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
703          && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
704          && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
705          && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
706          && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
707          && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
708          && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
709          && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
710          && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
711          && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
712          && tone[0] && !!strncmp(tone,"crypt_*",6))
713         {
714                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
715                 tone = "";
716         }
717
718         if (portlist)
719         {
720                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
721                 SCPY(message->param.tone.dir, e_ext.tones_dir[0]?e_ext.tones_dir:options.tones_dir);
722                 SCPY(message->param.tone.name, tone);
723                 message_put(message);
724                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
725         } else
726         {
727                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
728                 return;
729         }
730 }
731
732
733 /*
734  * hunts an mISDNport that is available for an outgoing call
735  * if no ifname was given, any interface that is not an extension
736  * will be searched.
737  */
738 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
739 {
740         struct interface *interface;
741         struct interface_port *ifport, *ifport_start;
742         struct select_channel *selchannel; 
743         struct mISDNport *mISDNport;
744         int index, i;
745
746         interface = interface_first;
747
748         /* first find the given interface or, if not given, one with no extension */
749         checknext:
750         if (!interface)
751                 return(NULL);
752
753         /* check for given interface */
754         if (ifname)
755         {
756                 if (!strcasecmp(interface->name, ifname))
757                 {
758                         /* found explicit interface */
759                         trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
760                         add_trace("interface", NULL, "%s", ifname);
761                         end_trace();
762                         goto foundif;
763                 }
764
765         } else
766         {
767                 if (!interface->extension)
768                 {
769                         /* found non extension */
770                         trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
771                         add_trace("interface", NULL, "%s", interface->name);
772                         end_trace();
773                         goto foundif;
774                 }
775         }
776
777         interface = interface->next;
778         goto checknext;
779 foundif:
780
781         /* see if interface has ports */
782         if (!interface->ifport)
783         {
784                 /* no ports */
785                 trace_header("CHANNEL SELECTION (interface has no active ports, skipping)", DIRECTION_NONE);
786                 add_trace("interface", NULL, "%s", interface->name);
787                 end_trace();
788                 interface = interface->next;
789                 goto checknext;
790         }
791
792         /* select port by algorithm */
793         ifport_start = interface->ifport;
794         index = 0;
795         if (interface->hunt == HUNT_ROUNDROBIN)
796         {
797                 while(ifport_start->next && index<interface->hunt_next)
798                 {
799                         ifport_start = ifport_start->next;
800                         index++;
801                 }
802                 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
803                 add_trace("port", NULL, "%d", ifport_start->portnum);
804                 add_trace("position", NULL, "%d", index);
805                 end_trace();
806         }
807
808         /* loop ports */
809         ifport = ifport_start;
810         nextport:
811
812         /* see if port is available */
813         if (!ifport->mISDNport)
814         {
815                 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
816                 add_trace("port", NULL, "%d", ifport->portnum);
817                 add_trace("position", NULL, "%d", index);
818                 end_trace();
819                 goto portbusy;
820         }
821         mISDNport = ifport->mISDNport;
822
823         /* see if port is administratively blocked */
824         if (ifport->block)
825         {
826                 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
827                 add_trace("port", NULL, "%d", ifport->portnum);
828                 add_trace("position", NULL, "%d", index);
829                 end_trace();
830                 goto portbusy;
831         }
832
833         /* see if link is up on PTP*/
834         if (mISDNport->ptp && !mISDNport->l2link)
835         {
836                 trace_header("CHANNEL SELECTION (port is ptp with layer 2 down, skipping)", DIRECTION_NONE);
837                 add_trace("port", NULL, "%d", ifport->portnum);
838                 add_trace("position", NULL, "%d", index);
839                 end_trace();
840                 goto portbusy;
841         }
842
843         /* check for channel form selection list */
844         *channel = 0;
845         selchannel = ifport->out_channel;
846         while(selchannel)
847         {
848                 switch(selchannel->channel)
849                 {
850                         case CHANNEL_FREE: /* free channel */
851                         if (mISDNport->b_reserved >= mISDNport->b_num)
852                                 break; /* all channel in use or reserverd */
853                         /* find channel */
854                         i = 0;
855                         while(i < mISDNport->b_num)
856                         {
857                                 if (mISDNport->b_port[i] == NULL)
858                                 {
859                                         *channel = i+1+(i>=15);
860                                         trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
861                                         add_trace("port", NULL, "%d", ifport->portnum);
862                                         add_trace("position", NULL, "%d", index);
863                                         add_trace("channel", NULL, "%d", *channel);
864                                         end_trace();
865                                         break;
866                                 }
867                                 i++;
868                         }
869                         trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
870                         add_trace("port", NULL, "%d", ifport->portnum);
871                         add_trace("position", NULL, "%d", index);
872                         end_trace();
873                         break;
874
875                         case CHANNEL_ANY: /* don't ask for channel */
876                         if (mISDNport->b_reserved >= mISDNport->b_num)
877                         {
878                                 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
879                                 add_trace("port", NULL, "%d", ifport->portnum);
880                                 add_trace("position", NULL, "%d", index);
881                                 add_trace("total", NULL, "%d", mISDNport->b_num);
882                                 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
883                                 end_trace();
884                                 break; /* all channel in use or reserverd */
885                         }
886                         trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
887                         add_trace("port", NULL, "%d", ifport->portnum);
888                         add_trace("position", NULL, "%d", index);
889                         end_trace();
890                         *channel = CHANNEL_ANY;
891                         break;
892
893                         case CHANNEL_NO: /* call waiting */
894                         trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
895                         add_trace("port", NULL, "%d", ifport->portnum);
896                         add_trace("position", NULL, "%d", index);
897                         end_trace();
898                         *channel = CHANNEL_NO;
899                         break;
900
901                         default:
902                         if (selchannel->channel<1 || selchannel->channel==16)
903                         {
904                                 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
905                                 add_trace("port", NULL, "%d", ifport->portnum);
906                                 add_trace("position", NULL, "%d", index);
907                                 add_trace("channel", NULL, "%d", selchannel->channel);
908                                 end_trace();
909                                 break; /* invalid channels */
910                         }
911                         i = selchannel->channel-1-(selchannel->channel>=17);
912                         if (i >= mISDNport->b_num)
913                         {
914                                 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
915                                 add_trace("port", NULL, "%d", ifport->portnum);
916                                 add_trace("position", NULL, "%d", index);
917                                 add_trace("channel", NULL, "%d", selchannel->channel);
918                                 add_trace("channels", NULL, "%d", mISDNport->b_num);
919                                 end_trace();
920                                 break; /* channel not in port */
921                         }
922                         if (mISDNport->b_port[i] == NULL)
923                         {
924                                 *channel = selchannel->channel;
925                                 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
926                                 add_trace("port", NULL, "%d", ifport->portnum);
927                                 add_trace("position", NULL, "%d", index);
928                                 add_trace("channel", NULL, "%d", *channel);
929                                 end_trace();
930                                 break;
931                         }
932                         break;
933                 }
934                 if (*channel)
935                         break; /* found channel */
936                 selchannel = selchannel->next;
937         }
938
939         /* if channel was found, return mISDNport and channel */
940         if (*channel)
941         {
942                 /* setting next port to start next time */
943                 if (interface->hunt == HUNT_ROUNDROBIN)
944                 {
945                         index++;
946                         if (!ifport->next)
947                                 index = 0;
948                         interface->hunt_next = index;
949                 }
950                 
951                 return(mISDNport);
952         }
953
954         trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
955         add_trace("port", NULL, "%d", ifport->portnum);
956         add_trace("position", NULL, "%d", index);
957         end_trace();
958
959         portbusy:
960         /* go next port, until all ports are checked */
961         index++;
962         ifport = ifport->next;
963         if (!ifport)
964         {
965                 index = 0;
966                 ifport = interface->ifport;
967         }
968         if (ifport != ifport_start)
969                 goto nextport;
970
971         return(NULL); /* no port found */
972 }
973
974 /* outgoing setup to port(s)
975  * ports will be created and a setup is sent if everything is ok. otherwhise
976  * the endpoint is destroyed.
977  */
978 void EndpointAppPBX::out_setup(void)
979 {
980         struct dialing_info     dialinginfo;
981         class Port              *port;
982 //      class pdss1             *pdss1;
983         struct port_list        *portlist;
984         struct message          *message;
985         int                     anycall = 0;
986         int                     cause = CAUSE_RESSOURCEUNAVAIL;
987         char                    *p;
988         char                    cfp[64];
989         struct mISDNport        *mISDNport;
990         char                    portname[32];
991         char                    *dirname;
992         class EndpointAppPBX    *atemp;
993 //      char                    allowed_ports[256];
994 //      char                    exten[256];
995         char                    ifname[sizeof(e_ext.interfaces)],
996                                 number[256];
997         struct port_settings    port_settings;
998         int                     channel = 0;
999         int                     earlyb;
1000
1001         /* create settings for creating port */
1002         memset(&port_settings, 0, sizeof(port_settings));
1003         if (e_ext.tones_dir)
1004                 SCPY(port_settings.tones_dir, e_ext.tones_dir);
1005         else
1006                 SCPY(port_settings.tones_dir, options.tones_dir);
1007         port_settings.tout_setup = e_ext.tout_setup;
1008         port_settings.tout_dialing = e_ext.tout_dialing;
1009         port_settings.tout_proceeding = e_ext.tout_proceeding;
1010         port_settings.tout_alerting = e_ext.tout_alerting;
1011         port_settings.tout_disconnect = e_ext.tout_disconnect;
1012 //      port_settings.tout_hold = e_ext.tout_hold;
1013 //      port_settings.tout_park = e_ext.tout_park;
1014         port_settings.no_seconds = e_ext.no_seconds;
1015         
1016         /* NOTE: currently the try_card feature is not supported. it should be used later to try another card, if the outgoing call fails on one port */
1017
1018         /* check what dialinginfo.itype we got */
1019         switch(e_dialinginfo.itype)
1020         {
1021                 /* *********************** call to extension or vbox */
1022                 case INFO_ITYPE_ISDN_EXTENSION:
1023                 /* check if we deny incoming calls when we use an extension */
1024                 if (e_ext.noknocking)
1025                 {
1026                         atemp = apppbx_first;
1027                         while(atemp)
1028                         {
1029                                 if (atemp != this)
1030                                 if (!strcmp(atemp->e_ext.number, e_ext.number))
1031                                         break;
1032                                 atemp = atemp->next;
1033                         }
1034                         if (atemp)
1035                         {
1036                                 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
1037                                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
1038                                 return; /* must exit here */
1039                         }
1040                 }
1041                 /* FALL THROUGH !!!! */
1042                 case INFO_ITYPE_VBOX:
1043                 /* get dialed extension's info */
1044 //              SCPY(exten, e_dialinginfo.id);
1045 //              if (strchr(exten, ','))
1046 //                      *strchr(exten, ',') = '\0';
1047 //              if (!read_extension(&e_ext, exten))
1048                 if (!read_extension(&e_ext, e_dialinginfo.id))
1049                 {
1050                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1051                         release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1052                         return; /* must exit here */
1053                 }
1054
1055                 if (e_dialinginfo.itype == INFO_ITYPE_VBOX)
1056                 {
1057                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
1058                         p = "vbox";
1059                         goto vbox_only;
1060                 }
1061
1062                 /* string from unconditional call forward (cfu) */
1063                 p = e_ext.cfu;
1064                 if (*p)
1065                 {
1066                         /* present to forwarded party */
1067                         if (e_ext.anon_ignore && e_callerinfo.id[0])
1068                         {
1069                                 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1070                         }
1071                         if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1072                                 goto cfu_only;
1073                 }
1074
1075                 /* string from busy call forward (cfb) */
1076                 p = e_ext.cfb;
1077                 if (*p)
1078                 {
1079                         class EndpointAppPBX *checkapp = apppbx_first;
1080                         while(checkapp)
1081                         {
1082                                 if (checkapp != this) /* any other endpoint except our own */
1083                                 {
1084                                         if (!strcmp(checkapp->e_ext.number, e_ext.number))
1085                                         {
1086                                                 /* present to forwarded party */
1087                                                 if (e_ext.anon_ignore && e_callerinfo.id[0])
1088                                                 {
1089                                                         e_callerinfo.present = INFO_PRESENT_ALLOWED;
1090                                                 }
1091                                                 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1092                                                         goto cfb_only;
1093                                         }
1094                                 }
1095                                 checkapp = checkapp->next;
1096                         }
1097                 }
1098
1099                 /* string from no-response call forward (cfnr) */
1100                 p = e_ext.cfnr;
1101                 if (*p)
1102                 {
1103                         /* when cfnr is done, out_setup() will setup the call */
1104                         if (e_cfnr_call)
1105                         {
1106                                 /* present to forwarded party */
1107                                 if (e_ext.anon_ignore && e_callerinfo.id[0])
1108                                 {
1109                                         e_callerinfo.present = INFO_PRESENT_ALLOWED;
1110                                 }
1111                                 goto cfnr_only;
1112                         }
1113                         if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
1114                         {
1115                                 e_cfnr_release = now + e_ext.cfnr_delay;
1116                                 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
1117                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) setting time for call-forward-busy to %s with delay %ld.\n", ea_endpoint->ep_serial, e_ext.cfnr, e_ext.cfnr_delay);
1118                         }
1119                 }
1120
1121                 /* call to all internal interfaces */
1122                 p = e_ext.interfaces;
1123                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1124                 while(*p)
1125                 {
1126                         ifname[0] = '\0';
1127                         while(*p!=',' && *p!='\0')
1128                                 if (*p > ' ')
1129                                         SCCAT(ifname, *p++);
1130                         if (*p == ',')
1131                                 p++;
1132                         /* found interface */
1133                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
1134                         /* hunt for mISDNport and create Port */
1135                         mISDNport = hunt_port(ifname, &channel);
1136                         if (!mISDNport)
1137                         {
1138                                 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
1139                                 add_trace("interface", NULL, "%s", ifname);
1140                                 end_trace();
1141                                 continue;
1142                         }
1143                         /* creating INTERNAL port */
1144                         SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1145                         port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force);
1146                         if (!port)
1147                                 FATAL("No memory for DSS1 Port instance\n");
1148                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
1149                         memset(&dialinginfo, 0, sizeof(dialinginfo));
1150                         SCPY(dialinginfo.id, e_dialinginfo.id);
1151                         dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1152                         dialinginfo.ntype = e_dialinginfo.ntype;
1153                         /* create port_list relation */
1154                         portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1155                         if (!portlist)
1156                         {
1157                                 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1158                                 delete port;
1159                                 goto check_anycall_intern;
1160                         }
1161                         /* directory.list */
1162                         if (e_callerinfo.id[0] && (e_ext.centrex || e_ext.display_name))
1163                         {
1164                                 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
1165                                 if (dirname)
1166                                         SCPY(e_callerinfo.name, dirname);
1167                         }
1168 //                      dss1 = (class Pdss1 *)port;
1169                         /* message */
1170 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1171                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1172                         memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1173                         memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1174                         memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1175                         memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1176 //terminal                      SCPY(message->param.setup.from_terminal, e_ext.number);
1177 //terminal                      if (e_dialinginfo.id)
1178 //terminal                              SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1179                         /* handle restricted caller ids */
1180                         apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1181                         apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1182                         /* display callerid if desired for extension */
1183                         SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1184 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
1185                         /* use cnip, if enabld */
1186                         if (!e_ext.centrex)
1187                                 message->param.setup.callerinfo.name[0] = '\0';
1188                         /* screen clip if prefix is required */
1189                         if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0])
1190                         {
1191                                 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
1192                                 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype));
1193                                 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1194                         }
1195                         /* use internal caller id */
1196                         if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
1197                         {
1198                                 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
1199                                 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
1200                         }
1201                         message_put(message);
1202                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1203                         anycall = 1;
1204                 }
1205
1206                 /* string from parallel call forward (cfp) */
1207                 p = e_ext.cfp;
1208                 if (*p)
1209                 {
1210                         if (e_ext.anon_ignore && e_callerinfo.id[0])
1211                         {
1212                                 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1213                         }
1214                 }
1215
1216                 vbox_only: /* entry point for answering machine only */
1217                 cfu_only: /* entry point for cfu */
1218                 cfb_only: /* entry point for cfb */
1219                 cfnr_only: /* entry point for cfnr */
1220                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1221 //              i=0;
1222                 while(*p)
1223                 {
1224                         earlyb = 0;
1225                         /* only if vbox should be dialed, and terminal is given */
1226                         if (!strcmp(p, "vbox") && e_ext.number[0])
1227                         {
1228                                 /* go to the end of p */
1229                                 p += strlen(p);
1230
1231                                 /* answering vbox call */
1232                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1233                                 /* alloc port */
1234                                 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1235                                         FATAL("No memory for VBOX Port instance\n");
1236                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1237                                 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1238                         } else
1239                         {
1240                                 cfp[0] = '\0';
1241                                 while(*p!=',' && *p!='\0')
1242                                         SCCAT(cfp, *p++);
1243                                 if (*p == ',')
1244                                         p++;
1245                                 /* external call */
1246                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1247                                 /* hunt for mISDNport and create Port */
1248                                 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1249                                 if (mISDNport)
1250                                 {
1251                                         /* creating EXTERNAL port*/
1252                                         SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1253                                         if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1254                                                 FATAL("No memory for DSS1 Port instance\n");
1255                                         earlyb = mISDNport->earlyb;
1256                                 } else
1257                                 {
1258                                         port = NULL;
1259                                         trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1260                                         add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1261                                         end_trace();
1262                                 }
1263                         }
1264                         if (!port)
1265                         {
1266                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1267                                 goto check_anycall_intern;
1268                         }
1269                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1270                         memset(&dialinginfo, 0, sizeof(dialinginfo));
1271                         SCPY(dialinginfo.id, cfp);
1272                         dialinginfo.itype = INFO_ITYPE_ISDN;
1273                         dialinginfo.ntype = e_dialinginfo.ntype;
1274                         portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1275                         if (!portlist)
1276                         {
1277                                 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1278                                 delete port;
1279                                 goto check_anycall_intern;
1280                         }
1281 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1282                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1283                         memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1284                         memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1285                         memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1286                         /* if clip is hidden */
1287                         if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT)
1288                         {
1289                                 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1290                                 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1291                                 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1292                                 message->param.setup.callerinfo.present = e_ext.callerid_present;
1293                         }
1294                         memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1295 //terminal                      SCPY(message->param.setup.from_terminal, e_ext.number);
1296 //terminal                      if (e_dialinginfo.id)
1297 //terminal                              SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1298                                 /* handle restricted caller ids */
1299                         apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1300                         apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1301                         /* display callerid if desired for extension */
1302                         SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1303                         message_put(message);
1304                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1305                         anycall = 1;
1306                 }
1307
1308                 check_anycall_intern:
1309                 /* now we have all ports created */
1310                 if (!anycall)
1311                 {
1312                         trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1313                         end_trace();
1314                         if (!ea_endpoint->ep_join_id)
1315                                 break;
1316                         release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1317                         return; /* must exit here */
1318                 }
1319                 break;
1320
1321                 /* *********************** external call */
1322                 default:
1323                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1324                 /* call to extenal interfaces */
1325                 p = e_dialinginfo.id;
1326                 do
1327                 {
1328                         number[0] = '\0';
1329                         while(*p!=',' && *p!='\0')
1330                                 SCCAT(number, *p++);
1331                         if (*p == ',')
1332                                 p++;
1333                         /* found number */
1334                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1335                         /* hunt for mISDNport and create Port */
1336                         /* hunt for mISDNport and create Port */
1337                         mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1338                         if (!mISDNport)
1339                         {
1340                                 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1341                                 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1342                                 end_trace();
1343                                 goto check_anycall_extern;
1344                         }
1345                         /* creating EXTERNAL port*/
1346                         SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1347                         if (!(port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force)))
1348                                 FATAL("No memory for DSS1 Port instance\n");
1349                         earlyb = mISDNport->earlyb;
1350                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1351                         memset(&dialinginfo, 0, sizeof(dialinginfo));
1352                         SCPY(dialinginfo.id, number);
1353                         dialinginfo.itype = INFO_ITYPE_ISDN;
1354                         dialinginfo.ntype = e_dialinginfo.ntype;
1355                         portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1356                         if (!portlist)
1357                         {
1358                                 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1359                                 delete port;
1360                                 goto check_anycall_extern;
1361                         }
1362 //                      dss1 = (class Pdss1 *)port;
1363 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1364                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1365                         memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1366                         SCPY(message->param.setup.dialinginfo.id, number);
1367                         memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1368                         memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1369                         memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1370 //terminal                      SCPY(message->param.setup.from_terminal, e_ext.number);
1371 //terminal                      if (e_dialinginfo.id)
1372 //terminal                              SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1373                                 /* handle restricted caller ids */
1374                         apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1375                         apply_callerid_restriction(e_ext.anon_ignore, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
1376                         /* display callerid if desired for extension */
1377                         SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
1378                         message_put(message);
1379                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1380                         anycall = 1;
1381                 } while(*p);
1382
1383                 check_anycall_extern:
1384                 /* now we have all ports created */
1385                 if (!anycall)
1386                 {
1387                         trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1388                         end_trace();
1389                         if (!ea_endpoint->ep_join_id)
1390                                 break;
1391                         release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1392                         return; /* must exit here */
1393                 }
1394                 break;
1395         }
1396
1397 }
1398
1399
1400 /* handler for endpoint
1401  */
1402
1403 extern int quit;
1404 int EndpointAppPBX::handler(void)
1405 {
1406         if (e_crypt_state!=CM_ST_NULL)
1407         {
1408                 cryptman_handler();
1409         }
1410
1411         /* process answering machine (play) handling */
1412         if (e_action)
1413         {
1414                 if (e_action->index == ACTION_VBOX_PLAY)
1415                         vbox_handler();
1416
1417                 /* process action timeout */
1418                 if (e_action_timeout)
1419                 if (now_d >= e_action_timeout)
1420                 {
1421                         if (e_state!=EPOINT_STATE_CONNECT)
1422                         {
1423                                 e_redial = 0;
1424                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1425                                 e_multipoint_cause = 0;
1426                                 e_multipoint_location = 0;
1427                                 new_state(EPOINT_STATE_IN_OVERLAP);
1428                                 e_join_pattern = 0;
1429                                 process_dialing();
1430                                 return(1); /* we must exit, because our endpoint might be gone */
1431                         } else
1432                                 e_action_timeout = 0;
1433                 }
1434         } else {
1435                 /* process action timeout */
1436                 if (e_match_timeout)
1437                 if (now_d >= e_match_timeout)
1438                 {
1439                         e_redial = 0;
1440                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1441                         process_dialing();
1442                         return(1); /* we must exit, because our endpoint might be gone */
1443                 }
1444         }
1445
1446
1447         /* process redialing (epoint redials to port) */
1448         if (e_redial)
1449         {
1450                 if (now_d >= e_redial)
1451                 {
1452                         e_redial = 0;
1453                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1454
1455                         new_state(EPOINT_STATE_OUT_SETUP);
1456                         /* call special setup routine */
1457                         out_setup();
1458
1459                         return(1);
1460                 }
1461         }
1462
1463         /* process powerdialing (epoint redials to epoint) */
1464         if (e_powerdialing > 0)
1465         {
1466                 if (now_d >= e_powerdialing)
1467                 {
1468                         e_powerdialing = -1; /* leave power dialing on */
1469                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1470
1471                         /* redial */
1472                         e_ruleset = ruleset_main;
1473                         if (e_ruleset)
1474                                 e_rule = e_ruleset->rule_first;
1475                         e_action = NULL;
1476                         new_state(EPOINT_STATE_IN_OVERLAP);
1477                         process_dialing();
1478                         return(1);
1479                 }
1480         }
1481
1482         /* process call forward no response */
1483         if (e_cfnr_release)
1484         {
1485                 struct port_list *portlist;
1486                 struct message *message;
1487
1488                 if (now >= e_cfnr_release)
1489                 {
1490                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1491                         e_cfnr_release = 0;
1492
1493                         /* release all ports */
1494                         while((portlist = ea_endpoint->ep_portlist))
1495                         {
1496                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1497                                 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1498                                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1499                                 message_put(message);
1500                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1501                                 ea_endpoint->free_portlist(portlist);
1502                         }
1503                         /* put on hold */
1504                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1505                         message->param.audiopath = CHANNEL_STATE_HOLD;
1506                         message_put(message);
1507                         /* indicate no patterns */
1508                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1509                         message_put(message);
1510                         /* set setup state, since we have no response from the new join */
1511                         new_state(EPOINT_STATE_OUT_SETUP);
1512                 }
1513         } else
1514         if (e_cfnr_call)
1515         {
1516                 if (now >= e_cfnr_call)
1517                 {
1518                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1519                         out_setup();
1520                         e_cfnr_call = 0;
1521                 }
1522         }
1523
1524         /* handle connection to user */
1525         if (e_state == EPOINT_STATE_IDLE)
1526         {
1527                 /* epoint is idle, check callback */
1528                 if (e_callback)
1529                 if (now_d >= e_callback)
1530                 {
1531                         e_callback = 0; /* done with callback */
1532                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1533                         new_state(EPOINT_STATE_OUT_SETUP);
1534                         out_setup();
1535                         return(1);
1536                 }
1537         }
1538
1539         /* check for password timeout */
1540         if (e_action)
1541         if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE)
1542         {
1543                 struct port_list *portlist;
1544
1545                 if (now >= e_password_timeout)
1546                 {
1547                         e_ruleset = ruleset_main;
1548                         if (e_ruleset)
1549                                 e_rule = e_ruleset->rule_first;
1550                         e_action = NULL;
1551                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1552                         trace_header("PASSWORD timeout", DIRECTION_NONE);
1553                         end_trace();
1554                         e_connectedmode = 0;
1555                         e_dtmf = 0;
1556                         new_state(EPOINT_STATE_OUT_DISCONNECT);
1557                         portlist = ea_endpoint->ep_portlist;
1558                         if (portlist)
1559                         {
1560                                 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1561                                 set_tone(portlist, "cause_10");
1562                         }
1563                         return(1);
1564                 }
1565         }
1566  
1567         return(0);
1568 }
1569
1570
1571 /* doing a hookflash */
1572 void EndpointAppPBX::hookflash(void)
1573 {
1574         class Port *port;
1575
1576         /* be sure that we are active */
1577         notify_active();
1578         e_tx_state = NOTIFY_STATE_ACTIVE;
1579
1580         trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1581         end_trace();
1582         if (ea_endpoint->ep_use > 1)
1583         {
1584                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1585                 return;
1586         }
1587         /* dialtone after pressing the hash key */
1588         process_hangup(e_join_cause, e_join_location);
1589         e_multipoint_cause = 0;
1590         e_multipoint_location = 0;
1591         port = find_port_id(ea_endpoint->ep_portlist->port_id);
1592         if (port)
1593         {
1594                 port->set_echotest(0);
1595         }
1596         if (ea_endpoint->ep_join_id)
1597         {
1598                 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1599         }
1600         e_ruleset = ruleset_main;
1601         if (e_ruleset)
1602                 e_rule = e_ruleset->rule_first;
1603         e_action = NULL;
1604         new_state(EPOINT_STATE_IN_OVERLAP);
1605         e_connectedmode = 1;
1606         SCPY(e_dialinginfo.id, e_ext.prefix);
1607         e_extdialing = e_dialinginfo.id;
1608         e_join_pattern = 0;
1609         if (e_dialinginfo.id[0])
1610         {
1611                 set_tone(ea_endpoint->ep_portlist, "dialing");
1612                 process_dialing();
1613         } else
1614         {
1615                 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1616         }
1617         e_dtmf_time = now;
1618         e_dtmf_last = '\0';
1619 }
1620
1621
1622 /* messages from port
1623  */
1624 /* port MESSAGE_SETUP */
1625 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1626 {
1627         struct message          *message;
1628         char                    buffer[256];
1629         int                     writeext;               /* flags need to write extension after modification */
1630         class Port              *port;
1631         struct interface        *interface;
1632
1633         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1634         
1635         portlist->port_type = param->setup.port_type;
1636         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
1637         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
1638         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
1639         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
1640         e_dtmf = param->setup.dtmf;
1641         /* screen incoming caller id */
1642         interface = interface_first;
1643         while(interface)
1644         {
1645                 if (!strcmp(e_callerinfo.interface, interface->name))
1646                 {
1647                         break;
1648                 }
1649                 interface = interface->next;
1650         }
1651         if (interface)
1652                 screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1653
1654         /* process extension */
1655         if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1656         {
1657                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1658                 /* port makes call from extension */
1659                 SCPY(e_callerinfo.extension, e_callerinfo.id);
1660                 SCPY(e_ext.number, e_callerinfo.extension);
1661                 SCPY(e_extension_interface, e_callerinfo.interface);
1662         } else
1663         {
1664                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1665         }
1666
1667         if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1668         {
1669                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1670
1671                 /* get extension's info about caller */
1672                 if (!read_extension(&e_ext, e_ext.number))
1673                 {
1674                         /* extension doesn't exist */
1675                         trace_header("EXTENSION (not created)", DIRECTION_IN);
1676                         add_trace("extension", NULL, "%s", e_ext.number);
1677                         end_trace();
1678                         message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1679                         new_state(EPOINT_STATE_OUT_DISCONNECT);
1680                         set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1681                         e_ext.number[0] = '\0'; /* no terminal */
1682                         return;
1683                 }
1684                 writeext = 0;
1685
1686                 /* put prefix (next) in front of e_dialinginfo.id */
1687                 if (e_ext.next[0])
1688                 {
1689                         SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1690                         SCPY(e_dialinginfo.id, buffer);
1691                         e_ext.next[0] = '\0';
1692                         writeext = 1;
1693                 } else if (e_ext.prefix[0])
1694                 {
1695                         SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1696                         SCPY(e_dialinginfo.id, buffer);
1697                 }
1698
1699                 /* screen caller id by extension's config */
1700                 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1701                 if (e_ext.name[0])
1702                         SCPY(e_callerinfo.name, e_ext.name);
1703                 /* use caller id (or if exist: id_next_call) for this call */
1704                 if (e_ext.id_next_call_present >= 0)
1705                 {
1706                         SCPY(e_callerinfo.id, e_ext.id_next_call);
1707                         /* if we restrict the pesentation */
1708                         if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1709                                 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1710                         else    e_callerinfo.present = e_ext.id_next_call_present;
1711                         e_callerinfo.ntype = e_ext.id_next_call_type;
1712                         e_ext.id_next_call_present = -1;
1713                         writeext = 1;
1714                 } else
1715                 {
1716                         SCPY(e_callerinfo.id, e_ext.callerid);
1717                         /* if we restrict the pesentation */
1718                         if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1719                                 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1720                         else    e_callerinfo.present = e_ext.callerid_present;
1721                         e_callerinfo.ntype = e_ext.callerid_type;
1722                 }
1723
1724                 /* extension is written */
1725                 if (writeext)
1726                         write_extension(&e_ext, e_ext.number);
1727
1728                 /* set volume of rx and tx */
1729                 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1730                 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
1731                 {
1732                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1733                         message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1734                         message->param.mISDNsignal.rxvol = e_ext.txvol;
1735                         message->param.mISDNsignal.txvol = e_ext.rxvol;
1736                         message_put(message);
1737                 }
1738
1739                 /* start recording if enabled */
1740                 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
1741                 {
1742                         /* check if we are a terminal */
1743                         if (e_ext.number[0] == '\0')
1744                                 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1745                         else
1746                         {
1747                                 port = find_port_id(portlist->port_id);
1748                                 if (port)
1749                                         port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1750                         }
1751                 }
1752         } else
1753         {
1754                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1755                 /* no terminal identification */
1756                 e_ext.number[0] = '\0';
1757                 e_extension_interface[0] = '\0';
1758                 memset(&e_ext, 0, sizeof(e_ext));
1759                 e_ext.rights = 4; /* right to dial internat */
1760         }
1761
1762         /* incoming call */
1763         e_ruleset = ruleset_main;
1764         if (e_ruleset)
1765                 e_rule = e_ruleset->rule_first;
1766         e_action = NULL;
1767         e_extdialing = e_dialinginfo.id;
1768         new_state(EPOINT_STATE_IN_SETUP);
1769         if (e_dialinginfo.id[0])
1770         {
1771                 set_tone(portlist, "dialing");
1772         } else
1773         {
1774                 if (e_ext.number[0])
1775                         set_tone(portlist, "dialpbx");
1776                 else
1777                         set_tone(portlist, "dialtone");
1778         }
1779         process_dialing();
1780         if (e_state == EPOINT_STATE_IN_SETUP)
1781         {
1782                 /* request MORE info, if not already at higher state */
1783                 new_state(EPOINT_STATE_IN_OVERLAP);
1784                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1785                 message_put(message);
1786                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1787         }
1788 }
1789
1790 /* port MESSAGE_INFORMATION */
1791 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1792 {
1793         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1794
1795         e_overlap = 1;
1796
1797         /* turn off dtmf detection, in case dtmf is sent with keypad information */
1798         if (e_dtmf)
1799         {
1800                 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1801                 end_trace();
1802                 e_dtmf = 0;
1803         }
1804
1805         /* if vbox_play is done, the information are just used as they come */
1806         if (e_action)
1807         if (e_action->index == ACTION_VBOX_PLAY)
1808         {
1809                 /* concat dialing string */
1810                 SCAT(e_dialinginfo.id, param->information.id);
1811                 process_dialing();
1812                 return;
1813         }
1814
1815         /* keypad when disconnect but in connected mode */
1816         if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode)
1817         {
1818                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1819                 /* processing keypad function */
1820                 if (param->information.id[0] == '0')
1821                 {
1822                         hookflash();
1823                 }
1824                 return;
1825         }
1826
1827         /* keypad when connected */
1828         if (e_state == EPOINT_STATE_CONNECT)
1829         {
1830                 if (e_ext.keypad)
1831                 {
1832                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1833                         /* processing keypad function */
1834                         if (param->information.id[0] == '0')
1835                         {
1836                                 hookflash();
1837                         }
1838                         if (param->information.id[0])
1839                                 keypad_function(param->information.id[0]);
1840                 } else
1841                 {
1842                         if (e_ext.number[0])
1843                                 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1844                         else
1845                                 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1846                         end_trace();
1847                 }
1848                 return;
1849         }
1850         if (e_state != EPOINT_STATE_IN_OVERLAP)
1851         {
1852                 if (e_ext.number[0])
1853                         trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1854                 else
1855                         trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1856                 end_trace();
1857                 return;
1858         }
1859         if (!param->information.id[0])
1860                 return;
1861         if (e_dialinginfo.id[0]=='\0' && !e_action)
1862         {
1863                 set_tone(portlist, "dialing");
1864         }
1865         if (e_action)
1866         if (e_action->index==ACTION_OUTDIAL
1867          || e_action->index==ACTION_EXTERNAL)
1868         {
1869                 if (!e_extdialing)
1870                         set_tone(portlist, "dialing");
1871                 else if (!e_extdialing[0])
1872                         set_tone(portlist, "dialing");
1873         }
1874         /* concat dialing string */
1875         SCAT(e_dialinginfo.id, param->information.id);
1876         process_dialing();
1877 }
1878
1879 /* port MESSAGE_DTMF */
1880 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1881 {
1882         /* only if dtmf detection is enabled */
1883         if (!e_dtmf)
1884         {
1885                 trace_header("DTMF (disabled)", DIRECTION_IN);
1886                 end_trace();
1887                 return;
1888         }
1889         trace_header("DTMF", DIRECTION_IN);
1890         add_trace("digit", NULL, "%c", param->dtmf);
1891         end_trace();
1892
1893 #if 0
1894 NOTE: vbox is now handled due to overlap state
1895         /* if vbox_play is done, the dtmf digits are just used as they come */
1896         if (e_action)
1897         if (e_action->index == ACTION_VBOX_PLAY)
1898         {
1899                 /* concat dialing string */
1900                 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1901                 {
1902                         e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1903                         e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1904                         process_dialing();
1905                 }
1906                 /* continue to process *X# sequences */
1907         }
1908 #endif
1909
1910         /* check for *X# sequence */
1911         if (e_state == EPOINT_STATE_CONNECT)
1912         {
1913                 if (e_dtmf_time+3 < now)
1914                 {
1915                         /* the last digit was too far in the past to be a sequence */
1916                         if (param->dtmf == '*')
1917                                 /* only start is allowed in the sequence */
1918                                 e_dtmf_last = '*';
1919                         else
1920                                 e_dtmf_last = '\0';
1921                 } else
1922                 {
1923                         /* we have a sequence of digits, see what we got */
1924                         if (param->dtmf == '*')
1925                                 e_dtmf_last = '*';
1926                         else if (param->dtmf>='0' && param->dtmf<='9')
1927                         {
1928                                 /* we need to have a star before we receive the digit of the sequence */
1929                                 if (e_dtmf_last == '*')
1930                                         e_dtmf_last = param->dtmf;
1931                         } else if (param->dtmf == '#')
1932                         {
1933                                 /* the hash key */
1934                                 if (e_dtmf_last>='0' && e_dtmf_last<='9')
1935                                 {
1936                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1937                                         if (e_dtmf_last == '0')
1938                                         {
1939                                                 hookflash();
1940                                                 return;
1941                                         }
1942                                         /* processing keypad function */
1943                                         if (param->dtmf)
1944                                                 keypad_function(e_dtmf_last);
1945                                         e_dtmf_last = '\0';
1946                                 }
1947                         }
1948                 }
1949
1950                 /* set last time of dtmf */
1951                 e_dtmf_time = now;
1952                 return;
1953         }
1954
1955         /* check for ## hookflash during dialing */
1956         if (e_action)
1957         if (e_action->index==ACTION_PASSWORD
1958          || e_action->index==ACTION_PASSWORD_WRITE)
1959                 goto password;
1960         if (param->dtmf=='#') /* current digit is '#' */
1961         {
1962                 if (e_state==EPOINT_STATE_IN_DISCONNECT
1963                  || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) /* when disconnected, just #. when dialing, ##. */
1964                 {
1965                         hookflash();
1966                         return;
1967                 } else
1968                 {
1969                         e_dtmf_time = now;
1970                         e_dtmf_last = '#';
1971                 }
1972         } else
1973         {
1974                 password:
1975                 e_dtmf_time = now;
1976                 e_dtmf_last = '\0';
1977         }
1978         
1979
1980         /* dialing using dtmf digit */
1981         if (e_state==EPOINT_STATE_IN_OVERLAP)// && e_state==e_connectedmode)
1982         {
1983                 if (e_dialinginfo.id[0]=='\0' && !e_action)
1984                 {
1985                         set_tone(portlist, "dialing");
1986                 }
1987                 /* concat dialing string */
1988                 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id))
1989                 {
1990                         e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1991                         e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1992                         process_dialing();
1993                 }
1994         }
1995 }
1996
1997 /* port MESSAGE_CRYPT */
1998 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1999 {
2000         /* send crypt response to cryptman */
2001         if (param->crypt.type == CR_MESSAGE_IND)
2002                 cryptman_msg2man(param->crypt.data, param->crypt.len);
2003         else
2004                 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2005 }
2006
2007 /* port MESSAGE_OVERLAP */
2008 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
2009 {
2010         struct message *message;
2011
2012         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2013
2014         /* signal to call tool */
2015         admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
2016
2017         if (e_dialing_queue[0] && portlist)
2018         {
2019                 /* send what we have not dialed yet, because we had no setup complete */
2020                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
2021                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2022                 SCPY(message->param.information.id, e_dialing_queue);
2023                 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2024                 message_put(message);
2025                 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2026                 e_dialing_queue[0] = '\0';
2027         }
2028         /* check if pattern is available */
2029         if (!ea_endpoint->ep_portlist->next && portlist->early_b) /* one port_list relation and tones available */
2030         {
2031                 /* indicate patterns */
2032                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2033                 message_put(message);
2034
2035                 /* connect audio, if not already */
2036                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2037                 message->param.audiopath = CHANNEL_STATE_CONNECT;
2038                 message_put(message);
2039         } else
2040         {
2041                 /* indicate no patterns */
2042                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2043                 message_put(message);
2044
2045                 /* disconnect audio, if not already */
2046                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2047                 message->param.audiopath = CHANNEL_STATE_HOLD;
2048                 message_put(message);
2049         }
2050         new_state(EPOINT_STATE_OUT_OVERLAP);
2051         /* if we are in a join */
2052         if (ea_endpoint->ep_join_id)
2053         { 
2054                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2055                 memcpy(&message->param, param, sizeof(union parameter));
2056                 message_put(message);
2057         }
2058 }
2059
2060 /* port MESSAGE_PROCEEDING */
2061 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2062 {
2063         struct message *message;
2064
2065         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2066
2067         /* signal to call tool */
2068         admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
2069
2070         e_state = EPOINT_STATE_OUT_PROCEEDING;
2071         /* check if pattern is availatle */
2072         if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2073         {
2074                 /* indicate patterns */
2075                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2076                 message_put(message);
2077
2078                 /* connect audio, if not already */
2079                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2080                 message->param.audiopath = CHANNEL_STATE_CONNECT;
2081                 message_put(message);
2082         } else
2083         {
2084                 /* indicate no patterns */
2085                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2086                 message_put(message);
2087
2088                 /* disconnect audio, if not already */
2089                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2090                 message->param.audiopath = CHANNEL_STATE_HOLD;
2091                 message_put(message);
2092         }
2093         /* if we are in a call */
2094         if (ea_endpoint->ep_join_id)
2095         { 
2096                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2097                 memcpy(&message->param, param, sizeof(union parameter));
2098                 message_put(message);
2099         }
2100 }
2101
2102 /* port MESSAGE_ALERTING */
2103 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
2104 {
2105         struct message *message;
2106
2107         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2108
2109         /* signal to call tool */
2110         admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
2111
2112         new_state(EPOINT_STATE_OUT_ALERTING);
2113         /* check if pattern is available */
2114         if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) /* one port_list relation and tones available */
2115         {
2116                 /* indicate patterns */
2117                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2118                 message_put(message);
2119
2120                 /* connect audio, if not already */
2121                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2122                 message->param.audiopath = CHANNEL_STATE_CONNECT;
2123                 message_put(message);
2124         } else
2125         {
2126                 /* indicate no patterns */
2127                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
2128                 message_put(message);
2129
2130                 /* disconnect audio, if not already */
2131                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2132                 message->param.audiopath = CHANNEL_STATE_HOLD;
2133                 message_put(message);
2134         }
2135         /* if we are in a call */
2136         if (ea_endpoint->ep_join_id)
2137         { 
2138                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2139                 memcpy(&message->param, param, sizeof(union parameter));
2140                 message_put(message);
2141         }
2142 }
2143
2144 /* port MESSAGE_CONNECT */
2145 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
2146 {
2147         struct message *message;
2148         char buffer[256];
2149         unsigned long port_id = portlist->port_id;
2150         struct port_list *tportlist;
2151         class Port *port;
2152         struct interface        *interface;
2153
2154         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2155
2156         /* signal to call tool */
2157         admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype), 0, 0, 0);
2158
2159         memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_connectinfo));
2160         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
2161         while(ea_endpoint->ep_portlist->next) /* as long as we have at least two ports */
2162         {
2163                 tportlist = ea_endpoint->ep_portlist;
2164                 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
2165                         tportlist = tportlist->next;
2166                 if (tportlist->port_id == port_id)
2167                         FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
2168                 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2169                 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
2170                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2171                 message_put(message);
2172                 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
2173                 ea_endpoint->free_portlist(tportlist);
2174         }
2175         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
2176
2177         e_start = now;
2178
2179         /* screen incoming connected id */
2180         interface = interface_first;
2181         while(interface)
2182         {
2183                 if (!strcmp(e_connectinfo.interface, interface->name))
2184                 {
2185                         break;
2186                 }
2187                 interface = interface->next;
2188         }
2189         if (interface)
2190                 screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
2191
2192         /* screen connected name */
2193         if (e_ext.name[0])
2194                 SCPY(e_connectinfo.name, e_ext.name);
2195
2196         /* add internal id to colp */
2197         SCPY(e_connectinfo.extension, e_ext.number);
2198
2199         /* we store the connected port number */
2200         SCPY(e_extension_interface, e_connectinfo.interface);
2201
2202         /* for internal and am calls, we get the extension's id */
2203         if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE)
2204         {
2205                 SCPY(e_connectinfo.id, e_ext.callerid);
2206                 SCPY(e_connectinfo.extension, e_ext.number);
2207                 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
2208                 e_connectinfo.ntype = e_ext.callerid_type;
2209                 e_connectinfo.present = e_ext.callerid_present;
2210         }
2211         if (portlist->port_type==PORT_TYPE_VBOX_OUT)
2212         {
2213                 e_connectinfo.itype = INFO_ITYPE_VBOX;
2214                 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2215         }
2216
2217         new_state(EPOINT_STATE_CONNECT);
2218
2219         /* set volume of rx and tx */
2220         if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2221         {
2222                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2223                 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2224                 message->param.mISDNsignal.rxvol = e_ext.txvol;
2225                 message->param.mISDNsignal.txvol = e_ext.rxvol;
2226                 message_put(message);
2227         }
2228
2229         e_cfnr_call = e_cfnr_release = 0;
2230         if (e_ext.number[0])
2231                 e_dtmf = 1; /* allow dtmf */
2232
2233         /* modify colp */
2234         /* other calls with no caller id (or not available for the extension) and force colp */
2235         if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE)
2236         {
2237                 e_connectinfo.present = INFO_PRESENT_NOTAVAIL;
2238                 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT) /* external extension answered */
2239                 {
2240                         port = find_port_id(portlist->port_id);
2241                         if (port)
2242                         {
2243                                 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype));
2244                                 e_connectinfo.present = INFO_PRESENT_ALLOWED;
2245                         }
2246                 }
2247         }
2248
2249         /* send connect to join */
2250         if (ea_endpoint->ep_join_id)
2251         {
2252                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2253                 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
2254                 message_put(message);
2255
2256                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2257                 message->param.audiopath = CHANNEL_STATE_CONNECT;
2258                 message_put(message);
2259         } else if (!e_adminid)
2260         {
2261                 /* callback */
2262                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
2263                 SCPY(e_ext.number, e_cbcaller);
2264                 new_state(EPOINT_STATE_IN_OVERLAP);
2265                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2266
2267                 /* get extension's info about terminal */
2268                 if (!read_extension(&e_ext, e_ext.number))
2269                 {
2270                         /* extension doesn't exist */
2271                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
2272                         message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
2273                         new_state(EPOINT_STATE_OUT_DISCONNECT);
2274                         set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
2275                         return;
2276                 }
2277
2278                 /* put prefix in front of e_cbdialing */
2279                 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
2280                 SCPY(e_dialinginfo.id, buffer);
2281                 e_dialinginfo.itype = INFO_ITYPE_ISDN;
2282                 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
2283
2284                 /* use caller id (or if exist: id_next_call) for this call */
2285                 e_callerinfo.screen = INFO_SCREEN_NETWORK;
2286                 SCPY(e_callerinfo.extension, e_ext.number);
2287                 if (e_ext.id_next_call_present >= 0)
2288                 {
2289                         SCPY(e_callerinfo.id, e_ext.id_next_call);
2290                         e_callerinfo.present = e_ext.id_next_call_present;
2291                         e_callerinfo.ntype = e_ext.id_next_call_type;
2292                         e_ext.id_next_call_present = -1;
2293                         /* extension is written */
2294                         write_extension(&e_ext, e_ext.number);
2295                 } else
2296                 {
2297                         SCPY(e_callerinfo.id, e_ext.callerid);
2298                         e_callerinfo.present = e_ext.callerid_present;
2299                         e_callerinfo.ntype = e_ext.callerid_type;
2300                 }
2301
2302                 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2303                 e_dtmf = 1;
2304
2305                 /* check if caller id is NOT authenticated */
2306                 if (!parse_callbackauth(e_ext.number, &e_callbackinfo))
2307                 {
2308                         /* make call state to enter password */
2309                         new_state(EPOINT_STATE_IN_OVERLAP);
2310                         e_action = &action_password_write;
2311                         e_match_timeout = 0;
2312                         e_match_to_action = NULL;
2313                         e_dialinginfo.id[0] = '\0';
2314                         e_extdialing = strchr(e_dialinginfo.id, '\0');
2315                         e_password_timeout = now+20;
2316                         process_dialing();
2317                 } else
2318                 {
2319                         /* incoming call (callback) */
2320                         e_ruleset = ruleset_main;
2321                         if (e_ruleset)
2322                                 e_rule = e_ruleset->rule_first;
2323                         e_action = NULL;
2324                         e_extdialing = e_dialinginfo.id;
2325                         if (e_dialinginfo.id[0])
2326                         {
2327                                 set_tone(portlist, "dialing");
2328                                 process_dialing();
2329                         } else
2330                         {
2331                                 set_tone(portlist, "dialpbx");
2332                         }
2333                 }
2334         } else /* testcall */
2335         {
2336                 set_tone(portlist, "hold");
2337         }
2338
2339         /* start recording if enabled, not when answering machine answers */
2340         if (param->connectinfo.itype!=INFO_ITYPE_VBOX && e_ext.number[0] && e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO))
2341         {
2342                 /* check if we are a terminal */
2343                 if (e_ext.number[0] == '\0')
2344                         PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2345                 else
2346                 {
2347                         port = find_port_id(portlist->port_id);
2348                         if (port)
2349                                 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2350                 }
2351         }
2352 }
2353
2354 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2355 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2356 {
2357         struct message  *message;
2358         char            buffer[256];
2359         unsigned long   port_id = portlist->port_id;
2360         int             cause,
2361                         location;
2362
2363         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2364
2365         /* signal to call tool */
2366         admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2367
2368 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2369         if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE)// || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2370         {
2371                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2372                 return;
2373         }
2374
2375         /* collect cause */
2376         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current multipoint cause %d location %d, received cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2377         collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2378         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2379
2380         /* check if we have more than one portlist relation and we just ignore the disconnect */
2381         if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next)
2382         {
2383                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2384                 portlist = ea_endpoint->ep_portlist;
2385                 while(portlist)
2386                 {
2387                         if (portlist->port_id == port_id)
2388                                 break;
2389                         portlist = portlist->next;
2390                 }
2391                 if (!portlist)
2392                         FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2393                 if (message_type != MESSAGE_RELEASE)
2394                 {
2395                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2396                         message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2397                         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2398                         message_put(message);
2399                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2400                 }
2401                 ea_endpoint->free_portlist(portlist);
2402                 return; /* one relation removed */ 
2403         }
2404         if (e_state == EPOINT_STATE_CONNECT)
2405         {
2406                 /* use cause from port after connect */
2407                 cause = param->disconnectinfo.cause;
2408                 location = param->disconnectinfo.location;
2409         } else
2410         {
2411                 /* use multipoint cause if no connect yet */
2412                 if (e_multipoint_cause)
2413                 {
2414                         cause = e_multipoint_cause;
2415                         location = e_multipoint_location;
2416                 } else
2417                 {
2418                         cause = CAUSE_NOUSER;
2419                         location = LOCATION_PRIVATE_LOCAL;
2420                 }
2421         }
2422
2423         e_cfnr_call = e_cfnr_release = 0;
2424
2425         /* process hangup */
2426         process_hangup(e_join_cause, e_join_location);
2427         e_multipoint_cause = 0;
2428         e_multipoint_location = 0;
2429
2430         if (message_type == MESSAGE_DISCONNECT)
2431         {
2432                 /* tone to disconnected end */
2433                 SPRINT(buffer, "cause_%02x", cause);
2434                 if (ea_endpoint->ep_portlist)
2435                         set_tone(ea_endpoint->ep_portlist, buffer);
2436
2437                 new_state(EPOINT_STATE_IN_DISCONNECT);
2438         }
2439
2440         if (ea_endpoint->ep_join_id)
2441         {
2442                 int haspatterns = 0;
2443                 /* check if pattern is available */
2444                 if (ea_endpoint->ep_portlist)
2445                 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2446                 if (joinpbx_countrelations(ea_endpoint->ep_join_id)==2 // we must count relations, in order not to disturb the conference ; NOTE: asterisk always counts two, since it is a point to point call 
2447                  && message_type != MESSAGE_RELEASE) // if we release, we are done
2448                         haspatterns = 1;
2449                 if (haspatterns)
2450                 {
2451                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2452                         /* indicate patterns */
2453                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2454                         message_put(message);
2455                         /* connect audio, if not already */
2456                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2457                         message->param.audiopath = CHANNEL_STATE_CONNECT;
2458                         message_put(message);
2459                         /* send disconnect */
2460                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2461                         memcpy(&message->param, param, sizeof(union parameter));
2462                         message_put(message);
2463                         /* disable encryption if disconnected */
2464 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2465                         if (e_crypt_state)
2466                                 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2467                         return;
2468                 } else
2469                 {
2470                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2471                 }
2472         }
2473         if (message_type == MESSAGE_RELEASE)
2474                 ea_endpoint->free_portlist(portlist);
2475         release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2476         return; /* must exit here */
2477 }
2478
2479 /* port MESSAGE_TIMEOUT */
2480 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2481 {
2482         char cause[16];
2483
2484         trace_header("TIMEOUT", DIRECTION_IN);
2485         message_type = MESSAGE_DISCONNECT;
2486         switch (param->state)
2487         {
2488                 case PORT_STATE_OUT_SETUP:
2489                 case PORT_STATE_OUT_OVERLAP:
2490                 add_trace("state", NULL, "outgoing setup/dialing");
2491                 end_trace();
2492                 /* no user responding */
2493                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2494                 return; /* must exit here */
2495
2496                 case PORT_STATE_IN_SETUP:
2497                 case PORT_STATE_IN_OVERLAP:
2498                 add_trace("state", NULL, "incoming setup/dialing");
2499                 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2500                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2501                 break;
2502
2503                 case PORT_STATE_OUT_PROCEEDING:
2504                 add_trace("state", NULL, "outgoing proceeding");
2505                 end_trace();
2506                 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2507                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2508                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2509                 return; /* must exit here */
2510
2511                 case PORT_STATE_IN_PROCEEDING:
2512                 add_trace("state", NULL, "incoming proceeding");
2513                 param->disconnectinfo.cause = CAUSE_NOUSER;
2514                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2515                 break;
2516
2517                 case PORT_STATE_OUT_ALERTING:
2518                 add_trace("state", NULL, "outgoing alerting");
2519                 end_trace();
2520                 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2521                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2522                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2523                 return; /* must exit here */
2524
2525                 case PORT_STATE_CONNECT:
2526                 add_trace("state", NULL, "connect");
2527                 end_trace();
2528                 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2529                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2530                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2531                 return; /* must exit here */
2532
2533                 case PORT_STATE_IN_ALERTING:
2534                 add_trace("state", NULL, "incoming alerting");
2535                 param->disconnectinfo.cause = CAUSE_NOANSWER;
2536                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2537                 break;
2538
2539                 case PORT_STATE_IN_DISCONNECT:
2540                 case PORT_STATE_OUT_DISCONNECT:
2541                 add_trace("state", NULL, "disconnect");
2542                 end_trace();
2543                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2544                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2545                 return; /* must exit here */
2546
2547                 default:
2548                 param->disconnectinfo.cause = 31; /* normal unspecified */
2549                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2550         }
2551         end_trace();
2552         /* release call, disconnect isdn */
2553         e_join_pattern = 0;
2554         new_state(EPOINT_STATE_OUT_DISCONNECT);
2555         SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2556         SCPY(e_tone, cause);
2557         while(portlist)
2558         {
2559                 set_tone(portlist, cause);
2560                 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2561                 portlist = portlist->next;
2562         }
2563         release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2564 }
2565
2566 /* port MESSAGE_NOTIFY */
2567 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2568 {
2569         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2570
2571         struct message *message;
2572         char *logtext = "";
2573         char buffer[64];
2574
2575         /* signal to call tool */
2576         admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype), 0, 0, param->notifyinfo.notify);
2577         if (param->notifyinfo.notify)
2578         {
2579                 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2580         }
2581
2582         /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2583         if (param->notifyinfo.local) switch(param->notifyinfo.notify)
2584         {
2585                 case INFO_NOTIFY_REMOTE_HOLD:
2586                 case INFO_NOTIFY_USER_SUSPENDED:
2587                 /* tell call about it */
2588                 if (ea_endpoint->ep_join_id)
2589                 {
2590                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2591                         message->param.audiopath = CHANNEL_STATE_HOLD;
2592                         message_put(message);
2593                 }
2594                 break;
2595
2596                 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2597                 case INFO_NOTIFY_USER_RESUMED:
2598                 /* set volume of rx and tx */
2599                 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2600                 if (e_ext.txvol!=256 || e_ext.rxvol!=256)
2601                 if (portlist)
2602                 {
2603                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2604                         message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2605                         message->param.mISDNsignal.rxvol = e_ext.txvol;
2606                         message->param.mISDNsignal.txvol = e_ext.rxvol;
2607                         message_put(message);
2608                 }
2609                 /* set current tone */
2610                 if (portlist)
2611                         set_tone(portlist, e_tone);
2612                 /* tell call about it */
2613                 if (ea_endpoint->ep_join_id)
2614                 {
2615                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2616                         message->param.audiopath = CHANNEL_STATE_CONNECT;
2617                         message_put(message);
2618                 }
2619                 break;
2620         }
2621
2622         /* get name of notify */
2623         switch(param->notifyinfo.notify)
2624         {
2625                 case 0x00:
2626                 logtext = "NULL";
2627                 break;
2628                 case 0x80:
2629                 logtext = "USER_SUSPENDED";
2630                 break;
2631                 case 0x82:
2632                 logtext = "BEARER_SERVICE_CHANGED";
2633                 break;
2634                 case 0x81:
2635                 logtext = "USER_RESUMED";
2636                 break;
2637                 case 0xc2:
2638                 logtext = "CONFERENCE_ESTABLISHED";
2639                 break;
2640                 case 0xc3:
2641                 logtext = "CONFERENCE_DISCONNECTED";
2642                 break;
2643                 case 0xc4:
2644                 logtext = "OTHER_PARTY_ADDED";
2645                 break;
2646                 case 0xc5:
2647                 logtext = "ISOLATED";
2648                 break;
2649                 case 0xc6:
2650                 logtext = "REATTACHED";
2651                 break;
2652                 case 0xc7:
2653                 logtext = "OTHER_PARTY_ISOLATED";
2654                 break;
2655                 case 0xc8:
2656                 logtext = "OTHER_PARTY_REATTACHED";
2657                 break;
2658                 case 0xc9:
2659                 logtext = "OTHER_PARTY_SPLIT";
2660                 break;
2661                 case 0xca:
2662                 logtext = "OTHER_PARTY_DISCONNECTED";
2663                 break;
2664                 case 0xcb:
2665                 logtext = "CONFERENCE_FLOATING";
2666                 break;
2667                 case 0xcc:
2668                 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2669                 break;
2670                 case 0xcf:
2671                 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2672                 break;
2673                 case 0xe0:
2674                 logtext = "CALL_IS_A_WAITING_CALL";
2675                 break;
2676                 case 0xe8:
2677                 logtext = "DIVERSION_ACTIVATED";
2678                 break;
2679                 case 0xe9:
2680                 logtext = "RESERVED_CT_1";
2681                 break;
2682                 case 0xea:
2683                 logtext = "RESERVED_CT_2";
2684                 break;
2685                 case 0xee:
2686                 logtext = "REVERSE_CHARGING";
2687                 break;
2688                 case 0xf9:
2689                 logtext = "REMOTE_HOLD";
2690                 break;
2691                 case 0xfa:
2692                 logtext = "REMOTE_RETRIEVAL";
2693                 break;
2694                 case 0xfb:
2695                 logtext = "CALL_IS_DIVERTING";
2696                 break;
2697                 default:
2698                 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2699                 logtext = buffer;
2700
2701         }
2702
2703         /* notify call if available */
2704         if (ea_endpoint->ep_join_id)
2705         {
2706                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2707                 memcpy(&message->param.notifyinfo, &param->notifyinfo, sizeof(struct notify_info));
2708                 message_put(message);
2709         }
2710
2711 }
2712
2713 /* port MESSAGE_FACILITY */
2714 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2715 {
2716         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2717
2718         struct message *message;
2719
2720         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2721         memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
2722         message_put(message);
2723 }
2724
2725 /* port MESSAGE_SUSPEND */
2726 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2727 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2728 {
2729         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2730
2731         /* epoint is now parked */
2732         ea_endpoint->ep_park = 1;
2733         memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2734         ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2735
2736         /* remove port relation */
2737         ea_endpoint->free_portlist(portlist);
2738 }
2739
2740 /* port MESSAGE_RESUME */
2741 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2742 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2743 {
2744         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2745
2746         /* epoint is now resumed */
2747         ea_endpoint->ep_park = 0;
2748
2749 }
2750
2751
2752 /* port sends message to the endpoint
2753  */
2754 void EndpointAppPBX::ea_message_port(unsigned long port_id, int message_type, union parameter *param)
2755 {
2756         struct port_list *portlist;
2757         struct message *message;
2758
2759         portlist = ea_endpoint->ep_portlist;
2760         while(portlist)
2761         {
2762                 if (port_id == portlist->port_id)
2763                         break;
2764                 portlist = portlist->next;
2765         }
2766         if (!portlist)
2767         {
2768                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) warning: port is not related to this endpoint. This may happen, if port has been released after the message was created.\n", ea_endpoint->ep_serial);
2769                 return;
2770         }
2771
2772 //      PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2773         switch(message_type)
2774         {
2775                 case MESSAGE_DATA: /* data from port */
2776                 /* check if there is a call */
2777                 if (!ea_endpoint->ep_join_id)
2778                         break;
2779                 /* continue if only one portlist */
2780                 if (ea_endpoint->ep_portlist->next != NULL)
2781                         break;
2782                 /* forward message */
2783                 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);  
2784                 break;
2785
2786                 case MESSAGE_TONE_EOF: /* tone is end of file */
2787                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2788                 if (e_action)
2789                 {
2790                         if (e_action->index == ACTION_VBOX_PLAY)
2791                         {
2792                                 vbox_message_eof();
2793                         }
2794                         if (e_action->index == ACTION_EFI)
2795                         {
2796                                 efi_message_eof();
2797                         }
2798                 }
2799                 break;
2800
2801                 case MESSAGE_TONE_COUNTER: /* counter info received */
2802                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received counter information: %d / %d seconds after start of tone.\n", ea_endpoint->ep_serial, param->counter.current, param->counter.max);
2803                 if (e_action)
2804                 if (e_action->index == ACTION_VBOX_PLAY)
2805                 {
2806                         e_vbox_counter = param->counter.current;
2807                         if (param->counter.max >= 0)
2808                                 e_vbox_counter_max = param->counter.max;
2809                 }
2810                 break;
2811
2812                 /* PORT sends SETUP message */
2813                 case MESSAGE_SETUP:
2814                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call from callerid=%s, dialing=%s\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
2815                 if (e_state!=EPOINT_STATE_IDLE)
2816                 {
2817                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2818                         break;
2819                 }
2820                 port_setup(portlist, message_type, param);
2821                 break;
2822
2823                 /* PORT sends INFORMATION message */
2824                 case MESSAGE_INFORMATION: /* additional digits received */
2825                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call dialing more=%s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->information.id, e_ext.number, e_callerinfo.id);
2826                 port_information(portlist, message_type, param);
2827                 break;
2828
2829                 /* PORT sends FACILITY message */
2830                 case MESSAGE_FACILITY:
2831                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2832                 port_facility(portlist, message_type, param);
2833                 break;
2834
2835                 /* PORT sends DTMF message */
2836                 case MESSAGE_DTMF: /* dtmf digits received */
2837                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
2838                 port_dtmf(portlist, message_type, param);
2839                 break;
2840
2841                 /* PORT sends CRYPT message */
2842                 case MESSAGE_CRYPT: /* crypt response received */
2843                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2844                 port_crypt(portlist, message_type, param);
2845                 break;
2846
2847                 /* PORT sends MORE message */
2848                 case MESSAGE_OVERLAP:
2849                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is accepted [overlap dialing] (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2850                 if (e_state != EPOINT_STATE_OUT_SETUP)
2851                 {
2852                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2853                         break;
2854                 }
2855                 port_overlap(portlist, message_type, param);
2856                 break;
2857
2858                 /* PORT sends PROCEEDING message */
2859                 case MESSAGE_PROCEEDING: /* port is proceeding */
2860                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is proceeding (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2861                 if (e_state!=EPOINT_STATE_OUT_SETUP
2862                  && e_state!=EPOINT_STATE_OUT_OVERLAP)
2863                 {
2864                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in overlap state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2865                         break;
2866                 }
2867                 port_proceeding(portlist, message_type, param);
2868                 break;
2869
2870                 /* PORT sends ALERTING message */
2871                 case MESSAGE_ALERTING:
2872                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call is ringing (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2873                 if (e_state!=EPOINT_STATE_OUT_SETUP
2874                  && e_state!=EPOINT_STATE_OUT_OVERLAP
2875                  && e_state!=EPOINT_STATE_OUT_PROCEEDING)
2876                 {
2877                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state (for port_list: another portlist might have changed the state already).\n", ea_endpoint->ep_serial);
2878                         break;
2879                 }
2880                 port_alerting(portlist, message_type, param);
2881                 break;
2882
2883                 /* PORT sends CONNECT message */
2884                 case MESSAGE_CONNECT:
2885                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) outgoing call connected to %s (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_connectinfo.id, e_ext.number, e_callerinfo.id);
2886                 if (e_state!=EPOINT_STATE_OUT_SETUP
2887                  && e_state!=EPOINT_STATE_OUT_OVERLAP
2888                  && e_state!=EPOINT_STATE_OUT_PROCEEDING
2889                  && e_state!=EPOINT_STATE_OUT_ALERTING)
2890                 {
2891                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2892                         break;
2893                 }
2894                 port_connect(portlist, message_type, param);
2895                 break;
2896
2897                 /* PORT sends DISCONNECT message */
2898                 case MESSAGE_DISCONNECT: /* port is disconnected */
2899                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call disconnect with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2900                 port_disconnect_release(portlist, message_type, param);
2901                 break;
2902
2903                 /* PORT sends a RELEASE message */
2904                 case MESSAGE_RELEASE: /* port releases */
2905                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) release with cause=%d location=%d (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->disconnectinfo.cause, param->disconnectinfo.location, e_ext.number, e_callerinfo.id);
2906                 /* portlist is release at port_disconnect_release, thanx Paul */
2907                 port_disconnect_release(portlist, message_type, param);
2908                 break;
2909
2910                 /* PORT sends a TIMEOUT message */
2911                 case MESSAGE_TIMEOUT:
2912                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received timeout (state=%d).\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->state);
2913                 port_timeout(portlist, message_type, param);
2914                 break; /* release */
2915
2916                 /* PORT sends a NOTIFY message */
2917                 case MESSAGE_NOTIFY:
2918                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2919                 port_notify(portlist, message_type, param);
2920                 break;
2921
2922                 /* PORT sends a SUSPEND message */
2923                 case MESSAGE_SUSPEND:
2924                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received suspend.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2925                 port_suspend(portlist, message_type, param);
2926                 break; /* suspend */
2927
2928                 /* PORT sends a RESUME message */
2929                 case MESSAGE_RESUME:
2930                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received resume.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2931                 port_resume(portlist, message_type, param);
2932                 break;
2933
2934 #if 0
2935                 /* port assigns bchannel */
2936                 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2937                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel message %d from port.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
2938                 /* only one port is expected to be connected to bchannel */
2939                 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2940                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2941                 break;
2942 #endif
2943
2944
2945                 default:
2946                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
2947         }
2948
2949         /* Note: this endpoint may be destroyed, so we MUST return */
2950 }
2951
2952
2953 /* messages from join
2954  */
2955 /* join MESSAGE_CRYPT */
2956 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2957 {
2958         switch(param->crypt.type)
2959         {
2960                 /* message from remote port to "crypt manager" */
2961                 case CU_ACTK_REQ:           /* activate key-exchange */
2962                 case CU_ACTS_REQ:            /* activate shared key */
2963                 case CU_DACT_REQ:          /* deactivate */
2964                 case CU_INFO_REQ:         /* request last info message */
2965                 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2966                 break;
2967
2968                 /* message from "crypt manager" to user */
2969                 case CU_ACTK_CONF:          /* key-echange done */
2970                 case CU_ACTS_CONF:          /* shared key done */
2971                 case CU_DACT_CONF:           /* deactivated */
2972                 case CU_DACT_IND:           /* deactivated */
2973                 case CU_ERROR_IND:         /* receive error message */
2974                 case CU_INFO_IND:         /* receive info message */
2975                 case CU_INFO_CONF:         /* receive info message */
2976                 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2977                 break;
2978
2979                 default:
2980                 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
2981         }
2982 }
2983
2984 /* join MESSAGE_INFORMATION */
2985 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2986 {
2987         struct message *message;
2988
2989         e_overlap = 1;
2990
2991         while(portlist)
2992         {
2993                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2994                 memcpy(&message->param.information, &param->information, sizeof(struct dialing_info));
2995                 message_put(message);
2996                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2997                 portlist = portlist->next;
2998         }
2999 }
3000
3001 /* join MESSAGE_FACILITY */
3002 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
3003 {
3004         struct message *message;
3005
3006         if (!e_ext.facility)
3007         {
3008                 return;
3009         }
3010
3011         while(portlist)
3012         {
3013                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
3014                 memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
3015                 message_put(message);
3016                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3017                 portlist = portlist->next;
3018         }
3019 }
3020
3021 /* join MESSAGE_MORE */
3022 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
3023 {
3024         struct message *message;
3025
3026         new_state(EPOINT_STATE_IN_OVERLAP);
3027         
3028         /* own dialtone */
3029         if (e_join_pattern && e_ext.own_setup)
3030         {
3031                 /* disconnect audio */
3032                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3033                 message->param.audiopath = CHANNEL_STATE_HOLD;
3034                 message_put(message);
3035         }
3036         if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3037         {
3038                         set_tone(portlist, "dialtone");
3039                         return;
3040         }
3041         if (e_ext.number[0])
3042                 set_tone(portlist, "dialpbx");
3043         else
3044                 set_tone(portlist, "dialtone");
3045 }
3046
3047 /* join MESSAGE_PROCEEDING */
3048 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3049 {
3050         struct message *message;
3051
3052         new_state(EPOINT_STATE_IN_PROCEEDING);
3053
3054         /* own proceeding tone */
3055         if (e_join_pattern)
3056         {
3057                 /* connect / disconnect audio */
3058                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3059                 if (e_ext.own_proceeding)
3060                         message->param.audiopath = CHANNEL_STATE_HOLD;
3061                 else
3062                         message->param.audiopath = CHANNEL_STATE_CONNECT;
3063                 message_put(message);
3064         }
3065 //                      UCPY(e_join_tone, "proceeding");
3066         if (portlist)
3067         {
3068                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3069                 message_put(message);
3070                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3071         }
3072         set_tone(portlist, "proceeding");
3073 }
3074
3075 /* join MESSAGE_ALERTING */
3076 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
3077 {
3078         struct message *message;
3079
3080         new_state(EPOINT_STATE_IN_ALERTING);
3081
3082         /* own alerting tone */
3083         if (e_join_pattern)
3084         {
3085                 /* connect / disconnect audio */
3086                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3087                 if (e_ext.own_alerting)
3088                         message->param.audiopath = CHANNEL_STATE_HOLD;
3089                 else
3090                         message->param.audiopath = CHANNEL_STATE_CONNECT;
3091                 message_put(message);
3092         }
3093         if (portlist)
3094         {
3095                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3096                 message_put(message);
3097                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3098         }
3099         if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3100         {
3101                 set_tone(portlist, "ringing");
3102                 return;
3103         }
3104         if (e_ext.number[0])
3105                 set_tone(portlist, "ringpbx");
3106         else
3107                 set_tone(portlist, "ringing");
3108 }
3109
3110 /* join MESSAGE_CONNECT */
3111 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3112 {
3113         struct message *message;
3114         struct interface        *interface;
3115
3116         new_state(EPOINT_STATE_CONNECT);
3117 //                      UCPY(e_join_tone, "");
3118         if (e_ext.number[0])
3119                 e_dtmf = 1; /* allow dtmf */
3120         e_powerdialing = 0;
3121         memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_callerinfo));
3122         if(portlist)
3123         {
3124                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3125                 memcpy(&message->param, param, sizeof(union parameter));
3126                 /* screen incoming caller id */
3127                 interface = interface_first;
3128                 while(interface)
3129                 {
3130                         if (!strcmp(e_connectinfo.interface, interface->name))
3131                         {
3132                                 break;
3133                         }
3134                         interface = interface->next;
3135                 }
3136                 if (interface)
3137                         screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3138                 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3139
3140                 /* screen clip if prefix is required */
3141                 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3142                 {
3143                         SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3144                         SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3145                         message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3146                 }
3147
3148                 /* use internal caller id */
3149                 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3150                 {
3151                         SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3152                         message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3153                 }
3154
3155                 /* handle restricted caller ids */
3156                 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3157                 /* display callerid if desired for extension */
3158                 SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
3159
3160                 /* use conp, if enabld */
3161                 if (!e_ext.centrex)
3162                         message->param.connectinfo.name[0] = '\0';
3163
3164                 /* send connect */
3165                 message_put(message);
3166                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3167         }
3168         set_tone(portlist, NULL);
3169         e_join_pattern = 0;
3170         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3171         message->param.audiopath = CHANNEL_STATE_CONNECT;
3172         message_put(message);
3173         e_start = now;
3174 }
3175
3176 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3177 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3178 {
3179         char cause[16];
3180         struct message *message;
3181         struct port_list *portlist = NULL;
3182
3183
3184         /* be sure that we are active */
3185         notify_active();
3186         e_tx_state = NOTIFY_STATE_ACTIVE;
3187
3188         /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3189         if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3190         {
3191                 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3192
3193                 /* set time for power dialing */
3194                 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3195                 e_powercount++;
3196
3197                 /* set redial tone */
3198                 if (ea_endpoint->ep_portlist)
3199                 {
3200                         e_join_pattern = 0;
3201                 }
3202                 set_tone(ea_endpoint->ep_portlist, "redial");
3203                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (int)e_powerdelay);
3204                 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3205                 if (e_state==EPOINT_STATE_IN_OVERLAP)
3206                 {
3207                         new_state(EPOINT_STATE_IN_PROCEEDING);
3208                         if (ea_endpoint->ep_portlist)
3209                         {
3210                                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3211                                 message_put(message);
3212                                 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3213                         }
3214 /* caused the error, that the first knock sound was not there */
3215 /*                                      set_tone(portlist, "proceeding"); */
3216                 }
3217                 /* send display of powerdialing */
3218                 if (e_ext.display_dialing)
3219                 {
3220                         portlist = ea_endpoint->ep_portlist;
3221                         while (portlist)
3222                         {
3223                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3224                                 if (e_powerlimit)
3225                                         SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3226                                 else
3227                                         SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3228                                 message_put(message);
3229                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3230                                 portlist = portlist->next;
3231                         }
3232                 }
3233                 return;
3234         }
3235
3236         /* set stop time */
3237         e_stop = now;
3238
3239         if ((e_state!=EPOINT_STATE_CONNECT
3240           && e_state!=EPOINT_STATE_OUT_DISCONNECT
3241           && e_state!=EPOINT_STATE_IN_OVERLAP
3242           && e_state!=EPOINT_STATE_IN_PROCEEDING
3243           && e_state!=EPOINT_STATE_IN_ALERTING)
3244          || !ea_endpoint->ep_portlist) /* or no port */
3245         {
3246                 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3247                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3248                 return; /* must exit here */
3249         }
3250         /* save cause */
3251         if (!e_join_cause)
3252         {
3253                 e_join_cause = param->disconnectinfo.cause;
3254                 e_join_location = param->disconnectinfo.location;
3255         }
3256
3257         /* on release we need the audio again! */
3258         if (message_type == MESSAGE_RELEASE)
3259         {
3260                 e_join_pattern = 0;
3261                 ea_endpoint->ep_join_id = 0;
3262         }
3263         /* disconnect and select tone */
3264         new_state(EPOINT_STATE_OUT_DISCONNECT);
3265         SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3266         /* if own_cause, we must release the join */
3267         if (e_ext.own_cause /* own cause */
3268          || !e_join_pattern) /* no patterns */
3269         {
3270                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have own cause or we have no patterns. (own_cause=%d pattern=%d)\n", ea_endpoint->ep_serial, e_ext.own_cause, e_join_pattern);
3271                 if (message_type != MESSAGE_RELEASE)
3272                         release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3273                 e_join_pattern = 0;
3274         } else /* else we enable audio */
3275         {
3276                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3277                 message->param.audiopath = CHANNEL_STATE_CONNECT;
3278                 message_put(message);
3279         }
3280         /* send disconnect message */
3281         SCPY(e_tone, cause);
3282         portlist = ea_endpoint->ep_portlist;
3283         while(portlist)
3284         {
3285                 set_tone(portlist, cause);
3286                 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3287                 portlist = portlist->next;
3288         }
3289 }
3290
3291 /* join MESSAGE_SETUP */
3292 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3293 {
3294         struct message *message;
3295         struct interface        *interface;
3296
3297         /* if we already in setup state, we just update the dialing with new digits */
3298         if (e_state == EPOINT_STATE_OUT_SETUP
3299          || e_state == EPOINT_STATE_OUT_OVERLAP)
3300         {
3301                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3302                 /* if digits changed, what we have already dialed */
3303                 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3304                 {
3305                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have dialed digits which have been changed or we have a new multidial, so we must redial.\n", ea_endpoint->ep_serial);
3306                         /* release all ports */
3307                         while((portlist = ea_endpoint->ep_portlist))
3308                         {
3309                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3310                                 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3311                                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3312                                 message_put(message);
3313                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3314                                 ea_endpoint->free_portlist(portlist);
3315                         }
3316
3317                         /* disconnect audio */
3318                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3319                         message->param.audiopath = CHANNEL_STATE_HOLD;
3320                         message_put(message);
3321
3322                         /* get dialing info */
3323                         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
3324                         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3325                         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
3326                         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
3327                         new_state(EPOINT_STATE_OUT_OVERLAP);
3328
3329                         /* get time */
3330                         e_redial = now_d + 1; /* set redial one second in the future */
3331                         return;
3332                 }
3333                 /* if we have a pending redial, so we just adjust the dialing number */
3334                 if (e_redial)
3335                 {
3336                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3337                         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3338                         return;
3339                 }
3340                 if (!ea_endpoint->ep_portlist)
3341                 {
3342                         PERROR("ERROR: overlap dialing to a NULL port relation\n");
3343                 }
3344                 if (ea_endpoint->ep_portlist->next)
3345                 {
3346                         PERROR("ERROR: overlap dialing to a port_list port relation\n");
3347                 }
3348                 if (e_state == EPOINT_STATE_OUT_SETUP)
3349                 {
3350                         /* queue digits */
3351                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) digits '%s' are queued because we didn't receive a setup acknowledge.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3352                         SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3353                         
3354                 } else
3355                 {
3356                         /* get what we have not dialed yet */
3357                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.id+strlen(e_dialinginfo.id));
3358                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3359                         SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3360                         message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3361                         message_put(message);
3362                         logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3363                 }
3364                 /* always store what we have dialed or queued */
3365                 memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3366                 
3367                 return;
3368         }
3369         if (e_state != EPOINT_STATE_IDLE)
3370         {
3371                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3372                 return;
3373         }
3374         /* if an internal extension is dialed, copy that number */
3375         if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3376                 SCPY(e_ext.number, param->setup.dialinginfo.id);
3377         /* if an internal extension is dialed, get extension's info about caller */
3378         if (e_ext.number[0]) 
3379         {
3380                 if (!read_extension(&e_ext, e_ext.number))
3381                 {
3382                         e_ext.number[0] = '\0';
3383                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3384                 }
3385         }
3386
3387         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
3388         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3389         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
3390         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
3391
3392         /* screen incoming caller id */
3393         interface = interface_first;
3394         while(interface)
3395         {
3396                 if (!strcmp(e_callerinfo.interface, interface->name))
3397                 {
3398                         break;
3399                 }
3400                 interface = interface->next;
3401         }
3402         if (interface)
3403                 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3404
3405         /* process (voice over) data calls */
3406         if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3407         {
3408                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3409                 memset(&e_capainfo, 0, sizeof(e_capainfo));
3410                 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3411                 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3412                 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3413         }
3414
3415         new_state(EPOINT_STATE_OUT_SETUP);
3416         /* call special setup routine */
3417         out_setup();
3418 }
3419
3420 /* join MESSAGE_mISDNSIGNAL */
3421 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3422 {
3423         struct message *message;
3424
3425         while(portlist)
3426         {
3427                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3428                 memcpy(&message->param, param, sizeof(union parameter));
3429                 message_put(message);
3430                 portlist = portlist->next;
3431         }
3432 }
3433
3434 /* join MESSAGE_NOTIFY */
3435 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3436 {
3437         struct message *message;
3438         int new_state;
3439
3440         if (param->notifyinfo.notify)
3441         {
3442                 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3443 //              /* if notification was generated locally, we turn hold music on/off */ 
3444 //              if (param->notifyinfo.local)
3445 // NOTE: we always assume that we send hold music on suspension of call, because we don't track if audio is available or not (we assume that we always have no audio, to make it easier)
3446                 {
3447                         if (e_hold)
3448                         {
3449                                 /* unhold if */
3450                                 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3451                                 {
3452                                         if (!strcmp(e_tone, "hold")) // don't interrupt other tones
3453                                         {
3454                                                 while(portlist)
3455                                                 {
3456                                                         set_tone(portlist, "");
3457                                                         portlist = portlist->next;
3458                                                 }
3459                                         }
3460                                         portlist = ea_endpoint->ep_portlist;
3461                                         e_hold = 0;
3462                                 }
3463                         } else {
3464                                 /* hold if */
3465                                 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3466                                 {
3467                                         while(portlist)
3468                                         {
3469                                                 set_tone(portlist, "hold");
3470                                                 portlist = portlist->next;
3471                                         }
3472                                         portlist = ea_endpoint->ep_portlist;
3473                                         e_hold = 1;
3474                                 }
3475                         }
3476                 }
3477                 /* save new state */
3478                 e_tx_state = new_state;
3479         }
3480
3481         /* notify port(s) about it */
3482         while(portlist)
3483         {
3484                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3485                 memcpy(&message->param.notifyinfo, &param->notifyinfo, sizeof(struct notify_info));
3486                 /* handle restricted caller ids */
3487                 apply_callerid_restriction(e_ext.anon_ignore, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3488                 /* display callerid if desired for extension */
3489                 SCPY(message->param.notifyinfo.display, apply_callerid_display(message->param.notifyinfo.id, message->param.notifyinfo.itype, message->param.notifyinfo.ntype, message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL));
3490                 message_put(message);
3491                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3492                 portlist = portlist->next;
3493         }
3494 }
3495
3496 /* JOIN sends messages to the endpoint
3497  */
3498 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3499 {
3500         struct port_list *portlist;
3501         struct message *message;
3502
3503         if (!join_id)
3504         {
3505                 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3506                 return;
3507         }
3508
3509         portlist = ea_endpoint->ep_portlist;
3510
3511         /* send MESSAGE_DATA to port */
3512         if (message_type == MESSAGE_DATA)
3513         {
3514                 if (join_id == ea_endpoint->ep_join_id) // still linked with JOIN
3515                 {
3516                         /* skip if no port relation */
3517                         if (!portlist)
3518                                 return;
3519                         /* skip if more than one port relation */
3520                         if (portlist->next)
3521                                 return;
3522                         /* forward audio data to port */
3523                         message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3524                         return;
3525                 }
3526         }
3527
3528 //      PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active JOIN (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3529         switch(message_type)
3530         {
3531                 /* JOIN SENDS TONE message */
3532                 case MESSAGE_TONE:
3533                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received tone message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->tone.name);
3534                 set_tone(portlist, param->tone.name);
3535                 break;
3536
3537                 /* JOIN SENDS CRYPT message */
3538                 case MESSAGE_CRYPT:
3539                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
3540                 join_crypt(portlist, message_type, param);
3541                 break;
3542
3543                 /* JOIN sends INFORMATION message */
3544                 case MESSAGE_INFORMATION:
3545                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received more digits: '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->information.id);
3546                 join_information(portlist, message_type, param);
3547                 break;
3548
3549                 /* JOIN sends FACILITY message */
3550                 case MESSAGE_FACILITY:
3551                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received facility\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3552                 join_facility(portlist, message_type, param);
3553                 break;
3554
3555                 /* JOIN sends OVERLAP message */
3556                 case MESSAGE_OVERLAP:
3557                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received 'more info available'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3558                 if (e_state!=EPOINT_STATE_IN_SETUP
3559                  && e_state!=EPOINT_STATE_IN_OVERLAP)
3560                 {
3561                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3562                         break;
3563                 }
3564                 join_overlap(portlist, message_type, param);
3565                 break;
3566
3567                 /* JOIN sends PROCEEDING message */
3568                 case MESSAGE_PROCEEDING:
3569                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s (caller id '%s') received proceeding\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3570                 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3571                 {
3572                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3573                         break;
3574                 }
3575                 join_proceeding(portlist, message_type, param);
3576                 break;
3577
3578                 /* JOIN sends ALERTING message */
3579                 case MESSAGE_ALERTING:
3580                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received alerting\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3581                 if (e_state!=EPOINT_STATE_IN_OVERLAP
3582                  && e_state!=EPOINT_STATE_IN_PROCEEDING)
3583                 {
3584                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3585                         break;
3586                 }
3587                 join_alerting(portlist, message_type, param);
3588                 break;
3589
3590                 /* JOIN sends CONNECT message */
3591                 case MESSAGE_CONNECT:
3592                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received connect\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3593                 if (e_state!=EPOINT_STATE_IN_OVERLAP
3594                  && e_state!=EPOINT_STATE_IN_PROCEEDING
3595                  && e_state!=EPOINT_STATE_IN_ALERTING)
3596                 {
3597                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3598                         break;
3599                 }
3600                 join_connect(portlist, message_type, param);
3601                 break;
3602
3603                 /* JOIN sends DISCONNECT/RELEASE message */
3604                 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3605                 case MESSAGE_RELEASE: /* JOIN releases */
3606                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received %s with cause %d location %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (message_type==MESSAGE_DISCONNECT)?"disconnect":"release", param->disconnectinfo.cause, param->disconnectinfo.location);
3607                 join_disconnect_release(message_type, param);
3608                 break;
3609
3610                 /* JOIN sends SETUP message */
3611                 case MESSAGE_SETUP:
3612                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from terminal='%s',id='%s' to id='%s' (dialing itype=%d)\n", ea_endpoint->ep_serial, param->setup.callerinfo.extension, param->setup.callerinfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.itype);
3613                 join_setup(portlist, message_type, param);
3614                 break;
3615
3616                 /* JOIN sends special mISDNSIGNAL message */
3617                 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3618                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received mISDNsignal message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3619                 join_mISDNsignal(portlist, message_type, param);
3620                 break;
3621
3622 #if 0
3623                 /* JOIN requests bchannel */
3624                 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3625                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
3626                 /* only one port is expected to be connected to bchannel */
3627                 if (!portlist)
3628                         break;
3629                 if (portlist->next)
3630                         break;
3631                 e_join_pattern = 1;
3632                 SCPY(e_tone, "");
3633                 set_tone(portlist, NULL);
3634                 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3635                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3636                 break;
3637 #endif
3638
3639                 /* JOIN has pattern available */
3640                 case MESSAGE_PATTERN: /* indicating pattern available */
3641                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern availability.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3642                 if (!e_join_pattern)
3643                 {
3644                         PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3645                         e_join_pattern = 1;
3646                         SCPY(e_tone, "");
3647                         while(portlist)
3648                         {
3649                                 set_tone(portlist, NULL);
3650                                 portlist = portlist->next;
3651                         }
3652                         /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3653                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3654                         message->param.audiopath = CHANNEL_STATE_CONNECT;
3655                         message_put(message);
3656 //                      /* tell remote epoint to connect audio also, because we like to hear the patterns */
3657 //                      message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3658 //                      message->param.audiopath = CHANNEL_STATE_CONNECT;
3659 //                      message_put(message);
3660 // patterns are available, remote already connected audio
3661                 }
3662                 break;
3663
3664                 /* JOIN has no pattern available */
3665                 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3666                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received pattern NOT available.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3667                 if (e_join_pattern)
3668                 {
3669                         PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3670                         e_join_pattern = 0;
3671                         /* disconnect our audio tx and rx */
3672                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3673                         message->param.audiopath = CHANNEL_STATE_HOLD;
3674                         message_put(message);
3675                 }
3676                 break;
3677
3678 #if 0
3679                 /* JOIN (dunno at the moment) */
3680                 case MESSAGE_REMOTE_AUDIO:
3681                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received audio remote request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3682                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3683                 message->param.audiopath = param->channel;
3684                 message_put(message);
3685                 break;
3686 #endif
3687
3688                 /* JOIN sends a notify message */
3689                 case MESSAGE_NOTIFY:
3690                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received notify.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3691                 join_notify(portlist, message_type, param);
3692                 break;
3693
3694                 default:
3695                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: #%d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
3696         }
3697 }
3698
3699
3700 /* pick_join will connect the first incoming call found. the endpoint
3701  * will receivce a MESSAGE_CONNECT.
3702  */
3703 int match_list(char *list, char *item)
3704 {
3705         char *end, *next = NULL;
3706
3707         /* no list make matching */
3708         if (!list)
3709                 return(1);
3710
3711         while(42)
3712         {
3713                 /* eliminate white spaces */
3714                 while (*list <= ' ')
3715                         list++;
3716                 if (*list == ',')
3717                 {
3718                         list++;
3719                         continue;
3720                 }
3721                 /* if end of list is reached, we return */
3722                 if (list[0] == '\0')
3723                         return(0);
3724                 /* if we have more than one entry (left) */
3725                 if ((end = strchr(list, ',')))
3726                         next = end + 1;
3727                 else
3728                         next = end = strchr(list, '\0');
3729                 while (*(end-1) <= ' ')
3730                         end--;
3731                 /* if string part matches item */
3732                 if (!strncmp(list, item, end-list))
3733                         return(1);
3734                 list = next;
3735         }
3736 }
3737
3738 void EndpointAppPBX::pick_join(char *extensions)
3739 {
3740         struct message *message;
3741         struct port_list *portlist;
3742         class Port *port;
3743         class EndpointAppPBX *eapp, *found;
3744         class Join *join;
3745         class JoinPBX *joinpbx;
3746         struct join_relation *relation;
3747         int vbox;
3748
3749         /* find an endpoint that is ringing internally or vbox with higher priority */
3750         vbox = 0;
3751         found = NULL;
3752         eapp = apppbx_first;
3753         while(eapp)
3754         {
3755                 if (eapp!=this && ea_endpoint->ep_portlist)
3756                 {
3757                         portlist = eapp->ea_endpoint->ep_portlist;
3758                         while(portlist)
3759                         {
3760                                 if ((port = find_port_id(portlist->port_id)))
3761                                 {
3762                                         if (port->p_type == PORT_TYPE_VBOX_OUT)
3763                                         {
3764                                                 if (match_list(extensions, eapp->e_ext.number))
3765                                                 {
3766                                                         found = eapp;
3767                                                         vbox = 1;
3768                                                         break;
3769                                                 }
3770                                         }
3771                                         if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3772                                          && port->p_state==PORT_STATE_OUT_ALERTING)
3773                                                 if (match_list(extensions, eapp->e_ext.number))
3774                                                 {
3775                                                         found = eapp;
3776                                                 }
3777                                 }
3778                                 portlist = portlist->next;
3779                         }
3780                         if (portlist)
3781                                 break;
3782                 }
3783                 eapp = eapp->next;
3784         }
3785
3786         /* if no endpoint found */
3787         if (!found)
3788         {
3789                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) nobody is ringing internally (or we don't have her in the access list), so we disconnect.\n", ea_endpoint->ep_serial);
3790 reject:
3791                 set_tone(ea_endpoint->ep_portlist, "cause_10");
3792                 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3793                 new_state(EPOINT_STATE_OUT_DISCONNECT);
3794                 return;
3795         }
3796         eapp = found;
3797
3798         if (ea_endpoint->ep_join_id)
3799         {
3800                 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3801                 goto reject;
3802         }
3803         if (!eapp->ea_endpoint->ep_join_id)
3804         {
3805                 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3806                 goto reject;
3807         }
3808         join = find_join_id(eapp->ea_endpoint->ep_join_id);
3809         if (!join)
3810         {
3811                 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3812                 goto reject;
3813         }
3814         if (join->j_type != JOIN_TYPE_PBX)
3815         {
3816                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3817                 goto reject;
3818         }
3819         joinpbx = (class JoinPBX *)join;
3820         relation = joinpbx->j_relation;
3821         if (!relation)
3822         {
3823                 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3824                 goto reject;
3825         }
3826         while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3827         {
3828                 relation = relation->next;
3829                 if (!relation)
3830                 {
3831                         PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3832                         goto reject;
3833                 }
3834         }
3835
3836         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3837
3838         if (options.deb & DEBUG_EPOINT)
3839         {
3840                 class Join *debug_c = join_first;
3841                 class Endpoint *debug_e = epoint_first;
3842                 class Port *debug_p = port_first;
3843
3844                 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3845
3846                 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3847                 while(debug_c)
3848                 {
3849                         PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3850                         debug_c = debug_c->next;
3851                 }
3852                 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3853                 while(debug_e)
3854                 {
3855                         PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3856                         debug_e = debug_e->next;
3857                 }
3858                 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3859                 while(debug_p)
3860                 {
3861                         PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3862                         debug_p = debug_p->next;
3863                 }
3864         }
3865
3866         /* relink join */
3867         ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3868         relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3869         eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3870
3871         /* connnecting our endpoint */
3872         new_state(EPOINT_STATE_CONNECT);
3873         e_dtmf = 1;
3874         set_tone(ea_endpoint->ep_portlist, NULL);
3875
3876         /* now we send a release to the ringing endpoint */
3877         message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3878         message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3879         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3880         message_put(message);
3881
3882         /* we send a connect to the join with our caller id */
3883         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3884         SCPY(message->param.connectinfo.id, e_callerinfo.id);
3885         message->param.connectinfo.present = e_callerinfo.present;
3886         message->param.connectinfo.screen = e_callerinfo.screen;
3887         message->param.connectinfo.itype = e_callerinfo.itype;
3888         message->param.connectinfo.ntype = e_callerinfo.ntype;
3889         message_put(message);
3890
3891         /* we send a connect to our port with the remote callerid */
3892         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3893         SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3894         message->param.connectinfo.present = eapp->e_callerinfo.present;
3895         message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3896         message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3897         message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3898         /* handle restricted caller ids */
3899         apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3900         /* display callerid if desired for extension */
3901         SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype,  message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
3902         message_put(message);
3903
3904         /* we send a connect to the audio path (not for vbox) */
3905         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3906         message->param.audiopath = CHANNEL_STATE_CONNECT;
3907         message_put(message);
3908
3909         /* beeing paranoid, we make call update */
3910         joinpbx->j_updatebridge = 1;
3911
3912         if (options.deb & DEBUG_EPOINT)
3913         {
3914                 class Join *debug_c = join_first;
3915                 class Endpoint *debug_e = epoint_first;
3916                 class Port *debug_p = port_first;
3917
3918                 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3919
3920                 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3921                 while(debug_c)
3922                 {
3923                         PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3924                         debug_c = debug_c->next;
3925                 }
3926                 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3927                 while(debug_e)
3928                 {
3929                         PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3930                         debug_e = debug_e->next;
3931                 }
3932                 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3933                 while(debug_p)
3934                 {
3935                         PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3936                         debug_p = debug_p->next;
3937                 }
3938         }
3939 }
3940
3941
3942 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3943  */
3944 void EndpointAppPBX::join_join(void)
3945 {
3946         struct message *message;
3947         struct join_relation *our_relation, *other_relation;
3948         struct join_relation **our_relation_pointer, **other_relation_pointer;
3949         class Join *our_join, *other_join;
3950         class JoinPBX *our_joinpbx, *other_joinpbx;
3951         class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3952         class Port *our_port, *other_port;
3953         class Pdss1 *our_pdss1, *other_pdss1;
3954
3955         /* are we a candidate to join a join */
3956         our_join = find_join_id(ea_endpoint->ep_join_id);
3957         if (!our_join)
3958         {
3959                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3960                 return;
3961         }
3962         if (our_join->j_type != JOIN_TYPE_PBX)
3963         {
3964                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3965                 return;
3966         }
3967         our_joinpbx = (class JoinPBX *)our_join;
3968         if (!ea_endpoint->ep_portlist)
3969         {
3970                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3971                 return;
3972         }
3973         if (!e_ext.number[0])
3974         {
3975                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3976                 return;
3977         }
3978         our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3979         if (!our_port)
3980         {
3981                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3982                 return;
3983         }
3984         if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3985         {
3986                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3987                 return;
3988         }
3989         our_pdss1 = (class Pdss1 *)our_port;
3990
3991         /* find an endpoint that is on hold and has the same mISDNport that we are on */
3992         other_eapp = apppbx_first;
3993         while(other_eapp)
3994         {
3995                 if (other_eapp == this)
3996                 {
3997                         other_eapp = other_eapp->next;
3998                         continue;
3999                 }
4000                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s join=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_join_id);
4001                 if (other_eapp->e_ext.number[0] /* has terminal */
4002                  && other_eapp->ea_endpoint->ep_portlist /* has port */
4003                  && other_eapp->ea_endpoint->ep_join_id) /* has join */
4004                 {
4005                         other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
4006                         if (other_port) /* port still exists */
4007                         {
4008                                 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
4009                                  || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
4010                                 {
4011                                         other_pdss1 = (class Pdss1 *)other_port;
4012                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
4013                                         if (other_pdss1->p_m_hold /* port is on hold */
4014                                          && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
4015                                          && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
4016                                                 break;
4017                                 } else
4018                                 {
4019                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
4020                                 }
4021                         } else
4022                         {
4023                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
4024                         }
4025                 }
4026                 other_eapp = other_eapp->next;
4027         }
4028         if (!other_eapp)
4029         {
4030                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
4031                 return;
4032         }
4033         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
4034
4035         /* if we have the same join */
4036         if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
4037         {
4038                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
4039                 return;
4040         }
4041         other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4042         if (!other_join)
4043         {
4044                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4045                 return;
4046         }
4047         if (other_join->j_type != JOIN_TYPE_PBX)
4048         {
4049                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4050                 return;
4051         }
4052         other_joinpbx = (class JoinPBX *)other_join;
4053         if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
4054         {
4055                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4056                 return;
4057         }
4058
4059         /* remove relation to endpoint for join on hold */
4060         other_relation = other_joinpbx->j_relation;
4061         other_relation_pointer = &other_joinpbx->j_relation;
4062         while(other_relation)
4063         {
4064                 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4065                 {
4066                 /* detach other endpoint on hold */
4067                         *other_relation_pointer = other_relation->next;
4068                         FREE(other_relation, sizeof(struct join_relation));
4069                         cmemuse--;
4070                         other_relation = *other_relation_pointer;
4071                         other_eapp->ea_endpoint->ep_join_id = NULL;
4072                         continue;
4073                 }
4074
4075                 /* change join/hold pointer of endpoint to the new join */
4076                 temp_epoint = find_epoint_id(other_relation->epoint_id);
4077                 if (temp_epoint)
4078                 {
4079                         if (temp_epoint->ep_join_id == other_join->j_serial)
4080                                 temp_epoint->ep_join_id = our_join->j_serial;
4081                 }
4082
4083                 other_relation_pointer = &other_relation->next;
4084                 other_relation = other_relation->next;
4085         }
4086         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
4087
4088         /* join call relations */
4089         our_relation = our_joinpbx->j_relation;
4090         our_relation_pointer = &our_joinpbx->j_relation;
4091         while(our_relation)
4092         {
4093                 our_relation_pointer = &our_relation->next;
4094                 our_relation = our_relation->next;
4095         }
4096         *our_relation_pointer = other_joinpbx->j_relation;
4097         other_joinpbx->j_relation = NULL;
4098         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4099
4100         /* release endpoint on hold */
4101         message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
4102         message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4103         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4104         message_put(message);
4105         
4106         /* if we are not a partyline, we get partyline state from other join */
4107         our_joinpbx->j_partyline += other_joinpbx->j_partyline; 
4108
4109         /* remove empty join */
4110         delete other_join;
4111         PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
4112
4113         /* mixer must update */
4114         our_joinpbx->j_updatebridge = 1; /* update mixer flag */
4115
4116         /* we send a retrieve to that endpoint */
4117         // mixer will update the hold-state of the join and send it to the endpoints is changes
4118 }
4119
4120
4121 /* check if we have an external call
4122  * this is used to check for encryption ability
4123  */
4124 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4125 {
4126         struct join_relation *relation;
4127         class Join *join;
4128         class JoinPBX *joinpbx;
4129         class Endpoint *epoint;
4130
4131         /* some paranoia check */
4132         if (!ea_endpoint->ep_portlist)
4133         {
4134                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4135                 *errstr = "No Call";
4136                 return(1);
4137         }
4138         if (!e_ext.number[0])
4139         {
4140                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4141                 *errstr = "No Call";
4142                 return(1);
4143         }
4144
4145         /* check if we have a join with 2 parties */
4146         join = find_join_id(ea_endpoint->ep_join_id);
4147         if (!join)
4148         {
4149                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4150                 *errstr = "No Call";
4151                 return(1);
4152         }
4153         if (join->j_type != JOIN_TYPE_PBX)
4154         {
4155                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4156                 *errstr = "No PBX Call";
4157                 return(1);
4158         }
4159         joinpbx = (class JoinPBX *)join;
4160         relation = joinpbx->j_relation;
4161         if (!relation)
4162         {
4163                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4164                 *errstr = "No Call";
4165                 return(1);
4166         }
4167         if (!relation->next)
4168         {
4169                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4170                 *errstr = "No Call";
4171                 return(1);
4172         }
4173         if (relation->next->next)
4174         {
4175                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4176                 *errstr = "Err: Conference";
4177                 return(1);
4178         }
4179         if (relation->epoint_id == ea_endpoint->ep_serial)
4180         {
4181                 relation = relation->next;
4182                 if (relation->epoint_id == ea_endpoint->ep_serial)
4183                 {
4184                         PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4185                         *errstr = "Software Error";
4186                         return(1);
4187                 }
4188         }
4189
4190         /* check remote port for external call */
4191         epoint = find_epoint_id(relation->epoint_id);
4192         if (!epoint)
4193         {
4194                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4195                 *errstr = "No Call";
4196                 return(1);
4197         }
4198         if (!epoint->ep_portlist)
4199         {
4200                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4201                 *errstr = "No Call";
4202                 return(1);
4203         }
4204         *port = find_port_id(epoint->ep_portlist->port_id);
4205         if (!(*port))
4206         {
4207                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4208                 *errstr = "No Call";
4209                 return(1);
4210         }
4211         if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4212         {
4213                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4214                 *errstr = "No Ext Call";
4215                 return(1);
4216         }
4217         if ((*port)->p_state != PORT_STATE_CONNECT)
4218         {
4219                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4220                 *errstr = "No Ext Connect";
4221                 return(1);
4222         }
4223         return(0);
4224 }
4225
4226 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4227 {
4228         char *logtext = "unknown";
4229         char buffer[64];
4230
4231         switch(message_type)
4232         {
4233                 case MESSAGE_SETUP:
4234                 trace_header("SETUP", dir);
4235                 if (dir == DIRECTION_OUT)
4236                         add_trace("to", NULL, "CH(%lu)", port_id);
4237                 if (dir == DIRECTION_IN)
4238                         add_trace("from", NULL, "CH(%lu)", port_id);
4239                 if (param->setup.callerinfo.extension[0])
4240                         add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4241                 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4242                 switch(param->setup.callerinfo.present)
4243                 {
4244                         case INFO_PRESENT_RESTRICTED:
4245                         add_trace("caller id", "present", "restricted");
4246                         break;
4247                         case INFO_PRESENT_ALLOWED:
4248                         add_trace("caller id", "present", "allowed");
4249                         break;
4250                         default:
4251                         add_trace("caller id", "present", "not available");
4252                 }
4253                 if (param->setup.redirinfo.id[0])
4254                 {
4255                         add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4256                         switch(param->setup.redirinfo.present)
4257                         {
4258                                 case INFO_PRESENT_RESTRICTED:
4259                                 add_trace("redir'ing", "present", "restricted");
4260                                 break;
4261                                 case INFO_PRESENT_ALLOWED:
4262                                 add_trace("redir'ing", "present", "allowed");
4263                                 break;
4264                                 default:
4265                                 add_trace("redir'ing", "present", "not available");
4266                         }
4267                 }
4268                 if (param->setup.dialinginfo.id[0])
4269                         add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4270                 end_trace();
4271                 break;
4272
4273                 case MESSAGE_OVERLAP:
4274                 trace_header("SETUP ACKNOWLEDGE", dir);
4275                 if (dir == DIRECTION_OUT)
4276                         add_trace("to", NULL, "CH(%lu)", port_id);
4277                 if (dir == DIRECTION_IN)
4278                         add_trace("from", NULL, "CH(%lu)", port_id);
4279                 end_trace();
4280                 break;
4281
4282                 case MESSAGE_PROCEEDING:
4283                 trace_header("PROCEEDING", dir);
4284                 if (dir == DIRECTION_OUT)
4285                         add_trace("to", NULL, "CH(%lu)", port_id);
4286                 if (dir == DIRECTION_IN)
4287                         add_trace("from", NULL, "CH(%lu)", port_id);
4288                 end_trace();
4289                 break;
4290
4291                 case MESSAGE_ALERTING:
4292                 trace_header("ALERTING", dir);
4293                 if (dir == DIRECTION_OUT)
4294                         add_trace("to", NULL, "CH(%lu)", port_id);
4295                 if (dir == DIRECTION_IN)
4296                         add_trace("from", NULL, "CH(%lu)", port_id);
4297                 end_trace();
4298                 break;
4299
4300                 case MESSAGE_CONNECT:
4301                 trace_header("CONNECT", dir);
4302                 if (dir == DIRECTION_OUT)
4303                         add_trace("to", NULL, "CH(%lu)", port_id);
4304                 if (dir == DIRECTION_IN)
4305                         add_trace("from", NULL, "CH(%lu)", port_id);
4306                 if (param->connectinfo.extension[0])
4307                         add_trace("extension", NULL, "%s", param->connectinfo.extension);
4308                 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4309                 switch(param->connectinfo.present)
4310                 {
4311                         case INFO_PRESENT_RESTRICTED:
4312                         add_trace("connect id", "present", "restricted");
4313                         break;
4314                         case INFO_PRESENT_ALLOWED:
4315                         add_trace("connect id", "present", "allowed");
4316                         break;
4317                         default:
4318                         add_trace("connect id", "present", "not available");
4319                 }
4320                 end_trace();
4321                 break;
4322
4323                 case MESSAGE_DISCONNECT:
4324                 case MESSAGE_RELEASE:
4325                 if (message_type == MESSAGE_DISCONNECT)
4326                         trace_header("DISCONNECT", dir);
4327                 else
4328                         trace_header("RELEASE", dir);
4329                 if (dir == DIRECTION_OUT)
4330                         add_trace("to", NULL, "CH(%lu)", port_id);
4331                 if (dir == DIRECTION_IN)
4332                         add_trace("from", NULL, "CH(%lu)", port_id);
4333                 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4334                 switch(param->disconnectinfo.location)
4335                 {
4336                         case LOCATION_USER:
4337                         add_trace("cause", "location", "0-User");
4338                         break;
4339                         case LOCATION_PRIVATE_LOCAL:
4340                         add_trace("cause", "location", "1-Local-PBX");
4341                         break;
4342                         case LOCATION_PUBLIC_LOCAL:
4343                         add_trace("cause", "location", "2-Local-Exchange");
4344                         break;
4345                         case LOCATION_TRANSIT:
4346                         add_trace("cause", "location", "3-Transit");
4347                         break;
4348                         case LOCATION_PUBLIC_REMOTE:
4349                         add_trace("cause", "location", "4-Remote-PBX");
4350                         break;
4351                         case LOCATION_PRIVATE_REMOTE:
4352                         add_trace("cause", "location", "5-Remote-Exchange");
4353                         break;
4354                         case LOCATION_INTERNATIONAL:
4355                         add_trace("cause", "location", "7-International-Exchange");
4356                         break;
4357                         case LOCATION_BEYOND:
4358                         add_trace("cause", "location", "10-Beyond-Interworking");
4359                         break;
4360                         default:
4361                         add_trace("cause", "location", "%d", param->disconnectinfo.location);
4362                 }
4363                 end_trace();
4364                 break;
4365
4366                 case MESSAGE_NOTIFY:
4367                 switch(param->notifyinfo.notify)
4368                 {
4369                         case 0x00:
4370                         logtext = "NULL";
4371                         break;
4372                         case 0x80:
4373                         logtext = "USER_SUSPENDED";
4374                         break;
4375                         case 0x82:
4376                         logtext = "BEARER_SERVICE_CHANGED";
4377                         break;
4378                         case 0x81:
4379                         logtext = "USER_RESUMED";
4380                         break;
4381                         case 0xc2:
4382                         logtext = "CONFERENCE_ESTABLISHED";
4383                         break;
4384                         case 0xc3:
4385                         logtext = "CONFERENCE_DISCONNECTED";
4386                         break;
4387                         case 0xc4:
4388                         logtext = "OTHER_PARTY_ADDED";
4389                         break;
4390                         case 0xc5:
4391                         logtext = "ISOLATED";
4392                         break;
4393                         case 0xc6:
4394                         logtext = "REATTACHED";
4395                         break;
4396                         case 0xc7:
4397                         logtext = "OTHER_PARTY_ISOLATED";
4398                         break;
4399                         case 0xc8:
4400                         logtext = "OTHER_PARTY_REATTACHED";
4401                         break;
4402                         case 0xc9:
4403                         logtext = "OTHER_PARTY_SPLIT";
4404                         break;
4405                         case 0xca:
4406                         logtext = "OTHER_PARTY_DISCONNECTED";
4407                         break;
4408                         case 0xcb:
4409                         logtext = "CONFERENCE_FLOATING";
4410                         break;
4411                         case 0xcc:
4412                         logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4413                         break;
4414                         case 0xcf:
4415                         logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4416                         break;
4417                         case 0xe0:
4418                         logtext = "CALL_IS_A_WAITING_CALL";
4419                         break;
4420                         case 0xe8:
4421                         logtext = "DIVERSION_ACTIVATED";
4422                         break;
4423                         case 0xe9:
4424                         logtext = "RESERVED_CT_1";
4425                         break;
4426                         case 0xea:
4427                         logtext = "RESERVED_CT_2";
4428                         break;
4429                         case 0xee:
4430                         logtext = "REVERSE_CHARGING";
4431                         break;
4432                         case 0xf9:
4433                         logtext = "REMOTE_HOLD";
4434                         break;
4435                         case 0xfa:
4436                         logtext = "REMOTE_RETRIEVAL";
4437                         break;
4438                         case 0xfb:
4439                         logtext = "CALL_IS_DIVERTING";
4440                         break;
4441                         default:
4442                         SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4443                         logtext = buffer;
4444
4445                 }
4446                 trace_header("NOTIFY", dir);
4447                 if (dir == DIRECTION_OUT)
4448                         add_trace("to", NULL, "CH(%lu)", port_id);
4449                 if (dir == DIRECTION_IN)
4450                         add_trace("from", NULL, "CH(%lu)", port_id);
4451                 if (param->notifyinfo.notify)
4452                         add_trace("indicator", NULL, "%s", logtext);
4453                 if (param->notifyinfo.id[0])
4454                 {
4455                         add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4456                         switch(param->notifyinfo.present)
4457                         {
4458                                 case INFO_PRESENT_RESTRICTED:
4459                                 add_trace("redir'on", "present", "restricted");
4460                                 break;
4461                                 case INFO_PRESENT_ALLOWED:
4462                                 add_trace("redir'on", "present", "allowed");
4463                                 break;
4464                                 default:
4465                                 add_trace("redir'on", "present", "not available");
4466                         }
4467                 }
4468                 if (param->notifyinfo.display[0])
4469                         add_trace("display", NULL, "%s", param->notifyinfo.display);
4470                 end_trace();
4471                 break;
4472
4473                 case MESSAGE_INFORMATION:
4474                 trace_header("INFORMATION", dir);
4475                 if (dir == DIRECTION_OUT)
4476                         add_trace("to", NULL, "CH(%lu)", port_id);
4477                 if (dir == DIRECTION_IN)
4478                         add_trace("from", NULL, "CH(%lu)", port_id);
4479                 add_trace("dialing", NULL, "%s", param->information.id);
4480                 end_trace();
4481                 break;
4482
4483                 case MESSAGE_FACILITY:
4484                 trace_header("FACILITY", dir);
4485                 if (dir == DIRECTION_OUT)
4486                         add_trace("to", NULL, "CH(%lu)", port_id);
4487                 if (dir == DIRECTION_IN)
4488                         add_trace("from", NULL, "CH(%lu)", port_id);
4489                 end_trace();
4490                 break;
4491
4492                 case MESSAGE_TONE:
4493                 trace_header("TONE", dir);
4494                 if (dir == DIRECTION_OUT)
4495                         add_trace("to", NULL, "CH(%lu)", port_id);
4496                 if (dir == DIRECTION_IN)
4497                         add_trace("from", NULL, "CH(%lu)", port_id);
4498                 if (param->tone.name[0])
4499                 {
4500                         add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4501                         add_trace("name", NULL, "%s", param->tone.name);
4502                 } else
4503                         add_trace("off", NULL, NULL);
4504                 end_trace();
4505                 break;
4506
4507                 case MESSAGE_SUSPEND:
4508                 case MESSAGE_RESUME:
4509                 if (message_type == MESSAGE_SUSPEND)
4510                         trace_header("SUSPEND", dir);
4511                 else
4512                         trace_header("RESUME", dir);
4513                 if (dir == DIRECTION_OUT)
4514                         add_trace("to", NULL, "CH(%lu)", port_id);
4515                 if (dir == DIRECTION_IN)
4516                         add_trace("from", NULL, "CH(%lu)", port_id);
4517                 if (param->parkinfo.len)
4518                         add_trace("length", NULL, "%d", param->parkinfo.len);
4519                 end_trace();
4520                 break;
4521
4522 #if 0
4523                 case MESSAGE_BCHANNEL:
4524                 trace_header("BCHANNEL", dir);
4525                 switch(param->bchannel.type)
4526                 {
4527                         case BCHANNEL_REQUEST:
4528                         add_trace("type", NULL, "request");
4529                         break;
4530                         case BCHANNEL_ASSIGN:
4531                         add_trace("type", NULL, "assign");
4532                         break;
4533                         case BCHANNEL_ASSIGN_ACK:
4534                         add_trace("type", NULL, "assign_ack");
4535                         break;
4536                         case BCHANNEL_REMOVE:
4537                         add_trace("type", NULL, "remove");
4538                         break;
4539                         case BCHANNEL_REMOVE_ACK:
4540                         add_trace("type", NULL, "remove_ack");
4541                         break;
4542                 }
4543                 if (param->bchannel.addr)
4544                         add_trace("address", NULL, "%x", param->bchannel.addr);
4545                 end_trace();
4546                 break;
4547 #endif
4548
4549                 default:
4550                 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4551         }
4552 }
4553
4554 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4555 {
4556         struct message *message;
4557
4558         if (!portlist)
4559                 return;
4560         if (!portlist->port_id)
4561                 return;
4562
4563         if (!e_connectedmode)
4564         {
4565                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4566                 message->param.disconnectinfo.cause = cause;
4567                 message->param.disconnectinfo.location = location;
4568                 if (display[0])
4569                         SCPY(message->param.disconnectinfo.display, display);
4570                 else
4571                         SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4572         } else
4573         {
4574                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4575                 if (display[0])
4576                         SCPY(message->param.notifyinfo.display, display);
4577                 else
4578                         SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4579         }
4580         message_put(message);
4581         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
4582 }
4583
4584