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