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