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