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