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