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