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