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