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