Added 'extern' flag to interface.conf.
[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 "main.h"
14
15 class EndpointAppPBX *apppbx_first = NULL;
16
17 /*
18  * EndpointAppPBX constructor
19  */
20 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
21 {
22         class EndpointAppPBX **apppointer;
23
24         /* add application to chain */
25         next = NULL;
26         apppointer = &apppbx_first;
27         while(*apppointer)
28                 apppointer = &((*apppointer)->next);
29         *apppointer = this;
30
31         /* initialize */
32         memset(&e_ext, 0, sizeof(struct extension));
33         // *************** NOTE: also change value in read_extension() **************
34         e_ext.rights = 4; /* international */
35         e_ext.rx_gain = e_ext.tx_gain = 0;
36         e_state = EPOINT_STATE_IDLE;
37         e_ext.number[0] = '\0';
38         e_extension_interface[0] = '\0';
39         memset(&e_callerinfo, 0, sizeof(struct caller_info));
40         memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
41         memset(&e_connectinfo, 0, sizeof(struct connect_info));
42         memset(&e_redirinfo, 0, sizeof(struct redir_info));
43         memset(&e_capainfo, 0, sizeof(struct capa_info));
44         e_start = e_stop = 0;
45         e_origin = origin;
46         e_ruleset = ruleset_main;
47         if (e_ruleset)
48                 e_rule = e_ruleset->rule_first;
49         e_rule_nesting = 0;
50         e_action = NULL;
51         e_action_timeout = 0;
52         e_match_timeout = 0;
53         e_match_to_action = NULL;
54         e_select = 0;
55         e_extdialing = e_dialinginfo.id;
56 //        e_knocking = 0;
57 //        e_knocktime = 0;
58         e_hold = 0;
59 //        e_join_tone[0] = e_hold_tone[0] = '\0';
60         e_join_pattern /*= e_hold_pattern*/ = 0;
61         e_redial = 0;
62         e_tone[0] = '\0';
63         e_adminid = 0; // will be set, if call was initiated via admin socket
64         e_powerdialing = 0;
65         e_powerdelay = 0;
66         e_powerlimit = 0;
67         e_callback = 0;
68         e_cbdialing[0] = '\0';
69         e_cbcaller[0] = '\0';
70         e_cbto[0] = '\0';
71         memset(&e_callbackinfo, 0, sizeof(struct caller_info));
72         e_connectedmode = 0;
73         e_dtmf = 0;
74         e_dtmf_time = 0;
75         e_dtmf_last = 0;
76         e_enablekeypad = 0;
77         e_cfnr_release = 0;
78         e_cfnr_call = 0;
79         e_password_timeout = 0;
80         e_multipoint_cause = 0;
81         e_multipoint_location = 0;
82         e_dialing_queue[0] = '\0';
83         e_crypt = CRYPT_OFF;
84         e_crypt_state = CM_ST_NULL;
85         e_crypt_keyengine_busy = 0;
86         e_crypt_info[0] = '\0'; 
87         e_overlap = 0;
88         e_vbox[0] = '\0';
89         e_tx_state = NOTIFY_STATE_ACTIVE;
90         e_rx_state = NOTIFY_STATE_ACTIVE;
91         e_join_cause = e_join_location = 0;
92 /*********************************
93  *********************************
94  ********* ATTENTION *************
95  *********************************
96  *********************************/
97 /* if you add new values, that must be initialized, also check if they must
98  * be initialized when doing callback
99  */
100
101 }
102
103 /*
104  * EpointAppPBX destructor
105  */
106 EndpointAppPBX::~EndpointAppPBX(void)
107 {
108         class EndpointAppPBX *temp, **tempp;
109
110         /* detach */
111         temp =apppbx_first;
112         tempp = &apppbx_first;
113         while(temp) {
114                 if (temp == this)
115                         break;
116
117                 tempp = &temp->next;
118                 temp = temp->next;
119         }
120         if (temp == 0)
121                 FATAL("Endpoint not in endpoint's list.\n");
122         *tempp = next;
123
124 }
125
126
127 /*
128  * trace header for application
129  */
130 void EndpointAppPBX::trace_header(const char *name, int direction)
131 {
132         struct trace _trace;
133
134         char msgtext[sizeof(_trace.name)];
135
136         SCPY(msgtext, name);
137
138         /* init trace with given values */
139         start_trace(0,
140                     NULL,
141                     numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
142                     e_dialinginfo.id,
143                     direction,
144                     CATEGORY_EP,
145                     ea_endpoint->ep_serial,
146                     msgtext);
147 }
148
149
150 EPOINT_STATE_NAMES
151
152 /* set new endpoint state
153  */
154 void EndpointAppPBX::new_state(int state)
155 {
156 #if 0
157         if (e_state != state) {
158                 trace_header("NEW STATE", DIRECTION_NONE);
159                 add_trace("state", "old", "%s", state_name[e_state]);
160                 add_trace("state", "new", "%s", state_name[state]);
161                 end_trace();
162         }
163 #endif
164         e_state = state;
165 }
166
167
168 /* release join and port (as specified)
169  */
170 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
171 {
172         struct port_list *portlist;
173         struct lcr_msg *message;
174         char cause[16];
175
176         /* message to test call */
177         admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
178
179         /* if a release is pending */
180         if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
181                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
182                 if (ea_endpoint->ep_join_id) {
183                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
184                         message->param.disconnectinfo.cause = joincause;
185                         message->param.disconnectinfo.location = joinlocation;
186                         message_put(message);
187                         ea_endpoint->ep_join_id = 0;
188                 }
189                 e_join_pattern = 0;
190 #if 0
191                 if (release != RELEASE_PORT_JOINONLY) {
192                         if (e_hold_id)
193                                 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
194                         e_hold_id = 0;
195                 }
196 #endif
197         }
198         if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
199                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
200                 while((portlist = ea_endpoint->ep_portlist)) {
201                         if (portlist->port_id) {
202                                 SPRINT(cause, "cause_%02x", portcause);
203                                 set_tone(portlist, cause);
204                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
205                                 message->param.disconnectinfo.cause = portcause;
206                                 message->param.disconnectinfo.location = portlocation;
207                                 message_put(message);
208                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
209                         }
210                         ea_endpoint->free_portlist(portlist);
211                 }
212
213                 /* if callback is enabled, call back with the given caller id */
214                 if (e_callback) {
215                         /* reset some stuff */
216                         new_state(EPOINT_STATE_IDLE);
217                         memset(&e_connectinfo, 0, sizeof(struct connect_info));
218                         memset(&e_redirinfo, 0, sizeof(struct redir_info));
219                         e_start = e_stop = 0;
220                         e_ruleset = ruleset_main;
221                         if (e_ruleset)
222                                 e_rule = e_ruleset->rule_first;
223                         e_action = NULL;
224                         e_action_timeout = 0;
225                         e_match_timeout = 0;
226                         e_match_to_action = NULL;
227                         //e_select = 0;
228                         e_extdialing = e_dialinginfo.id;
229                         e_connectedmode = 0;
230                         e_dtmf = 0;
231                         e_dtmf_time = 0;
232                         e_dtmf_last = 0;
233                         e_enablekeypad = 0;
234                         e_cfnr_release = 0;
235                         e_cfnr_call = 0;
236                         e_multipoint_cause = 0;
237                         e_multipoint_location = 0;
238                         e_dialing_queue[0] = '\0';
239                         e_crypt = 0;
240                         e_crypt_state = CM_ST_NULL;
241                         e_crypt_keyengine_busy = 0;
242                         e_crypt_info[0] = '\0'; 
243                         e_tone[0] = '\0';
244                         e_overlap = 0;
245                         e_vbox[0] = '\0';
246                         e_tx_state = NOTIFY_STATE_ACTIVE;
247                         e_rx_state = NOTIFY_STATE_ACTIVE;
248                         e_join_cause = e_join_location = 0;
249                         e_rule_nesting = 0;
250                         /* the caller info of the callback user */
251                         memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
252                         memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
253                         /* create dialing by callerinfo */
254                         if (e_ext.number[0] && e_extension_interface[0]) {
255                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
256                                 /* create callback to the current terminal */
257                                 SCPY(e_dialinginfo.id, e_ext.number);
258                                 SCPY(e_dialinginfo.interfaces, e_extension_interface);
259                                 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
260                                 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
261                         } else {
262                                 if (e_cbto[0]) {
263                                         SCPY(e_dialinginfo.id, e_cbto);
264                                 } else {
265                                         /* numberrize caller id and use it to dial to the callback */
266                                         SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
267                                 }
268                                 e_dialinginfo.itype = INFO_ITYPE_ISDN;
269                                 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
270                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
271                         }
272                         return;
273                 }
274
275                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
276                 ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
277                 return;
278         }
279 }
280
281
282 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
283 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
284 {
285         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");
286
287         /* caller id is not restricted, so we do nothing */
288         if (*present != INFO_PRESENT_RESTRICTED)
289                 return;
290
291         /* only extensions are restricted */
292         if (!ext->number[0])
293                 return;
294
295         /* if we enabled anonymouse ignore */
296         if (ext->anon_ignore)
297                 return;
298
299         /* else we remove the caller id */
300         if (id)
301                 id[0] = '\0';
302         if (ntype)
303                 *ntype = INFO_NTYPE_UNKNOWN;
304 //      if (screen)
305 //              *screen = INFO_SCREEN_USER;
306 // maybe we should not make voip address anonymous
307 //      if (voip)
308 //              voip[0] = '\0';
309 // maybe it's no fraud to present extension id
310 //      if (extension)
311 //              extension[0] = '\0';
312         if (name)
313                 name[0] = '\0';
314 }
315
316 /* used display message to display callerid as available */
317 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
318 {
319         static char display[81];
320
321         display[0] = '\0';
322         const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
323
324         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");
325
326         if (!id)
327                 id = "";
328         if (!extension)
329                 extension = "";
330         if (!name)
331                 name = "";
332
333         /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
334
335         /* internal extension's caller id */
336         if (extension[0] && e_ext.display_int) {
337                 if (!display[0])
338                         SCAT(display, extension);
339                 if (display[0])
340                         SCAT(display, " ");
341                 if (itype == INFO_ITYPE_VBOX)
342                         SCAT(display, "(vbox)");
343                 else
344                         SCAT(display, "(int)");
345         }
346
347         /* external caller id */
348         if (!extension[0] && e_ext.display_ext) {
349                 if (!display[0]) {
350                         if (!cid[0]) {
351                                 if (present == INFO_PRESENT_RESTRICTED)
352                                         SCAT(display, "anonymous");
353                                 else
354                                         SCAT(display, "unknown");
355                         }
356                         else
357                                 SCAT(display, cid);
358                 }
359         }
360
361         /* display if callerid is anonymouse but available due anon-ignore */
362         if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
363                 if (!cid[0])
364                         SCAT(display, "unknown");
365                 else 
366                         SCAT(display, cid);
367                 SCAT(display, " anon");
368         }
369
370         /* display if callerid is anonymouse but available due anon-ignore */
371         if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
372                 if (!display[0]) {
373                         if (!id[0]) {
374                                 if (present == INFO_PRESENT_RESTRICTED)
375                                         SCAT(display, "anonymous");
376                                 else
377                                         SCAT(display, "unknown");
378                         }
379                         else
380                                 SCAT(display, cid);
381                 }
382                 SCAT(display, " fake");
383         }
384
385         /* caller name */
386         if (name[0] && e_ext.display_name) {
387                 if (!display[0] && cid[0])
388                                 SCAT(display, cid);
389                 if (display[0])
390                                 SCAT(display, " ");
391                 SCAT(display, name);
392         }
393
394         return(display);
395 }
396
397 /*
398  * uses the current state to notify activity
399  */
400 void EndpointAppPBX::notify_active(void)
401 {
402         struct port_list *portlist = ea_endpoint->ep_portlist;
403         struct lcr_msg *message;
404         int notify = 0;
405
406         switch(e_tx_state) {
407                 case NOTIFY_STATE_ACTIVE:
408                 /* we are already active, so we don't do anything */
409                 break;
410
411                 case NOTIFY_STATE_SUSPEND:
412                 notify = INFO_NOTIFY_USER_RESUMED;
413                 while(portlist) {
414                         set_tone(portlist, NULL);
415                         portlist = portlist->next;
416                 }
417                 portlist = ea_endpoint->ep_portlist;
418                 break;
419
420                 case NOTIFY_STATE_HOLD:
421                 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
422                 while(portlist) {
423                         set_tone(portlist, NULL);
424                         portlist = portlist->next;
425                 }
426                 portlist = ea_endpoint->ep_portlist;
427                 break;
428
429                 case NOTIFY_STATE_CONFERENCE:
430                 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
431                 while(portlist) {
432                         set_tone(portlist, NULL);
433                         portlist = portlist->next;
434                 }
435                 portlist = ea_endpoint->ep_portlist;
436                 break;
437
438                 default:
439                 PERROR("unknown e_tx_state = %d\n", e_tx_state);
440         }
441
442         if (notify)
443         while(portlist) {
444                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
445                 message->param.notifyinfo.notify = notify;
446                 message_put(message);
447                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
448                 portlist = portlist->next;
449         }
450 }
451
452
453 /*
454  * keypad functions during call. one example to use this is to put a call on hold or start a conference
455  */
456 void EndpointAppPBX::keypad_function(char digit)
457 {
458
459         /* we must be in a call, in order to send messages to the call */
460         if (e_ext.number[0] == '\0') {
461                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
462                 return;
463         }
464
465         switch(digit) {
466                 /* join conference */
467                 case '3':
468                 if (ea_endpoint->ep_join_id == 0) {
469                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
470                         break;
471                 }
472                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
473                 join_join();
474                 break;
475
476                 /* crypt shared */
477                 case '7':
478                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
479                 encrypt_shared();
480                 break;
481
482                 /* crypt key-exchange */
483                 case '8':
484                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
485                 encrypt_keyex();
486                 break;
487
488                 /* crypt off */
489                 case '9':
490                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
491                 encrypt_off();
492                 break;
493
494                 default:        
495                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
496         }
497 }
498
499
500 /* set tone pattern for port */
501 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
502 {
503         struct lcr_msg *message;
504
505         if (!tone)
506                 tone = "";
507
508         /* store for suspended processes */
509         SCPY(e_tone, tone);
510
511
512         if (e_join_pattern /* pattern are provided */
513          && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
514          && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
515          && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
516          && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
517          && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
518          && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
519          && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
520          && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
521          && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
522          && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
523          && tone[0] && !!strncmp(tone,"crypt_*",6)) {
524                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
525                 tone = "";
526         }
527
528         if (portlist) {
529                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
530                 SCPY(message->param.tone.dir, e_ext.tones_dir);
531                 SCPY(message->param.tone.name, tone);
532                 message_put(message);
533                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
534         } else {
535                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
536                 return;
537         }
538 }
539
540
541 /*
542  * hunts an mISDNport that is available for an outgoing call
543  * if no ifname was given, any interface that is not an extension
544  * will be searched.
545  */
546 struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
547 {
548         struct interface *interface;
549         struct interface_port *ifport, *ifport_start;
550         struct select_channel *selchannel; 
551         struct mISDNport *mISDNport;
552         int index, i;
553         int there_is_an_external = 0;
554
555         interface = interface_first;
556
557         /* first find the given interface or, if not given, one with no extension */
558         checknext:
559         if (!interface) {
560                 if (!there_is_an_external && !(ifname && ifname[0])) {
561                         trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
562                         add_trace("info", NULL, "Add 'external' parameter to interface.conf.");
563                         end_trace();
564                 }
565                 return(NULL);
566         }
567
568         /* check for given interface */
569         if (ifname && ifname[0]) {
570                 if (!strcasecmp(interface->name, ifname)) {
571                         /* found explicit interface */
572                         trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
573                         add_trace("interface", NULL, "%s", ifname);
574                         end_trace();
575                         goto foundif;
576                 }
577
578         } else {
579                 if (interface->external) {
580                         there_is_an_external = 1;
581                         /* found non extension */
582                         trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
583                         add_trace("interface", NULL, "%s", interface->name);
584                         end_trace();
585                         goto foundif;
586                 }
587         }
588
589         interface = interface->next;
590         goto checknext;
591 foundif:
592
593         /* see if interface has ports */
594         if (!interface->ifport) {
595                 /* no ports */
596                 trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
597                 add_trace("interface", NULL, "%s", interface->name);
598                 end_trace();
599                 interface = interface->next;
600                 goto checknext;
601         }
602
603         /* select port by algorithm */
604         ifport_start = interface->ifport;
605         index = 0;
606         if (interface->hunt == HUNT_ROUNDROBIN) {
607                 while(ifport_start->next && index<interface->hunt_next) {
608                         ifport_start = ifport_start->next;
609                         index++;
610                 }
611                 trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
612                 add_trace("port", NULL, "%d", ifport_start->portnum);
613                 add_trace("position", NULL, "%d", index);
614                 end_trace();
615         }
616
617         /* loop ports */
618         ifport = ifport_start;
619         nextport:
620
621         /* see if port is available */
622         if (!ifport->mISDNport) {
623                 trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
624                 add_trace("port", NULL, "%d", ifport->portnum);
625                 add_trace("position", NULL, "%d", index);
626                 end_trace();
627                 goto portbusy;
628         }
629         mISDNport = ifport->mISDNport;
630
631         /* see if port is administratively blocked */
632         if (ifport->block) {
633                 trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
634                 add_trace("port", NULL, "%d", ifport->portnum);
635                 add_trace("position", NULL, "%d", index);
636                 end_trace();
637                 goto portbusy;
638         }
639
640         /* see if link is up on PTP*/
641         if (mISDNport->l2hold && mISDNport->l2link<1) {
642                 trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
643                 add_trace("port", NULL, "%d", ifport->portnum);
644                 add_trace("position", NULL, "%d", index);
645                 end_trace();
646                 goto portbusy;
647         }
648
649         /* check for channel form selection list */
650         *channel = 0;
651         selchannel = ifport->out_channel;
652         while(selchannel) {
653                 switch(selchannel->channel) {
654                         case CHANNEL_FREE: /* free channel */
655                         if (mISDNport->b_reserved >= mISDNport->b_num)
656                                 break; /* all channel in use or reserverd */
657                         /* find channel */
658                         i = 0;
659                         while(i < mISDNport->b_num) {
660                                 if (mISDNport->b_port[i] == NULL) {
661                                         *channel = i+1+(i>=15);
662                                         trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
663                                         add_trace("port", NULL, "%d", ifport->portnum);
664                                         add_trace("position", NULL, "%d", index);
665                                         add_trace("channel", NULL, "%d", *channel);
666                                         end_trace();
667                                         break;
668                                 }
669                                 i++;
670                         }
671                         if (*channel)
672                                 break;
673                         trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
674                         add_trace("port", NULL, "%d", ifport->portnum);
675                         add_trace("position", NULL, "%d", index);
676                         end_trace();
677                         break;
678
679                         case CHANNEL_ANY: /* don't ask for channel */
680                         if (mISDNport->b_reserved >= mISDNport->b_num) {
681                                 trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
682                                 add_trace("port", NULL, "%d", ifport->portnum);
683                                 add_trace("position", NULL, "%d", index);
684                                 add_trace("total", NULL, "%d", mISDNport->b_num);
685                                 add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
686                                 end_trace();
687                                 break; /* all channel in use or reserverd */
688                         }
689                         trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
690                         add_trace("port", NULL, "%d", ifport->portnum);
691                         add_trace("position", NULL, "%d", index);
692                         end_trace();
693                         *channel = CHANNEL_ANY;
694                         break;
695
696                         case CHANNEL_NO: /* call waiting */
697                         trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
698                         add_trace("port", NULL, "%d", ifport->portnum);
699                         add_trace("position", NULL, "%d", index);
700                         end_trace();
701                         *channel = CHANNEL_NO;
702                         break;
703
704                         default:
705                         if (selchannel->channel<1 || selchannel->channel==16) {
706                                 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
707                                 add_trace("port", NULL, "%d", ifport->portnum);
708                                 add_trace("position", NULL, "%d", index);
709                                 add_trace("channel", NULL, "%d", selchannel->channel);
710                                 end_trace();
711                                 break; /* invalid channels */
712                         }
713                         i = selchannel->channel-1-(selchannel->channel>=17);
714                         if (i >= mISDNport->b_num) {
715                                 trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
716                                 add_trace("port", NULL, "%d", ifport->portnum);
717                                 add_trace("position", NULL, "%d", index);
718                                 add_trace("channel", NULL, "%d", selchannel->channel);
719                                 add_trace("channels", NULL, "%d", mISDNport->b_num);
720                                 end_trace();
721                                 break; /* channel not in port */
722                         }
723                         if (mISDNport->b_port[i] == NULL) {
724                                 *channel = selchannel->channel;
725                                 trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
726                                 add_trace("port", NULL, "%d", ifport->portnum);
727                                 add_trace("position", NULL, "%d", index);
728                                 add_trace("channel", NULL, "%d", *channel);
729                                 end_trace();
730                                 break;
731                         }
732                         break;
733                 }
734                 if (*channel)
735                         break; /* found channel */
736                 selchannel = selchannel->next;
737         }
738
739         /* if channel was found, return mISDNport and channel */
740         if (*channel) {
741                 /* setting next port to start next time */
742                 if (interface->hunt == HUNT_ROUNDROBIN) {
743                         index++;
744                         if (!ifport->next)
745                                 index = 0;
746                         interface->hunt_next = index;
747                 }
748                 
749                 return(mISDNport);
750         }
751
752         trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
753         add_trace("port", NULL, "%d", ifport->portnum);
754         add_trace("position", NULL, "%d", index);
755         end_trace();
756
757         portbusy:
758         /* go next port, until all ports are checked */
759         index++;
760         ifport = ifport->next;
761         if (!ifport) {
762                 index = 0;
763                 ifport = interface->ifport;
764         }
765         if (ifport != ifport_start)
766                 goto nextport;
767
768         if (!ifname) {
769                 interface = interface->next;
770                 goto checknext;
771         }
772
773         return(NULL); /* no port found */
774 }
775
776 /* outgoing setup to port(s)
777  * ports will be created and a setup is sent if everything is ok. otherwhise
778  * the endpoint is destroyed.
779  */
780 void EndpointAppPBX::out_setup(void)
781 {
782         struct dialing_info     dialinginfo;
783         class Port              *port;
784         struct port_list        *portlist;
785         struct lcr_msg          *message;
786         int                     anycall = 0;
787         int                     cause = CAUSE_RESSOURCEUNAVAIL;
788         const char              *p;
789         char                    cfp[64];
790         struct mISDNport        *mISDNport;
791         char                    portname[32];
792         char                    *dirname;
793         class EndpointAppPBX    *atemp;
794 //      char                    allowed_ports[256];
795 //      char                    exten[256];
796         char                    ifname[sizeof(e_ext.interfaces)],
797                                 number[256];
798         struct port_settings    port_settings;
799         int                     channel = 0;
800         int                     earlyb;
801         int                     mode = B_MODE_TRANSPARENT;
802
803         /* set bchannel mode */
804         mode = e_capainfo.source_mode;
805
806         /* create settings for creating port */
807         memset(&port_settings, 0, sizeof(port_settings));
808         if (e_ext.tones_dir)
809                 SCPY(port_settings.tones_dir, e_ext.tones_dir);
810         else
811                 SCPY(port_settings.tones_dir, options.tones_dir);
812         port_settings.no_seconds = e_ext.no_seconds;
813         
814         /* 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 */
815
816         /* check what dialinginfo.itype we got */
817         switch(e_dialinginfo.itype) {
818                 /* *********************** call to extension or vbox */
819                 case INFO_ITYPE_ISDN_EXTENSION:
820                 /* check if we deny incoming calls when we use an extension */
821                 if (e_ext.noknocking) {
822                         atemp = apppbx_first;
823                         while(atemp) {
824                                 if (atemp != this)
825                                 if (!strcmp(atemp->e_ext.number, e_ext.number))
826                                         break;
827                                 atemp = atemp->next;
828                         }
829                         if (atemp) {
830                                 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
831                                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
832                                 return; /* must exit here */
833                         }
834                 }
835                 /* FALL THROUGH !!!! */
836                 case INFO_ITYPE_VBOX:
837                 /* get dialed extension's info */
838 //              SCPY(exten, e_dialinginfo.id);
839 //              if (strchr(exten, ','))
840 //                      *strchr(exten, ',') = '\0';
841 //              if (!read_extension(&e_ext, exten))
842                 if (!read_extension(&e_ext, e_dialinginfo.id)) {
843                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
844                         release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
845                         return; /* must exit here */
846                 }
847
848                 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
849                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
850                         p = "vbox";
851                         goto vbox_only;
852                 }
853
854                 /* string from unconditional call forward (cfu) */
855                 p = e_ext.cfu;
856                 if (*p) {
857                         /* present to forwarded party */
858                         if (e_ext.anon_ignore && e_callerinfo.id[0]) {
859                                 e_callerinfo.present = INFO_PRESENT_ALLOWED;
860                         }
861                         if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
862                                 goto cfu_only;
863                 }
864
865                 /* string from busy call forward (cfb) */
866                 p = e_ext.cfb;
867                 if (*p) {
868                         class EndpointAppPBX *checkapp = apppbx_first;
869                         while(checkapp) {
870                                 if (checkapp != this) { /* any other endpoint except our own */
871                                         if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
872                                                 /* present to forwarded party */
873                                                 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
874                                                         e_callerinfo.present = INFO_PRESENT_ALLOWED;
875                                                 }
876                                                 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
877                                                         goto cfb_only;
878                                         }
879                                 }
880                                 checkapp = checkapp->next;
881                         }
882                 }
883
884                 /* string from no-response call forward (cfnr) */
885                 p = e_ext.cfnr;
886                 if (*p) {
887                         /* when cfnr is done, out_setup() will setup the call */
888                         if (e_cfnr_call) {
889                                 /* present to forwarded party */
890                                 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
891                                         e_callerinfo.present = INFO_PRESENT_ALLOWED;
892                                 }
893                                 goto cfnr_only;
894                         }
895                         if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
896                                 e_cfnr_release = now + e_ext.cfnr_delay;
897                                 e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
898                                 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);
899                         }
900                 }
901
902                 /* call to all internal interfaces */
903                 p = e_ext.interfaces;
904                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
905                 while(*p) {
906                         ifname[0] = '\0';
907                         while(*p!=',' && *p!='\0')
908                                 if (*p > ' ')
909                                         SCCAT(ifname, *p++);
910                         if (*p == ',')
911                                 p++;
912                         /* found interface */
913                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
914                         /* hunt for mISDNport and create Port */
915                         mISDNport = hunt_port(ifname, &channel);
916                         if (!mISDNport) {
917                                 trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
918                                 add_trace("interface", NULL, "%s", ifname);
919                                 end_trace();
920                                 continue;
921                         }
922                         /* creating INTERNAL port */
923                         SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
924                         if (!mISDNport->gsm)
925                                 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
926                         else
927 #ifdef WITH_GSM
928                                 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
929 #else
930                                 port = NULL;
931 #endif
932                         if (!port)
933                                 FATAL("No memory for Port instance\n");
934                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
935                         memset(&dialinginfo, 0, sizeof(dialinginfo));
936                         SCPY(dialinginfo.id, e_dialinginfo.id);
937                         dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
938                         dialinginfo.ntype = e_dialinginfo.ntype;
939                         /* create port_list relation */
940                         portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
941                         if (!portlist) {
942                                 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
943                                 delete port;
944                                 goto check_anycall_intern;
945                         }
946                         /* directory.list */
947                         if (e_callerinfo.id[0] && e_ext.display_name) {
948                                 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
949                                 if (dirname)
950                                         SCPY(e_callerinfo.name, dirname);
951                         }
952 //                      dss1 = (class Pdss1 *)port;
953                         /* message */
954 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
955                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
956                         memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
957                         memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
958                         memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
959                         memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
960 //terminal                      SCPY(message->param.setup.from_terminal, e_ext.number);
961 //terminal                      if (e_dialinginfo.id)
962 //terminal                              SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
963                         /* handle restricted caller ids */
964                         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);
965                         apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
966                         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);
967                         /* display callerid if desired for extension */
968                         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));
969 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
970                         /* use cnip, if enabld */
971         //              if (!e_ext.centrex)
972         //                      message->param.setup.callerinfo.name[0] = '\0';
973                         /* screen clip if prefix is required */
974                         if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
975                                 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
976                                 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
977                                 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
978                         }
979                         if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
980                                 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
981                                 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
982                                 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
983                         }
984                         /* use internal caller id */
985                         if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
986                                 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
987                                 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
988                                 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
989                         }
990                         message_put(message);
991                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
992                         anycall = 1;
993                 }
994
995                 /* string from parallel call forward (cfp) */
996                 p = e_ext.cfp;
997                 if (*p) {
998                         if (e_ext.anon_ignore && e_callerinfo.id[0]) {
999                                 e_callerinfo.present = INFO_PRESENT_ALLOWED;
1000                                 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
1001                         }
1002                 }
1003
1004                 vbox_only: /* entry point for answering machine only */
1005                 cfu_only: /* entry point for cfu */
1006                 cfb_only: /* entry point for cfb */
1007                 cfnr_only: /* entry point for cfnr */
1008                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
1009 //              i=0;
1010                 while(*p) {
1011                         earlyb = 0;
1012                         /* only if vbox should be dialed, and terminal is given */
1013                         if (!strcmp(p, "vbox") && e_ext.number[0]) {
1014                                 /* go to the end of p */
1015                                 p += strlen(p);
1016
1017                                 /* answering vbox call */
1018                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
1019                                 /* alloc port */
1020                                 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
1021                                         FATAL("No memory for VBOX Port instance\n");
1022                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
1023                                 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
1024                         } else {
1025                                 cfp[0] = '\0';
1026                                 while(*p!=',' && *p!='\0')
1027                                         SCCAT(cfp, *p++);
1028                                 if (*p == ',')
1029                                         p++;
1030                                 /* external call */
1031                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
1032                                 /* hunt for mISDNport and create Port */
1033                                 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1034                                 if (mISDNport) {
1035                                         /* creating EXTERNAL port*/
1036                                         SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1037                                                 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1038                                         if (!port)
1039                                                 FATAL("No memory for Port instance\n");
1040                                         earlyb = mISDNport->earlyb;
1041                                 } else {
1042                                         port = NULL;
1043                                         trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1044                                         add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1045                                         end_trace();
1046                                 }
1047                         }
1048                         if (!port) {
1049                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
1050                                 goto check_anycall_intern;
1051                         }
1052                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
1053                         memset(&dialinginfo, 0, sizeof(dialinginfo));
1054                         SCPY(dialinginfo.id, cfp);
1055                         dialinginfo.itype = INFO_ITYPE_ISDN;
1056                         dialinginfo.ntype = e_dialinginfo.ntype;
1057                         portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1058                         if (!portlist) {
1059                                 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1060                                 delete port;
1061                                 goto check_anycall_intern;
1062                         }
1063 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1064                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1065                         memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1066                         memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1067                         memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1068                         /* if clip is hidden */
1069                         if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
1070                                 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
1071                                 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
1072                                 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
1073                                 message->param.setup.callerinfo.present = e_ext.callerid_present;
1074                                 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
1075                         }
1076                         memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1077 //terminal                      SCPY(message->param.setup.from_terminal, e_ext.number);
1078 //terminal                      if (e_dialinginfo.id)
1079 //terminal                              SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1080                                 /* handle restricted caller ids */
1081                         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);
1082                         apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1083                         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);
1084                         /* display callerid if desired for extension */
1085                         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));
1086                         message_put(message);
1087                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1088                         anycall = 1;
1089                 }
1090
1091                 check_anycall_intern:
1092                 /* now we have all ports created */
1093                 if (!anycall) {
1094                         trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
1095                         end_trace();
1096                         if (!ea_endpoint->ep_join_id)
1097                                 break;
1098                         release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1099                         return; /* must exit here */
1100                 }
1101                 break;
1102
1103                 /* *********************** external call */
1104                 default:
1105                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
1106                 /* call to extenal interfaces */
1107                 p = e_dialinginfo.id;
1108                 do {
1109                         number[0] = '\0';
1110                         while(*p!=',' && *p!='\0')
1111                                 SCCAT(number, *p++);
1112                         if (*p == ',')
1113                                 p++;
1114                         /* found number */
1115                         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");
1116                         /* hunt for mISDNport and create Port */
1117                         /* hunt for mISDNport and create Port */
1118                         mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1119                         if (!mISDNport) {
1120                                 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1121                                 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1122                                 end_trace();
1123                                 goto check_anycall_extern;
1124                         }
1125                         /* creating EXTERNAL port*/
1126                         SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1127                         if (!mISDNport->gsm)
1128                                 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1129                         else
1130 #ifdef WITH_GSM
1131                                 port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
1132 #else
1133                                 port = NULL;
1134 #endif
1135                         if (!port)
1136                                 FATAL("No memory for Port instance\n");
1137                         earlyb = mISDNport->earlyb;
1138                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1139                         memset(&dialinginfo, 0, sizeof(dialinginfo));
1140                         SCPY(dialinginfo.id, number);
1141                         dialinginfo.itype = INFO_ITYPE_ISDN;
1142                         dialinginfo.ntype = e_dialinginfo.ntype;
1143                         portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
1144                         if (!portlist) {
1145                                 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1146                                 delete port;
1147                                 goto check_anycall_extern;
1148                         }
1149 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1150                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1151                         memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1152                         SCPY(message->param.setup.dialinginfo.id, number);
1153                         memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1154                         memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1155                         memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1156 //terminal                      SCPY(message->param.setup.from_terminal, e_ext.number);
1157 //terminal                      if (e_dialinginfo.id)
1158 //terminal                              SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1159                                 /* handle restricted caller ids */
1160                         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);
1161                         apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
1162                         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);
1163                         /* display callerid if desired for extension */
1164                         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));
1165                         message_put(message);
1166                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1167                         anycall = 1;
1168                 } while(*p);
1169
1170                 check_anycall_extern:
1171                 /* now we have all ports created */
1172                 if (!anycall) {
1173                         trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1174                         end_trace();
1175                         if (!ea_endpoint->ep_join_id)
1176                                 break;
1177                         release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1178                         return; /* must exit here */
1179                 }
1180                 break;
1181         }
1182
1183 }
1184
1185
1186 /* handler for endpoint
1187  */
1188
1189 extern int quit;
1190 int EndpointAppPBX::handler(void)
1191 {
1192         if (e_crypt_state!=CM_ST_NULL) {
1193                 cryptman_handler();
1194         }
1195
1196         /* process answering machine (play) handling */
1197         if (e_action) {
1198                 if (e_action->index == ACTION_VBOX_PLAY)
1199                         vbox_handler();
1200
1201                 /* process action timeout */
1202                 if (e_action_timeout)
1203                 if (now_d >= e_action_timeout) {
1204                         if (e_state!=EPOINT_STATE_CONNECT) {
1205                                 e_redial = 0;
1206                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
1207                                 e_multipoint_cause = 0;
1208                                 e_multipoint_location = 0;
1209                                 new_state(EPOINT_STATE_IN_OVERLAP);
1210                                 e_join_pattern = 0;
1211                                 process_dialing();
1212                                 return(1); /* we must exit, because our endpoint might be gone */
1213                         } else
1214                                 e_action_timeout = 0;
1215                 }
1216         } else {
1217                 /* process action timeout */
1218                 if (e_match_timeout)
1219                 if (now_d >= e_match_timeout) {
1220                         e_redial = 0;
1221                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
1222                         process_dialing();
1223                         return(1); /* we must exit, because our endpoint might be gone */
1224                 }
1225         }
1226
1227
1228         /* process redialing (epoint redials to port) */
1229         if (e_redial) {
1230                 if (now_d >= e_redial) {
1231                         e_redial = 0;
1232                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
1233
1234                         new_state(EPOINT_STATE_OUT_SETUP);
1235                         /* call special setup routine */
1236                         out_setup();
1237
1238                         return(1);
1239                 }
1240         }
1241
1242         /* process powerdialing (epoint redials to epoint) */
1243         if (e_powerdialing > 0) {
1244                 if (now_d >= e_powerdialing) {
1245                         e_powerdialing = -1; /* leave power dialing on */
1246                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
1247
1248                         /* redial */
1249                         e_ruleset = ruleset_main;
1250                         if (e_ruleset)
1251                                 e_rule = e_ruleset->rule_first;
1252                         e_action = NULL;
1253                         new_state(EPOINT_STATE_IN_OVERLAP);
1254                         process_dialing();
1255                         return(1);
1256                 }
1257         }
1258
1259         /* process call forward no response */
1260         if (e_cfnr_release) {
1261                 struct port_list *portlist;
1262                 struct lcr_msg *message;
1263
1264                 if (now >= e_cfnr_release) {
1265                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
1266                         e_cfnr_release = 0;
1267
1268                         /* release all ports */
1269                         while((portlist = ea_endpoint->ep_portlist)) {
1270                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1271                                 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1272                                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1273                                 message_put(message);
1274                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1275                                 ea_endpoint->free_portlist(portlist);
1276                         }
1277                         /* put on hold */
1278                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1279                         message->param.audiopath = 0;
1280                         message_put(message);
1281                         /* indicate no patterns */
1282                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1283                         message_put(message);
1284                         /* set setup state, since we have no response from the new join */
1285                         new_state(EPOINT_STATE_OUT_SETUP);
1286                 }
1287         } else
1288         if (e_cfnr_call) {
1289                 if (now >= e_cfnr_call) {
1290                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
1291                         out_setup();
1292                         e_cfnr_call = 0;
1293                 }
1294         }
1295
1296         /* handle connection to user */
1297         if (e_state == EPOINT_STATE_IDLE) {
1298                 /* epoint is idle, check callback */
1299                 if (e_callback)
1300                 if (now_d >= e_callback) {
1301                         e_callback = 0; /* done with callback */
1302                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
1303                         new_state(EPOINT_STATE_OUT_SETUP);
1304                         out_setup();
1305                         return(1);
1306                 }
1307         }
1308
1309         /* check for password timeout */
1310         if (e_action)
1311         if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE) {
1312                 struct port_list *portlist;
1313
1314                 if (now >= e_password_timeout) {
1315                         e_ruleset = ruleset_main;
1316                         if (e_ruleset)
1317                                 e_rule = e_ruleset->rule_first;
1318                         e_action = NULL;
1319                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
1320                         trace_header("PASSWORD timeout", DIRECTION_NONE);
1321                         end_trace();
1322                         e_connectedmode = 0;
1323                         e_dtmf = 0;
1324                         new_state(EPOINT_STATE_OUT_DISCONNECT);
1325                         portlist = ea_endpoint->ep_portlist;
1326                         if (portlist) {
1327                                 message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1328                                 set_tone(portlist, "cause_10");
1329                         }
1330                         return(1);
1331                 }
1332         }
1333  
1334         return(0);
1335 }
1336
1337
1338 /* doing a hookflash */
1339 void EndpointAppPBX::hookflash(void)
1340 {
1341         class Port *port;
1342
1343         /* be sure that we are active */
1344         notify_active();
1345         e_tx_state = NOTIFY_STATE_ACTIVE;
1346
1347         trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1348         end_trace();
1349         if (ea_endpoint->ep_use > 1) {
1350                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1351                 return;
1352         }
1353         /* dialtone after pressing the hash key */
1354         process_hangup(e_join_cause, e_join_location);
1355         e_multipoint_cause = 0;
1356         e_multipoint_location = 0;
1357         port = find_port_id(ea_endpoint->ep_portlist->port_id);
1358         if (port) {
1359                 port->set_echotest(0);
1360         }
1361         if (ea_endpoint->ep_join_id) {
1362                 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
1363         }
1364         e_ruleset = ruleset_main;
1365         if (e_ruleset)
1366                 e_rule = e_ruleset->rule_first;
1367         e_action = NULL;
1368         new_state(EPOINT_STATE_IN_OVERLAP);
1369         e_connectedmode = 1;
1370         SCPY(e_dialinginfo.id, e_ext.prefix);
1371         e_extdialing = e_dialinginfo.id;
1372         e_join_pattern = 0;
1373         if (e_dialinginfo.id[0]) {
1374                 set_tone(ea_endpoint->ep_portlist, "dialing");
1375                 process_dialing();
1376         } else {
1377                 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1378         }
1379         e_dtmf_time = now;
1380         e_dtmf_last = '\0';
1381 }
1382
1383
1384 /* messages from port
1385  */
1386 /* port MESSAGE_SETUP */
1387 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1388 {
1389         struct lcr_msg          *message;
1390         char                    buffer[256];
1391         int                     writeext;               /* flags need to write extension after modification */
1392         class Port              *port;
1393         struct interface        *interface;
1394
1395         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1396         
1397         portlist->port_type = param->setup.port_type;
1398         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
1399         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
1400         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
1401         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
1402 //      e_dtmf = param->setup.dtmf;
1403         /* screen incoming caller id */
1404         interface = interface_first;
1405         while(interface) {
1406                 if (!strcmp(e_callerinfo.interface, interface->name)) {
1407                         break;
1408                 }
1409                 interface = interface->next;
1410         }
1411         if (interface) {
1412                 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
1413                 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
1414         }
1415
1416         /* process extension */
1417         if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1418                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1419                 /* port makes call from extension */
1420                 SCPY(e_callerinfo.extension, e_callerinfo.id);
1421                 SCPY(e_ext.number, e_callerinfo.extension);
1422                 SCPY(e_extension_interface, e_callerinfo.interface);
1423         } else {
1424                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1425         }
1426
1427         if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1428                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1429
1430                 /* get extension's info about caller */
1431                 if (!read_extension(&e_ext, e_ext.number)) {
1432                         /* extension doesn't exist */
1433                         trace_header("EXTENSION (not created)", DIRECTION_IN);
1434                         add_trace("extension", NULL, "%s", e_ext.number);
1435                         end_trace();
1436                         message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1437                         new_state(EPOINT_STATE_OUT_DISCONNECT);
1438                         set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1439                         e_ext.number[0] = '\0'; /* no terminal */
1440                         return;
1441                 }
1442                 writeext = 0;
1443
1444                 /* put prefix (next) in front of e_dialinginfo.id */
1445                 if (e_ext.next[0]) {
1446                         SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1447                         SCPY(e_dialinginfo.id, buffer);
1448                         e_ext.next[0] = '\0';
1449                         writeext = 1;
1450                 } else if (e_ext.prefix[0]) {
1451                         SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1452                         SCPY(e_dialinginfo.id, buffer);
1453                 }
1454
1455                 /* screen caller id by extension's config */
1456                 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1457                 if (e_ext.name[0])
1458                         SCPY(e_callerinfo.name, e_ext.name);
1459                 /* use caller id (or if exist: id_next_call) for this call */
1460                 if (e_ext.id_next_call_present >= 0) {
1461                         SCPY(e_callerinfo.id, e_ext.id_next_call);
1462                         /* if we restrict the pesentation */
1463                         if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1464                                 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1465                         else    e_callerinfo.present = e_ext.id_next_call_present;
1466                         e_callerinfo.ntype = e_ext.id_next_call_type;
1467                         e_ext.id_next_call_present = -1;
1468                         writeext = 1;
1469                 } else {
1470                         SCPY(e_callerinfo.id, e_ext.callerid);
1471                         /* if we restrict the pesentation */
1472                         if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1473                                 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1474                         else    e_callerinfo.present = e_ext.callerid_present;
1475                         e_callerinfo.ntype = e_ext.callerid_type;
1476                 }
1477                 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1478
1479                 /* extension is written */
1480                 if (writeext)
1481                         write_extension(&e_ext, e_ext.number);
1482
1483                 /* set volume of rx and tx */
1484                 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1485                 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1486                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1487                         message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1488                         message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1489                         message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1490                         message_put(message);
1491                 }
1492
1493                 /* start recording if enabled */
1494                 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1495                         /* check if we are a terminal */
1496                         if (e_ext.number[0] == '\0')
1497                                 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1498                         else {
1499                                 port = find_port_id(portlist->port_id);
1500                                 if (port)
1501                                         port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1502                         }
1503                 }
1504         } else {
1505                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1506                 /* no terminal identification */
1507                 e_ext.number[0] = '\0';
1508                 e_extension_interface[0] = '\0';
1509                 memset(&e_ext, 0, sizeof(e_ext));
1510                 e_ext.rights = 4; /* right to dial internat */
1511         }
1512
1513         /* incoming call */
1514         e_ruleset = ruleset_main;
1515         if (e_ruleset)
1516                 e_rule = e_ruleset->rule_first;
1517         e_action = NULL;
1518         e_extdialing = e_dialinginfo.id;
1519         new_state(EPOINT_STATE_IN_SETUP);
1520         if (e_dialinginfo.id[0]) {
1521                 set_tone(portlist, "dialing");
1522         } else {
1523                 if (e_ext.number[0])
1524                         set_tone(portlist, "dialpbx");
1525                 else
1526                         set_tone(portlist, "dialtone");
1527         }
1528         process_dialing();
1529         if (e_state == EPOINT_STATE_IN_SETUP) {
1530                 /* request MORE info, if not already at higher state */
1531                 new_state(EPOINT_STATE_IN_OVERLAP);
1532                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1533                 message_put(message);
1534                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1535         }
1536 }
1537
1538 /* port MESSAGE_INFORMATION */
1539 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1540 {
1541         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1542
1543         /* ignore information message without digit information */
1544         if (!param->information.id[0])
1545                 return;
1546
1547         e_overlap = 1;
1548
1549         /* turn off dtmf detection, in case dtmf is sent with keypad information */
1550         if (e_dtmf) {
1551                 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1552                 end_trace();
1553                 e_dtmf = 0;
1554         }
1555
1556         /* if vbox_play is done, the information are just used as they come */
1557         if (e_action)
1558         if (e_action->index == ACTION_VBOX_PLAY) {
1559                 /* concat dialing string */
1560                 SCAT(e_dialinginfo.id, param->information.id);
1561                 process_dialing();
1562                 return;
1563         }
1564
1565         /* keypad when disconnect but in connected mode */
1566         if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1567                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1568                 /* processing keypad function */
1569                 if (param->information.id[0] == '0') {
1570                         hookflash();
1571                 }
1572                 return;
1573         }
1574
1575         /* keypad when connected */
1576         if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1577                 if (e_ext.keypad || e_enablekeypad) {
1578                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1579                         /* processing keypad function */
1580                         if (param->information.id[0] == '0') {
1581                                 hookflash();
1582                         }
1583                         if (param->information.id[0])
1584                                 keypad_function(param->information.id[0]);
1585                 } else {
1586                         if (e_ext.number[0])
1587                                 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1588                         else
1589                                 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1590                         end_trace();
1591                 }
1592                 return;
1593         }
1594         if (e_state != EPOINT_STATE_IN_OVERLAP) {
1595                 if (e_ext.number[0])
1596                         trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1597                 else
1598                         trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1599                 end_trace();
1600                 return;
1601         }
1602         if (!param->information.id[0])
1603                 return;
1604         if (e_dialinginfo.id[0]=='\0' && !e_action) {
1605                 set_tone(portlist, "dialing");
1606         }
1607         if (e_action)
1608         if (e_action->index==ACTION_OUTDIAL
1609          || e_action->index==ACTION_EXTERNAL
1610          || e_action->index==ACTION_REMOTE) {
1611                 if (!e_extdialing)
1612                         set_tone(portlist, "dialing");
1613                 else if (!e_extdialing[0])
1614                         set_tone(portlist, "dialing");
1615         }
1616         /* concat dialing string */
1617         SCAT(e_dialinginfo.id, param->information.id);
1618         process_dialing();
1619 }
1620
1621 /* port MESSAGE_DTMF */
1622 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1623 {
1624         /* only if dtmf detection is enabled */
1625         if (!e_dtmf) {
1626                 trace_header("DTMF (disabled)", DIRECTION_IN);
1627                 end_trace();
1628                 return;
1629         }
1630         trace_header("DTMF", DIRECTION_IN);
1631         add_trace("digit", NULL, "%c", param->dtmf);
1632         end_trace();
1633
1634 #if 0
1635 NOTE: vbox is now handled due to overlap state
1636         /* if vbox_play is done, the dtmf digits are just used as they come */
1637         if (e_action)
1638         if (e_action->index == ACTION_VBOX_PLAY) {
1639                 /* concat dialing string */
1640                 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1641                         e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1642                         e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1643                         process_dialing();
1644                 }
1645                 /* continue to process *X# sequences */
1646         }
1647 #endif
1648
1649         /* check for *X# sequence */
1650         if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1651                 if (e_dtmf_time+3 < now) {
1652                         /* the last digit was too far in the past to be a sequence */
1653                         if (param->dtmf == '*')
1654                                 /* only start is allowed in the sequence */
1655                                 e_dtmf_last = '*';
1656                         else
1657                                 e_dtmf_last = '\0';
1658                 } else {
1659                         /* we have a sequence of digits, see what we got */
1660                         if (param->dtmf == '*')
1661                                 e_dtmf_last = '*';
1662                         else if (param->dtmf>='0' && param->dtmf<='9') {
1663                                 /* we need to have a star before we receive the digit of the sequence */
1664                                 if (e_dtmf_last == '*')
1665                                         e_dtmf_last = param->dtmf;
1666                         } else if (param->dtmf == '#') {
1667                                 /* the hash key */
1668                                 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1669                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1670                                         if (e_dtmf_last == '0') {
1671                                                 hookflash();
1672                                                 return;
1673                                         }
1674                                         /* processing keypad function */
1675                                         if (param->dtmf)
1676                                                 keypad_function(e_dtmf_last);
1677                                         e_dtmf_last = '\0';
1678                                 }
1679                         }
1680                 }
1681
1682                 /* set last time of dtmf */
1683                 e_dtmf_time = now;
1684                 return;
1685         }
1686
1687         /* check for ## hookflash during dialing */
1688         if (e_action)
1689         if (e_action->index==ACTION_PASSWORD
1690          || e_action->index==ACTION_PASSWORD_WRITE)
1691                 goto password;
1692         if (param->dtmf=='#') { /* current digit is '#' */
1693                 if (e_state==EPOINT_STATE_IN_DISCONNECT
1694                  || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1695                         hookflash();
1696                         return;
1697                 } else {
1698                         e_dtmf_time = now;
1699                         e_dtmf_last = '#';
1700                 }
1701         } else {
1702                 password:
1703                 e_dtmf_time = now;
1704                 e_dtmf_last = '\0';
1705         }
1706         
1707
1708         /* dialing using dtmf digit */
1709         if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1710                 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1711                         set_tone(portlist, "dialing");
1712                 }
1713                 /* concat dialing string */
1714                 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1715                         e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1716                         e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1717                         process_dialing();
1718                 }
1719         }
1720 }
1721
1722 /* port MESSAGE_CRYPT */
1723 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1724 {
1725         /* send crypt response to cryptman */
1726         if (param->crypt.type == CR_MESSAGE_IND)
1727                 cryptman_msg2man(param->crypt.data, param->crypt.len);
1728         else
1729                 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1730 }
1731
1732 /* port MESSAGE_OVERLAP */
1733 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1734 {
1735         struct lcr_msg *message;
1736
1737         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1738
1739         /* signal to call tool */
1740         admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1741
1742         if (e_dialing_queue[0] && portlist) {
1743                 /* send what we have not dialed yet, because we had no setup complete */
1744                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1745                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1746                 SCPY(message->param.information.id, e_dialing_queue);
1747                 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1748                 message_put(message);
1749                 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1750                 e_dialing_queue[0] = '\0';
1751         }
1752         /* check if pattern is available */
1753         if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1754                 /* indicate patterns */
1755                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1756                 message_put(message);
1757
1758                 /* connect audio, if not already */
1759                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1760                 message->param.audiopath = 1;
1761                 message_put(message);
1762         } else {
1763                 /* indicate no patterns */
1764                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1765                 message_put(message);
1766
1767                 /* disconnect audio, if not already */
1768                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1769                 message->param.audiopath = 0;
1770                 message_put(message);
1771         }
1772         new_state(EPOINT_STATE_OUT_OVERLAP);
1773         /* if we are in a join */
1774         if (ea_endpoint->ep_join_id) { 
1775                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1776                 memcpy(&message->param, param, sizeof(union parameter));
1777                 message_put(message);
1778         }
1779 }
1780
1781 /* port MESSAGE_PROCEEDING */
1782 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1783 {
1784         struct lcr_msg *message;
1785
1786         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1787
1788         /* signal to call tool */
1789         admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1790
1791         e_state = EPOINT_STATE_OUT_PROCEEDING;
1792         /* check if pattern is availatle */
1793         if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1794                 /* indicate patterns */
1795                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1796                 message_put(message);
1797
1798                 /* connect audio, if not already */
1799                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1800                 message->param.audiopath = 1;
1801                 message_put(message);
1802         } else {
1803                 /* indicate no patterns */
1804                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1805                 message_put(message);
1806
1807                 /* disconnect audio, if not already */
1808                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1809                 message->param.audiopath = 0;
1810                 message_put(message);
1811         }
1812         /* if we are in a call */
1813         if (ea_endpoint->ep_join_id) { 
1814                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1815                 memcpy(&message->param, param, sizeof(union parameter));
1816                 message_put(message);
1817         }
1818 }
1819
1820 /* port MESSAGE_ALERTING */
1821 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1822 {
1823         struct lcr_msg *message;
1824
1825         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1826
1827         /* signal to call tool */
1828         admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1829 //#warning hack!!
1830 //      if (e_adminid)
1831 //              set_tone(portlist, "hold");
1832
1833         new_state(EPOINT_STATE_OUT_ALERTING);
1834         /* check if pattern is available */
1835         if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1836                 /* indicate patterns */
1837                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1838                 message_put(message);
1839
1840                 /* connect audio, if not already */
1841                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1842                 message->param.audiopath = 1;
1843                 message_put(message);
1844         } else {
1845                 /* indicate no patterns */
1846                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1847                 message_put(message);
1848
1849                 /* disconnect audio, if not already */
1850                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1851                 message->param.audiopath = 0;
1852                 message_put(message);
1853         }
1854         /* if we are in a call */
1855         if (ea_endpoint->ep_join_id) { 
1856                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1857                 memcpy(&message->param, param, sizeof(union parameter));
1858                 message_put(message);
1859         }
1860 }
1861
1862 /* port MESSAGE_CONNECT */
1863 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1864 {
1865         struct lcr_msg *message;
1866         char buffer[256];
1867         unsigned int port_id = portlist->port_id;
1868         struct port_list *tportlist;
1869         class Port *port;
1870         struct interface        *interface;
1871
1872         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1873
1874         /* signal to call tool */
1875         admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1876
1877         memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_connectinfo));
1878         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1879         while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1880                 tportlist = ea_endpoint->ep_portlist;
1881                 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1882                         tportlist = tportlist->next;
1883                 if (tportlist->port_id == port_id)
1884                         FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1885                 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1886                 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1887                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1888                 message_put(message);
1889                 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1890                 ea_endpoint->free_portlist(tportlist);
1891         }
1892         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1893
1894         e_start = now;
1895
1896         /* screen incoming connected id */
1897         interface = interface_first;
1898         while(interface) {
1899                 if (!strcmp(e_connectinfo.interface, interface->name)) {
1900                         break;
1901                 }
1902                 interface = interface->next;
1903         }
1904         if (interface)
1905                 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
1906
1907         /* screen connected name */
1908         if (e_ext.name[0])
1909                 SCPY(e_connectinfo.name, e_ext.name);
1910
1911         /* add internal id to colp */
1912         SCPY(e_connectinfo.extension, e_ext.number);
1913
1914         /* we store the connected port number */
1915         SCPY(e_extension_interface, e_connectinfo.interface);
1916
1917         /* for internal and am calls, we get the extension's id */
1918         if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
1919                 SCPY(e_connectinfo.id, e_ext.callerid);
1920                 SCPY(e_connectinfo.extension, e_ext.number);
1921                 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1922                 e_connectinfo.ntype = e_ext.callerid_type;
1923                 e_connectinfo.present = e_ext.callerid_present;
1924         }
1925         if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
1926                 e_connectinfo.itype = INFO_ITYPE_VBOX;
1927                 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
1928         }
1929
1930         new_state(EPOINT_STATE_CONNECT);
1931
1932         /* set volume of rx and tx */
1933         if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1934                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1935                 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1936                 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1937                 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1938                 message_put(message);
1939         }
1940
1941         e_cfnr_call = e_cfnr_release = 0;
1942         if (e_ext.number[0])
1943                 e_dtmf = 1; /* allow dtmf */
1944
1945         /* modify colp */
1946         /* other calls with no caller id (or not available for the extension) and force colp */
1947         if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
1948                 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
1949                 if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT || portlist->port_type==PORT_TYPE_GSM_OUT) { /* external extension answered */
1950                         port = find_port_id(portlist->port_id);
1951                         if (port) {
1952                                 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
1953                                 e_connectinfo.present = INFO_PRESENT_ALLOWED;
1954                         }
1955                 }
1956         }
1957
1958         /* send connect to join */
1959         if (ea_endpoint->ep_join_id) {
1960                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1961                 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
1962                 message_put(message);
1963
1964                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1965                 message->param.audiopath = 1;
1966                 message_put(message);
1967         } else if (!e_adminid) {
1968                 /* callback */
1969                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
1970                 SCPY(e_ext.number, e_cbcaller);
1971                 new_state(EPOINT_STATE_IN_OVERLAP);
1972                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1973
1974                 /* get extension's info about terminal */
1975                 if (!read_extension(&e_ext, e_ext.number)) {
1976                         /* extension doesn't exist */
1977                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1978                         message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1979                         new_state(EPOINT_STATE_OUT_DISCONNECT);
1980                         set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1981                         return;
1982                 }
1983
1984                 /* put prefix in front of e_cbdialing */
1985                 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
1986                 SCPY(e_dialinginfo.id, buffer);
1987                 e_dialinginfo.itype = INFO_ITYPE_ISDN;
1988                 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1989
1990                 /* use caller id (or if exist: id_next_call) for this call */
1991                 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1992                 SCPY(e_callerinfo.extension, e_ext.number);
1993                 if (e_ext.id_next_call_present >= 0) {
1994                         SCPY(e_callerinfo.id, e_ext.id_next_call);
1995                         e_callerinfo.present = e_ext.id_next_call_present;
1996                         e_callerinfo.ntype = e_ext.id_next_call_type;
1997                         e_ext.id_next_call_present = -1;
1998                         /* extension is written */
1999                         write_extension(&e_ext, e_ext.number);
2000                 } else {
2001                         SCPY(e_callerinfo.id, e_ext.callerid);
2002                         e_callerinfo.present = e_ext.callerid_present;
2003                         e_callerinfo.ntype = e_ext.callerid_type;
2004                 }
2005                 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2006
2007                 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2008                 e_dtmf = 1;
2009
2010                 /* check if caller id is NOT authenticated */
2011                 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2012                         /* make call state to enter password */
2013                         new_state(EPOINT_STATE_IN_OVERLAP);
2014                         e_action = &action_password_write;
2015                         e_match_timeout = 0;
2016                         e_match_to_action = NULL;
2017                         e_dialinginfo.id[0] = '\0';
2018                         e_extdialing = strchr(e_dialinginfo.id, '\0');
2019                         e_password_timeout = now+20;
2020                         process_dialing();
2021                 } else {
2022                         /* incoming call (callback) */
2023                         e_ruleset = ruleset_main;
2024                         if (e_ruleset)
2025                                 e_rule = e_ruleset->rule_first;
2026                         e_action = NULL;
2027                         e_extdialing = e_dialinginfo.id;
2028                         if (e_dialinginfo.id[0]) {
2029                                 set_tone(portlist, "dialing");
2030                                 process_dialing();
2031                         } else {
2032                                 set_tone(portlist, "dialpbx");
2033                         }
2034                 }
2035         } else { /* testcall */
2036                 set_tone(portlist, "hold");
2037         }
2038
2039         /* start recording if enabled, not when answering machine answers */
2040         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)) {
2041                 /* check if we are a terminal */
2042                 if (e_ext.number[0] == '\0')
2043                         PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2044                 else {
2045                         port = find_port_id(portlist->port_id);
2046                         if (port)
2047                                 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2048                 }
2049         }
2050 }
2051
2052 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2053 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2054 {
2055         struct lcr_msg  *message;
2056         char            buffer[256];
2057         unsigned int    port_id = portlist->port_id;
2058         int             cause,
2059                         location;
2060
2061         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2062
2063         /* signal to call tool */
2064         admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2065
2066 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2067         if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2068                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2069                 return;
2070         }
2071
2072         /* collect cause */
2073         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);
2074         collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2075         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2076
2077         /* check if we have more than one portlist relation and we just ignore the disconnect */
2078         if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2079                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2080                 portlist = ea_endpoint->ep_portlist;
2081                 while(portlist) {
2082                         if (portlist->port_id == port_id)
2083                                 break;
2084                         portlist = portlist->next;
2085                 }
2086                 if (!portlist)
2087                         FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2088                 if (message_type != MESSAGE_RELEASE) {
2089                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2090                         message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2091                         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2092                         message_put(message);
2093                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2094                 }
2095                 ea_endpoint->free_portlist(portlist);
2096                 return; /* one relation removed */ 
2097         }
2098         if (e_state == EPOINT_STATE_CONNECT) {
2099                 /* use cause from port after connect */
2100                 cause = param->disconnectinfo.cause;
2101                 location = param->disconnectinfo.location;
2102         } else {
2103                 /* use multipoint cause if no connect yet */
2104                 if (e_multipoint_cause) {
2105                         cause = e_multipoint_cause;
2106                         location = e_multipoint_location;
2107                 } else {
2108                         cause = CAUSE_NOUSER;
2109                         location = LOCATION_PRIVATE_LOCAL;
2110                 }
2111         }
2112
2113         e_cfnr_call = e_cfnr_release = 0;
2114
2115         /* process hangup */
2116         process_hangup(e_join_cause, e_join_location);
2117         e_multipoint_cause = 0;
2118         e_multipoint_location = 0;
2119
2120         if (message_type == MESSAGE_DISCONNECT) {
2121                 /* tone to disconnected end */
2122                 SPRINT(buffer, "cause_%02x", cause);
2123                 if (ea_endpoint->ep_portlist)
2124                         set_tone(ea_endpoint->ep_portlist, buffer);
2125
2126                 new_state(EPOINT_STATE_IN_DISCONNECT);
2127         }
2128
2129         if (ea_endpoint->ep_join_id) {
2130                 int haspatterns = 0;
2131                 /* check if pattern is available */
2132                 if (ea_endpoint->ep_portlist)
2133                 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2134                 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 
2135                  && message_type != MESSAGE_RELEASE) // if we release, we are done
2136                         haspatterns = 1;
2137                 if (haspatterns) {
2138                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2139                         /* indicate patterns */
2140                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2141                         message_put(message);
2142                         /* connect audio, if not already */
2143                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2144                         message->param.audiopath = 1;
2145                         message_put(message);
2146                         /* send disconnect */
2147                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2148                         memcpy(&message->param, param, sizeof(union parameter));
2149                         message_put(message);
2150                         /* disable encryption if disconnected */
2151 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2152                         if (e_crypt_state)
2153                                 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2154                         return;
2155                 } else {
2156                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2157                 }
2158         }
2159         if (message_type == MESSAGE_RELEASE)
2160                 ea_endpoint->free_portlist(portlist);
2161         release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
2162         return; /* must exit here */
2163 }
2164
2165 /* port MESSAGE_TIMEOUT */
2166 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2167 {
2168         char cause[16];
2169
2170         trace_header("TIMEOUT", DIRECTION_IN);
2171         message_type = MESSAGE_DISCONNECT;
2172         switch (param->state) {
2173                 case PORT_STATE_OUT_SETUP:
2174                 case PORT_STATE_OUT_OVERLAP:
2175                 add_trace("state", NULL, "outgoing setup/dialing");
2176                 end_trace();
2177                 /* no user responding */
2178                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2179                 return; /* must exit here */
2180
2181                 case PORT_STATE_IN_SETUP:
2182                 case PORT_STATE_IN_OVERLAP:
2183                 add_trace("state", NULL, "incoming setup/dialing");
2184                 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2185                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2186                 break;
2187
2188                 case PORT_STATE_OUT_PROCEEDING:
2189                 add_trace("state", NULL, "outgoing proceeding");
2190                 end_trace();
2191                 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2192                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2193                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2194                 return; /* must exit here */
2195
2196                 case PORT_STATE_IN_PROCEEDING:
2197                 add_trace("state", NULL, "incoming proceeding");
2198                 param->disconnectinfo.cause = CAUSE_NOUSER;
2199                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2200                 break;
2201
2202                 case PORT_STATE_OUT_ALERTING:
2203                 add_trace("state", NULL, "outgoing alerting");
2204                 end_trace();
2205                 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2206                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2207                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2208                 return; /* must exit here */
2209
2210                 case PORT_STATE_CONNECT:
2211                 add_trace("state", NULL, "connect");
2212                 end_trace();
2213                 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2214                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2215                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2216                 return; /* must exit here */
2217
2218                 case PORT_STATE_IN_ALERTING:
2219                 add_trace("state", NULL, "incoming alerting");
2220                 param->disconnectinfo.cause = CAUSE_NOANSWER;
2221                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2222                 break;
2223
2224                 case PORT_STATE_IN_DISCONNECT:
2225                 case PORT_STATE_OUT_DISCONNECT:
2226                 add_trace("state", NULL, "disconnect");
2227                 end_trace();
2228                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2229                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
2230                 return; /* must exit here */
2231
2232                 default:
2233                 param->disconnectinfo.cause = 31; /* normal unspecified */
2234                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2235         }
2236         end_trace();
2237         /* release call, disconnect isdn */
2238         e_join_pattern = 0;
2239         new_state(EPOINT_STATE_OUT_DISCONNECT);
2240         SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2241         SCPY(e_tone, cause);
2242         while(portlist) {
2243                 set_tone(portlist, cause);
2244                 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2245                 portlist = portlist->next;
2246         }
2247         release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2248 }
2249
2250 /* port MESSAGE_NOTIFY */
2251 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2252 {
2253         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2254
2255         struct lcr_msg *message;
2256         const char *logtext = "";
2257         char buffer[64];
2258
2259         /* signal to call tool */
2260         admin_call_response(e_adminid, ADMIN_CALL_NOTIFY, numberrize_callerinfo(param->notifyinfo.id,param->notifyinfo.ntype, options.national, options.international), 0, 0, param->notifyinfo.notify);
2261         if (param->notifyinfo.notify) {
2262                 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2263         }
2264
2265         /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2266         if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2267                 case INFO_NOTIFY_REMOTE_HOLD:
2268                 case INFO_NOTIFY_USER_SUSPENDED:
2269                 /* tell call about it */
2270                 if (ea_endpoint->ep_join_id) {
2271                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2272                         message->param.audiopath = 0;
2273                         message_put(message);
2274                 }
2275                 break;
2276
2277                 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2278                 case INFO_NOTIFY_USER_RESUMED:
2279                 /* set volume of rx and tx */
2280                 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2281                 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2282                 if (portlist) {
2283                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2284                         message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2285                         message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2286                         message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2287                         message_put(message);
2288                 }
2289                 /* set current tone */
2290                 if (portlist)
2291                         set_tone(portlist, e_tone);
2292                 /* tell call about it */
2293                 if (ea_endpoint->ep_join_id) {
2294                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2295                         message->param.audiopath = 1;
2296                         message_put(message);
2297                 }
2298                 break;
2299         }
2300
2301         /* get name of notify */
2302         switch(param->notifyinfo.notify) {
2303                 case 0x00:
2304                 logtext = "NULL";
2305                 break;
2306                 case 0x80:
2307                 logtext = "USER_SUSPENDED";
2308                 break;
2309                 case 0x82:
2310                 logtext = "BEARER_SERVICE_CHANGED";
2311                 break;
2312                 case 0x81:
2313                 logtext = "USER_RESUMED";
2314                 break;
2315                 case 0xc2:
2316                 logtext = "CONFERENCE_ESTABLISHED";
2317                 break;
2318                 case 0xc3:
2319                 logtext = "CONFERENCE_DISCONNECTED";
2320                 break;
2321                 case 0xc4:
2322                 logtext = "OTHER_PARTY_ADDED";
2323                 break;
2324                 case 0xc5:
2325                 logtext = "ISOLATED";
2326                 break;
2327                 case 0xc6:
2328                 logtext = "REATTACHED";
2329                 break;
2330                 case 0xc7:
2331                 logtext = "OTHER_PARTY_ISOLATED";
2332                 break;
2333                 case 0xc8:
2334                 logtext = "OTHER_PARTY_REATTACHED";
2335                 break;
2336                 case 0xc9:
2337                 logtext = "OTHER_PARTY_SPLIT";
2338                 break;
2339                 case 0xca:
2340                 logtext = "OTHER_PARTY_DISCONNECTED";
2341                 break;
2342                 case 0xcb:
2343                 logtext = "CONFERENCE_FLOATING";
2344                 break;
2345                 case 0xcc:
2346                 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2347                 break;
2348                 case 0xcf:
2349                 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2350                 break;
2351                 case 0xe0:
2352                 logtext = "CALL_IS_A_WAITING_CALL";
2353                 break;
2354                 case 0xe8:
2355                 logtext = "DIVERSION_ACTIVATED";
2356                 break;
2357                 case 0xe9:
2358                 logtext = "RESERVED_CT_1";
2359                 break;
2360                 case 0xea:
2361                 logtext = "RESERVED_CT_2";
2362                 break;
2363                 case 0xee:
2364                 logtext = "REVERSE_CHARGING";
2365                 break;
2366                 case 0xf9:
2367                 logtext = "REMOTE_HOLD";
2368                 break;
2369                 case 0xfa:
2370                 logtext = "REMOTE_RETRIEVAL";
2371                 break;
2372                 case 0xfb:
2373                 logtext = "CALL_IS_DIVERTING";
2374                 break;
2375                 default:
2376                 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2377                 logtext = buffer;
2378
2379         }
2380
2381         /* notify call if available */
2382         if (ea_endpoint->ep_join_id) {
2383                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2384                 memcpy(&message->param.notifyinfo, &param->notifyinfo, sizeof(struct notify_info));
2385                 message_put(message);
2386         }
2387
2388 }
2389
2390 /* port MESSAGE_FACILITY */
2391 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2392 {
2393         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2394
2395         struct lcr_msg *message;
2396
2397         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2398         memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
2399         message_put(message);
2400 }
2401
2402 /* port MESSAGE_SUSPEND */
2403 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2404 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2405 {
2406         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2407
2408         /* epoint is now parked */
2409         ea_endpoint->ep_park = 1;
2410         memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2411         ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2412
2413         /* remove port relation */
2414         ea_endpoint->free_portlist(portlist);
2415 }
2416
2417 /* port MESSAGE_RESUME */
2418 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2419 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2420 {
2421         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2422
2423         /* epoint is now resumed */
2424         ea_endpoint->ep_park = 0;
2425
2426 }
2427
2428
2429 /* port sends message to the endpoint
2430  */
2431 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2432 {
2433         struct port_list *portlist;
2434
2435         portlist = ea_endpoint->ep_portlist;
2436         while(portlist) {
2437                 if (port_id == portlist->port_id)
2438                         break;
2439                 portlist = portlist->next;
2440         }
2441         if (!portlist) {
2442                 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);
2443                 return;
2444         }
2445
2446 //      PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2447         switch(message_type) {
2448                 case MESSAGE_DATA: /* data from port */
2449                 /* check if there is a call */
2450                 if (!ea_endpoint->ep_join_id)
2451                         break;
2452                 /* continue if only one portlist */
2453                 if (ea_endpoint->ep_portlist->next != NULL)
2454                         break;
2455                 /* forward message */
2456                 message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);  
2457                 break;
2458
2459                 case MESSAGE_TONE_EOF: /* tone is end of file */
2460                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2461                 if (e_action) {
2462                         if (e_action->index == ACTION_VBOX_PLAY) {
2463                                 vbox_message_eof();
2464                         }
2465                         if (e_action->index == ACTION_EFI) {
2466                                 efi_message_eof();
2467                         }
2468                 }
2469                 break;
2470
2471                 case MESSAGE_TONE_COUNTER: /* counter info received */
2472                 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);
2473                 if (e_action)
2474                 if (e_action->index == ACTION_VBOX_PLAY) {
2475                         e_vbox_counter = param->counter.current;
2476                         if (param->counter.max >= 0)
2477                                 e_vbox_counter_max = param->counter.max;
2478                 }
2479                 break;
2480
2481                 /* PORT sends SETUP message */
2482                 case MESSAGE_SETUP:
2483                 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);
2484                 if (e_state!=EPOINT_STATE_IDLE) {
2485                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2486                         break;
2487                 }
2488                 port_setup(portlist, message_type, param);
2489                 break;
2490
2491                 /* PORT sends INFORMATION message */
2492                 case MESSAGE_INFORMATION: /* additional digits received */
2493                 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);
2494                 port_information(portlist, message_type, param);
2495                 break;
2496
2497                 /* PORT sends FACILITY message */
2498                 case MESSAGE_FACILITY:
2499                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2500                 port_facility(portlist, message_type, param);
2501                 break;
2502
2503                 /* PORT sends DTMF message */
2504                 case MESSAGE_DTMF: /* dtmf digits received */
2505                 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);
2506                 port_dtmf(portlist, message_type, param);
2507                 break;
2508
2509                 /* PORT sends CRYPT message */
2510                 case MESSAGE_CRYPT: /* crypt response received */
2511                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2512                 port_crypt(portlist, message_type, param);
2513                 break;
2514
2515                 /* PORT sends MORE message */
2516                 case MESSAGE_OVERLAP:
2517                 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);
2518                 if (e_state != EPOINT_STATE_OUT_SETUP) {
2519                         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);
2520                         break;
2521                 }
2522                 port_overlap(portlist, message_type, param);
2523                 break;
2524
2525                 /* PORT sends PROCEEDING message */
2526                 case MESSAGE_PROCEEDING: /* port is proceeding */
2527                 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);
2528                 if (e_state!=EPOINT_STATE_OUT_SETUP
2529                  && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2530                         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);
2531                         break;
2532                 }
2533                 port_proceeding(portlist, message_type, param);
2534                 break;
2535
2536                 /* PORT sends ALERTING message */
2537                 case MESSAGE_ALERTING:
2538                 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);
2539                 if (e_state!=EPOINT_STATE_OUT_SETUP
2540                  && e_state!=EPOINT_STATE_OUT_OVERLAP
2541                  && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2542                         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);
2543                         break;
2544                 }
2545                 port_alerting(portlist, message_type, param);
2546                 break;
2547
2548                 /* PORT sends CONNECT message */
2549                 case MESSAGE_CONNECT:
2550                 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);
2551                 if (e_state!=EPOINT_STATE_OUT_SETUP
2552                  && e_state!=EPOINT_STATE_OUT_OVERLAP
2553                  && e_state!=EPOINT_STATE_OUT_PROCEEDING
2554                  && e_state!=EPOINT_STATE_OUT_ALERTING) {
2555                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2556                         break;
2557                 }
2558                 port_connect(portlist, message_type, param);
2559                 break;
2560
2561                 /* PORT sends DISCONNECT message */
2562                 case MESSAGE_DISCONNECT: /* port is disconnected */
2563                 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);
2564                 port_disconnect_release(portlist, message_type, param);
2565                 break;
2566
2567                 /* PORT sends a RELEASE message */
2568                 case MESSAGE_RELEASE: /* port releases */
2569                 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);
2570                 /* portlist is release at port_disconnect_release, thanx Paul */
2571                 port_disconnect_release(portlist, message_type, param);
2572                 break;
2573
2574                 /* PORT sends a TIMEOUT message */
2575                 case MESSAGE_TIMEOUT:
2576                 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);
2577                 port_timeout(portlist, message_type, param);
2578                 break; /* release */
2579
2580                 /* PORT sends a NOTIFY message */
2581                 case MESSAGE_NOTIFY:
2582                 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);
2583                 port_notify(portlist, message_type, param);
2584                 break;
2585
2586                 /* PORT sends a SUSPEND message */
2587                 case MESSAGE_SUSPEND:
2588                 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);
2589                 port_suspend(portlist, message_type, param);
2590                 break; /* suspend */
2591
2592                 /* PORT sends a RESUME message */
2593                 case MESSAGE_RESUME:
2594                 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);
2595                 port_resume(portlist, message_type, param);
2596                 break;
2597
2598 #if 0
2599                 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2600                 /* port assigns bchannel */
2601                 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2602                 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);
2603                 /* only one port is expected to be connected to bchannel */
2604                 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2605                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2606                 break;
2607 #endif
2608
2609
2610                 default:
2611                 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_type);
2612         }
2613
2614         /* Note: this endpoint may be destroyed, so we MUST return */
2615 }
2616
2617
2618 /* messages from join
2619  */
2620 /* join MESSAGE_CRYPT */
2621 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2622 {
2623         switch(param->crypt.type) {
2624                 /* message from remote port to "crypt manager" */
2625                 case CU_ACTK_REQ:           /* activate key-exchange */
2626                 case CU_ACTS_REQ:            /* activate shared key */
2627                 case CU_DACT_REQ:          /* deactivate */
2628                 case CU_INFO_REQ:         /* request last info message */
2629                 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2630                 break;
2631
2632                 /* message from "crypt manager" to user */
2633                 case CU_ACTK_CONF:          /* key-echange done */
2634                 case CU_ACTS_CONF:          /* shared key done */
2635                 case CU_DACT_CONF:           /* deactivated */
2636                 case CU_DACT_IND:           /* deactivated */
2637                 case CU_ERROR_IND:         /* receive error message */
2638                 case CU_INFO_IND:         /* receive info message */
2639                 case CU_INFO_CONF:         /* receive info message */
2640                 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2641                 break;
2642
2643                 default:
2644                 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);
2645         }
2646 }
2647
2648 /* join MESSAGE_INFORMATION */
2649 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2650 {
2651         struct lcr_msg *message;
2652
2653         e_overlap = 1;
2654
2655         while(portlist) {
2656                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2657                 memcpy(&message->param.information, &param->information, sizeof(struct dialing_info));
2658                 message_put(message);
2659                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2660                 portlist = portlist->next;
2661         }
2662 }
2663
2664 /* join MESSAGE_FACILITY */
2665 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2666 {
2667         struct lcr_msg *message;
2668
2669         if (!e_ext.facility && e_ext.number[0]) {
2670                 return;
2671         }
2672
2673         while(portlist) {
2674                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2675                 memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
2676                 message_put(message);
2677                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2678                 portlist = portlist->next;
2679         }
2680 }
2681
2682 /* join MESSAGE_MORE */
2683 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2684 {
2685         struct lcr_msg *message;
2686
2687         new_state(EPOINT_STATE_IN_OVERLAP);
2688         
2689         /* own dialtone */
2690         if (e_join_pattern && e_ext.own_setup) {
2691                 /* disconnect audio */
2692                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2693                 message->param.audiopath = 0;
2694                 message_put(message);
2695         }
2696         if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2697                         if (e_dialinginfo.id[0])
2698                                 set_tone(portlist, "dialing");
2699                         else
2700                                 set_tone(portlist, "dialtone");
2701                         return;
2702         }
2703         if (e_dialinginfo.id[0]) {
2704                 set_tone(portlist, "dialing");
2705         } else {
2706                 if (e_ext.number[0])
2707                         set_tone(portlist, "dialpbx");
2708                 else
2709                         set_tone(portlist, "dialtone");
2710         }
2711 }
2712
2713 /* join MESSAGE_PROCEEDING */
2714 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2715 {
2716         struct lcr_msg *message;
2717
2718         new_state(EPOINT_STATE_IN_PROCEEDING);
2719
2720         /* own proceeding tone */
2721         if (e_join_pattern) {
2722                 /* connect / disconnect audio */
2723                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2724                 if (e_ext.own_proceeding)
2725                         message->param.audiopath = 0;
2726                 else
2727                         message->param.audiopath = 1;
2728                 message_put(message);
2729         }
2730 //                      UCPY(e_join_tone, "proceeding");
2731         if (portlist) {
2732                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2733                 message_put(message);
2734                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2735         }
2736         set_tone(portlist, "proceeding");
2737 }
2738
2739 /* join MESSAGE_ALERTING */
2740 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2741 {
2742         struct lcr_msg *message;
2743
2744         new_state(EPOINT_STATE_IN_ALERTING);
2745
2746         /* own alerting tone */
2747         if (e_join_pattern) {
2748                 /* connect / disconnect audio */
2749                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2750                 if (e_ext.own_alerting)
2751                         message->param.audiopath = 0;
2752                 else
2753                         message->param.audiopath = 1;
2754                 message_put(message);
2755         }
2756         if (portlist) {
2757                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2758                 message_put(message);
2759                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2760         }
2761         if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2762                 set_tone(portlist, "ringing");
2763                 return;
2764         }
2765         if (e_ext.number[0])
2766                 set_tone(portlist, "ringpbx");
2767         else
2768                 set_tone(portlist, "ringing");
2769
2770         if (e_ext.number[0])
2771                 e_dtmf = 1; /* allow dtmf */
2772 }
2773
2774 /* join MESSAGE_CONNECT */
2775 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2776 {
2777         struct lcr_msg *message;
2778
2779         new_state(EPOINT_STATE_CONNECT);
2780 //                      UCPY(e_join_tone, "");
2781 //                      
2782         if (e_ext.number[0])
2783                 e_dtmf = 1; /* allow dtmf */
2784
2785         e_powerdialing = 0;
2786         memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_callerinfo));
2787         if(portlist) {
2788                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2789                 memcpy(&message->param, param, sizeof(union parameter));
2790
2791                 /* screen clip if prefix is required */
2792                 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2793                         SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2794                         SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2795                         message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2796                 }
2797
2798                 /* use internal caller id */
2799                 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2800                         SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2801                         message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2802                 }
2803
2804                 /* handle restricted caller ids */
2805                 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);
2806                 /* display callerid if desired for extension */
2807                 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));
2808
2809                 /* use conp, if enabld */
2810 //              if (!e_ext.centrex)
2811 //                      message->param.connectinfo.name[0] = '\0';
2812
2813                 /* send connect */
2814                 message_put(message);
2815                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2816         }
2817         set_tone(portlist, NULL);
2818         e_join_pattern = 0;
2819         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2820         message->param.audiopath = 1;
2821         message_put(message);
2822         e_start = now;
2823 }
2824
2825 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2826 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2827 {
2828         char cause[16];
2829         struct lcr_msg *message;
2830         struct port_list *portlist = NULL;
2831
2832
2833         /* be sure that we are active */
2834         notify_active();
2835         e_tx_state = NOTIFY_STATE_ACTIVE;
2836
2837         /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
2838         if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2839                 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2840
2841                 /* set time for power dialing */
2842                 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
2843                 e_powercount++;
2844
2845                 /* set redial tone */
2846                 if (ea_endpoint->ep_portlist) {
2847                         e_join_pattern = 0;
2848                 }
2849                 set_tone(ea_endpoint->ep_portlist, "redial");
2850                 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);
2851                 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2852                 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2853                         new_state(EPOINT_STATE_IN_PROCEEDING);
2854                         if (ea_endpoint->ep_portlist) {
2855                                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2856                                 message_put(message);
2857                                 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2858                         }
2859 /* caused the error, that the first knock sound was not there */
2860 /*                                      set_tone(portlist, "proceeding"); */
2861                 }
2862                 /* send display of powerdialing */
2863                 if (e_ext.display_dialing) {
2864                         portlist = ea_endpoint->ep_portlist;
2865                         while (portlist) {
2866                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2867                                 if (e_powerlimit)
2868                                         SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2869                                 else
2870                                         SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2871                                 message_put(message);
2872                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2873                                 portlist = portlist->next;
2874                         }
2875                 }
2876                 return;
2877         }
2878
2879         /* set stop time */
2880         e_stop = now;
2881
2882         if ((e_state!=EPOINT_STATE_CONNECT
2883           && e_state!=EPOINT_STATE_OUT_DISCONNECT
2884           && e_state!=EPOINT_STATE_IN_OVERLAP
2885           && e_state!=EPOINT_STATE_IN_PROCEEDING
2886           && e_state!=EPOINT_STATE_IN_ALERTING)
2887          || !ea_endpoint->ep_portlist) { /* or no port */
2888                 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
2889                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
2890                 return; /* must exit here */
2891         }
2892         /* save cause */
2893         if (!e_join_cause) {
2894                 e_join_cause = param->disconnectinfo.cause;
2895                 e_join_location = param->disconnectinfo.location;
2896         }
2897
2898         /* on release we need the audio again! */
2899         if (message_type == MESSAGE_RELEASE) {
2900                 e_join_pattern = 0;
2901                 ea_endpoint->ep_join_id = 0;
2902         }
2903         /* disconnect and select tone */
2904         new_state(EPOINT_STATE_OUT_DISCONNECT);
2905         SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2906         /* if own_cause, we must release the join */
2907         if (e_ext.own_cause /* own cause */
2908          || !e_join_pattern) { /* no patterns */
2909                 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);
2910                 if (message_type != MESSAGE_RELEASE)
2911                         release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
2912                 e_join_pattern = 0;
2913         } else { /* else we enable audio */
2914                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2915                 message->param.audiopath = 1;
2916                 message_put(message);
2917         }
2918         /* send disconnect message */
2919         SCPY(e_tone, cause);
2920         portlist = ea_endpoint->ep_portlist;
2921         while(portlist) {
2922                 set_tone(portlist, cause);
2923                 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2924                 portlist = portlist->next;
2925         }
2926 }
2927
2928 /* join MESSAGE_SETUP */
2929 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
2930 {
2931         struct lcr_msg *message;
2932 //      struct interface        *interface;
2933
2934         /* if we already in setup state, we just update the dialing with new digits */
2935         if (e_state == EPOINT_STATE_OUT_SETUP
2936          || e_state == EPOINT_STATE_OUT_OVERLAP) {
2937                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
2938                 /* if digits changed, what we have already dialed */
2939                 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
2940                         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);
2941                         /* release all ports */
2942                         while((portlist = ea_endpoint->ep_portlist)) {
2943                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2944                                 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2945                                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2946                                 message_put(message);
2947                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2948                                 ea_endpoint->free_portlist(portlist);
2949                         }
2950
2951                         /* disconnect audio */
2952                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2953                         message->param.audiopath = 0;
2954                         message_put(message);
2955
2956                         /* get dialing info */
2957                         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
2958                         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
2959                         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
2960                         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
2961                         new_state(EPOINT_STATE_OUT_OVERLAP);
2962
2963                         /* get time */
2964                         e_redial = now_d + 1; /* set redial one second in the future */
2965                         return;
2966                 }
2967                 /* if we have a pending redial, so we just adjust the dialing number */
2968                 if (e_redial) {
2969                         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);
2970                         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
2971                         return;
2972                 }
2973                 if (!ea_endpoint->ep_portlist) {
2974                         PERROR("ERROR: overlap dialing to a NULL port relation\n");
2975                 }
2976                 if (ea_endpoint->ep_portlist->next) {
2977                         PERROR("ERROR: overlap dialing to a port_list port relation\n");
2978                 }
2979                 if (e_state == EPOINT_STATE_OUT_SETUP) {
2980                         /* queue digits */
2981                         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);
2982                         SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
2983                         
2984                 } else {
2985                         /* get what we have not dialed yet */
2986                         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));
2987                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2988                         SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
2989                         message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2990                         message_put(message);
2991                         logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2992                 }
2993                 /* always store what we have dialed or queued */
2994                 memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
2995                 
2996                 return;
2997         }
2998         if (e_state != EPOINT_STATE_IDLE) {
2999                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3000                 return;
3001         }
3002         /* if an internal extension is dialed, copy that number */
3003         if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3004                 SCPY(e_ext.number, param->setup.dialinginfo.id);
3005         /* if an internal extension is dialed, get extension's info about caller */
3006         if (e_ext.number[0]) {
3007                 if (!read_extension(&e_ext, e_ext.number)) {
3008                         e_ext.number[0] = '\0';
3009                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3010                 }
3011         }
3012
3013         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
3014         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3015         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
3016         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
3017
3018         /* process (voice over) data calls */
3019         if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3020                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3021                 memset(&e_capainfo, 0, sizeof(e_capainfo));
3022                 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3023                 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3024                 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3025         }
3026
3027         new_state(EPOINT_STATE_OUT_SETUP);
3028         /* call special setup routine */
3029         out_setup();
3030 }
3031
3032 /* join MESSAGE_mISDNSIGNAL */
3033 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3034 {
3035         struct lcr_msg *message;
3036
3037         while(portlist) {
3038                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3039                 memcpy(&message->param, param, sizeof(union parameter));
3040                 message_put(message);
3041                 portlist = portlist->next;
3042         }
3043 }
3044
3045 /* join MESSAGE_NOTIFY */
3046 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3047 {
3048         struct lcr_msg *message;
3049         int new_state;
3050
3051         if (param->notifyinfo.notify) {
3052                 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3053 //              /* if notification was generated locally, we turn hold music on/off */ 
3054 //  &nb