For DOV: LCR random number generator
[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-busy 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         } else if (!e_adminid) {
1974                 /* callback */
1975                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
1976                 SCPY(e_ext.number, e_cbcaller);
1977                 new_state(EPOINT_STATE_IN_OVERLAP);
1978                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1979
1980                 /* get extension's info about terminal */
1981                 if (!read_extension(&e_ext, e_ext.number)) {
1982                         /* extension doesn't exist */
1983                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1984                         message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1985                         new_state(EPOINT_STATE_OUT_DISCONNECT);
1986                         set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1987                         return;
1988                 }
1989
1990                 /* put prefix in front of e_cbdialing */
1991                 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
1992                 SCPY(e_dialinginfo.id, buffer);
1993                 e_dialinginfo.itype = INFO_ITYPE_ISDN;
1994                 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1995
1996                 /* use caller id (or if exist: id_next_call) for this call */
1997                 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1998                 SCPY(e_callerinfo.extension, e_ext.number);
1999                 if (e_ext.id_next_call_present >= 0) {
2000                         SCPY(e_callerinfo.id, e_ext.id_next_call);
2001                         e_callerinfo.present = e_ext.id_next_call_present;
2002                         e_callerinfo.ntype = e_ext.id_next_call_type;
2003                         e_ext.id_next_call_present = -1;
2004                         /* extension is written */
2005                         write_extension(&e_ext, e_ext.number);
2006                 } else {
2007                         SCPY(e_callerinfo.id, e_ext.callerid);
2008                         e_callerinfo.present = e_ext.callerid_present;
2009                         e_callerinfo.ntype = e_ext.callerid_type;
2010                 }
2011                 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
2012
2013                 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
2014                 e_dtmf = 1;
2015
2016                 /* check if caller id is NOT authenticated */
2017                 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
2018                         /* make call state to enter password */
2019                         new_state(EPOINT_STATE_IN_OVERLAP);
2020                         e_action = &action_password_write;
2021                         unsched_timer(&e_match_timeout);
2022                         e_match_to_action = NULL;
2023                         e_dialinginfo.id[0] = '\0';
2024                         e_extdialing = strchr(e_dialinginfo.id, '\0');
2025                         schedule_timer(&e_password_timeout, 20, 0);
2026                         process_dialing(0);
2027                 } else {
2028                         /* incoming call (callback) */
2029                         e_ruleset = ruleset_main;
2030                         if (e_ruleset)
2031                                 e_rule = e_ruleset->rule_first;
2032                         e_action = NULL;
2033                         e_extdialing = e_dialinginfo.id;
2034                         if (e_dialinginfo.id[0]) {
2035                                 set_tone(portlist, "dialing");
2036                                 process_dialing(0);
2037                         } else {
2038                                 set_tone(portlist, "dialpbx");
2039                         }
2040                 }
2041         } else { /* testcall */
2042                 set_tone(portlist, "hold");
2043         }
2044
2045         /* start recording if enabled, not when answering machine answers */
2046         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)) {
2047                 /* check if we are a terminal */
2048                 if (e_ext.number[0] == '\0')
2049                         PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2050                 else {
2051                         port = find_port_id(portlist->port_id);
2052                         if (port)
2053                                 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2054                 }
2055         }
2056 }
2057
2058 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2059 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2060 {
2061         struct lcr_msg  *message;
2062         char            buffer[256];
2063         unsigned int    port_id = portlist->port_id;
2064         int             cause,
2065                         location;
2066
2067         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2068
2069         /* signal to call tool */
2070         admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2071
2072 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2073         if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2074                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2075                 return;
2076         }
2077
2078         /* collect cause */
2079         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);
2080         collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2081         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2082
2083         /* check if we have more than one portlist relation and we just ignore the disconnect */
2084         if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2085                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2086                 portlist = ea_endpoint->ep_portlist;
2087                 while(portlist) {
2088                         if (portlist->port_id == port_id)
2089                                 break;
2090                         portlist = portlist->next;
2091                 }
2092                 if (!portlist)
2093                         FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2094                 if (message_type != MESSAGE_RELEASE) {
2095                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2096                         message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2097                         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2098                         message_put(message);
2099                         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2100                 }
2101                 ea_endpoint->free_portlist(portlist);
2102                 return; /* one relation removed */ 
2103         }
2104         if (e_state == EPOINT_STATE_CONNECT) {
2105                 /* use cause from port after connect */
2106                 cause = param->disconnectinfo.cause;
2107                 location = param->disconnectinfo.location;
2108         } else {
2109                 /* use multipoint cause if no connect yet */
2110                 if (e_multipoint_cause) {
2111                         cause = e_multipoint_cause;
2112                         location = e_multipoint_location;
2113                 } else {
2114                         cause = CAUSE_NOUSER;
2115                         location = LOCATION_PRIVATE_LOCAL;
2116                 }
2117         }
2118
2119         unsched_timer(&e_cfnr_timeout);
2120         unsched_timer(&e_cfnr_call_timeout);
2121
2122         /* process hangup */
2123         process_hangup(e_join_cause, e_join_location);
2124         e_multipoint_cause = 0;
2125         e_multipoint_location = 0;
2126
2127         if (message_type == MESSAGE_DISCONNECT) {
2128                 /* tone to disconnected end */
2129                 SPRINT(buffer, "cause_%02x", cause);
2130                 if (ea_endpoint->ep_portlist)
2131                         set_tone(ea_endpoint->ep_portlist, buffer);
2132
2133                 new_state(EPOINT_STATE_IN_DISCONNECT);
2134         }
2135
2136         if (ea_endpoint->ep_join_id) {
2137                 int haspatterns = 0;
2138                 /* check if pattern is available */
2139                 if (ea_endpoint->ep_portlist)
2140                 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2141                 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 
2142                  && message_type != MESSAGE_RELEASE) // if we release, we are done
2143                         haspatterns = 1;
2144                 if (haspatterns) {
2145                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2146                         /* indicate patterns */
2147                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2148                         message_put(message);
2149                         /* connect audio, if not already */
2150                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2151                         message->param.audiopath = 1;
2152                         message_put(message);
2153                         /* send disconnect */
2154                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2155                         memcpy(&message->param, param, sizeof(union parameter));
2156                         message_put(message);
2157                         /* disable encryption if disconnected */
2158 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2159 #ifdef WITH_CRYPT
2160                         if (e_crypt_state)
2161                                 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2162 #endif
2163                         return;
2164                 } else {
2165                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2166                 }
2167         }
2168         if (message_type == MESSAGE_RELEASE)
2169                 ea_endpoint->free_portlist(portlist);
2170         release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
2171         return; /* must exit here */
2172 }
2173
2174 /* port MESSAGE_TIMEOUT */
2175 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2176 {
2177         char cause[16];
2178
2179         trace_header("TIMEOUT", DIRECTION_IN);
2180         message_type = MESSAGE_DISCONNECT;
2181         switch (param->state) {
2182                 case PORT_STATE_OUT_SETUP:
2183                 case PORT_STATE_OUT_OVERLAP:
2184                 add_trace("state", NULL, "outgoing setup/dialing");
2185                 end_trace();
2186                 /* no user responding */
2187                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2188                 return; /* must exit here */
2189
2190                 case PORT_STATE_IN_SETUP:
2191                 case PORT_STATE_IN_OVERLAP:
2192                 add_trace("state", NULL, "incoming setup/dialing");
2193                 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2194                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2195                 break;
2196
2197                 case PORT_STATE_OUT_PROCEEDING:
2198                 add_trace("state", NULL, "outgoing proceeding");
2199                 end_trace();
2200                 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2201                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2202                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2203                 return; /* must exit here */
2204
2205                 case PORT_STATE_IN_PROCEEDING:
2206                 add_trace("state", NULL, "incoming proceeding");
2207                 param->disconnectinfo.cause = CAUSE_NOUSER;
2208                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2209                 break;
2210
2211                 case PORT_STATE_OUT_ALERTING:
2212                 add_trace("state", NULL, "outgoing alerting");
2213                 end_trace();
2214                 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2215                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2216                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2217                 return; /* must exit here */
2218
2219                 case PORT_STATE_CONNECT:
2220                 add_trace("state", NULL, "connect");
2221                 end_trace();
2222                 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2223                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2224                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2225                 return; /* must exit here */
2226
2227                 case PORT_STATE_IN_ALERTING:
2228                 add_trace("state", NULL, "incoming alerting");
2229                 param->disconnectinfo.cause = CAUSE_NOANSWER;
2230                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2231                 break;
2232
2233                 case PORT_STATE_IN_DISCONNECT:
2234                 case PORT_STATE_OUT_DISCONNECT:
2235                 add_trace("state", NULL, "disconnect");
2236                 end_trace();
2237                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2238                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2239                 return; /* must exit here */
2240
2241                 default:
2242                 param->disconnectinfo.cause = 31; /* normal unspecified */
2243                 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2244         }
2245         end_trace();
2246         /* release call, disconnect isdn */
2247         e_join_pattern = 0;
2248         new_state(EPOINT_STATE_OUT_DISCONNECT);
2249         SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2250         SCPY(e_tone, cause);
2251         while(portlist) {
2252                 set_tone(portlist, cause);
2253                 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2254                 portlist = portlist->next;
2255         }
2256         release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2257 }
2258
2259 /* port MESSAGE_NOTIFY */
2260 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2261 {
2262         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2263
2264         struct lcr_msg *message;
2265
2266         /* signal to call tool */
2267         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);
2268         if (param->notifyinfo.notify) {
2269                 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2270         }
2271
2272         /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2273         if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2274                 case INFO_NOTIFY_REMOTE_HOLD:
2275                 case INFO_NOTIFY_USER_SUSPENDED:
2276                 /* tell call about it */
2277                 if (ea_endpoint->ep_join_id) {
2278                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2279                         message->param.audiopath = 0;
2280                         message_put(message);
2281                 }
2282                 break;
2283
2284                 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2285                 case INFO_NOTIFY_USER_RESUMED:
2286                 /* set volume of rx and tx */
2287                 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2288                 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2289                 if (portlist) {
2290                         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2291                         message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2292                         message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2293                         message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2294                         message_put(message);
2295                 }
2296                 /* set current tone */
2297                 if (portlist)
2298                         set_tone(portlist, e_tone);
2299                 /* tell call about it */
2300                 if (ea_endpoint->ep_join_id) {
2301                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2302                         message->param.audiopath = 1;
2303                         message_put(message);
2304                 }
2305                 break;
2306         }
2307
2308         /* notify call if available */
2309         if (ea_endpoint->ep_join_id) {
2310                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2311                 memcpy(&message->param.notifyinfo, &param->notifyinfo, sizeof(struct notify_info));
2312                 message_put(message);
2313         }
2314
2315 }
2316
2317 /* port MESSAGE_PROGRESS */
2318 void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
2319 {
2320         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2321
2322         struct lcr_msg *message;
2323
2324         /* signal to call tool */
2325         admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
2326
2327         /* send progress to call if available */
2328         if (ea_endpoint->ep_join_id) {
2329                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
2330                 memcpy(&message->param.progressinfo, &param->progressinfo, sizeof(struct progress_info));
2331                 message_put(message);
2332         }
2333
2334 }
2335
2336 /* port MESSAGE_FACILITY */
2337 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2338 {
2339         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2340
2341         struct lcr_msg *message;
2342
2343         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2344         memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
2345         message_put(message);
2346 }
2347
2348 /* port MESSAGE_3PTY */
2349 void EndpointAppPBX::port_3pty(struct port_list *portlist, int message_type, union parameter *param)
2350 {
2351         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2352
2353         struct lcr_msg *message;
2354         int rc;
2355
2356         /* 3PTY bridge */
2357         if (param->threepty.begin)
2358                 rc = join_3pty_dss1();
2359         else if (param->threepty.end)
2360                 rc = split_3pty();
2361         else
2362                 return;
2363
2364         message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_3PTY);
2365         message->param.threepty.begin = param->threepty.begin;
2366         message->param.threepty.end = param->threepty.end;
2367         if (rc < 0)
2368                 message->param.threepty.error = 1;
2369         else
2370                 message->param.threepty.result = 1;
2371         message->param.threepty.invoke_id = param->threepty.invoke_id;
2372         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2373         message_put(message);
2374 }
2375
2376 /* port MESSAGE_TRANSFER */
2377 void EndpointAppPBX::port_transfer(struct port_list *portlist, int message_type, union parameter *param)
2378 {
2379         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2380
2381         class Port *port;
2382
2383         /* bridge for real */
2384         if (!(port = find_port_id(portlist->port_id)))
2385                 return;
2386         if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS)
2387                 join_join_fxs();
2388         else if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_DSS1)
2389                 join_join_dss1();
2390 }
2391
2392 /* port MESSAGE_SUSPEND */
2393 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2394 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2395 {
2396         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2397
2398         /* epoint is now parked */
2399         ea_endpoint->ep_park = 1;
2400         memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2401         ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2402
2403         /* remove port relation */
2404         ea_endpoint->free_portlist(portlist);
2405 }
2406
2407 /* port MESSAGE_RESUME */
2408 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2409 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2410 {
2411         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2412
2413         /* epoint is now resumed */
2414         ea_endpoint->ep_park = 0;
2415
2416 }
2417
2418 /* port MESSAGE_ENABLEKEYPAD */
2419 void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
2420 {
2421         struct lcr_msg *message;
2422
2423         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2424
2425         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
2426         memcpy(&message->param, param, sizeof(union parameter));
2427         message_put(message);
2428 }
2429
2430
2431 /* port MESSAGE_DISABLE_DEJITTER */
2432 void EndpointAppPBX::port_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param)
2433 {
2434         struct lcr_msg *message;
2435
2436         logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2437
2438         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_DISABLE_DEJITTER);
2439         memcpy(&message->param, param, sizeof(union parameter));
2440         message_put(message);
2441 }
2442
2443
2444 /* port MESSAGE_UPDATEBRIDGE  */
2445 void EndpointAppPBX::port_updatebridge(struct port_list *portlist, int message_type, union parameter *param)
2446 {
2447         struct lcr_msg *message;
2448
2449         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_UPDATEBRIDGE);
2450         message_put(message);
2451 }
2452
2453
2454 /* port MESSAGE_VOOTP  */
2455 void EndpointAppPBX::port_vootp(struct port_list *portlist, int message_type, union parameter *param)
2456 {
2457         if (param->vootp.failed)
2458                 set_tone(ea_endpoint->ep_portlist, "crypt_off");
2459 }
2460
2461
2462 /* port sends message to the endpoint
2463  */
2464 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2465 {
2466         struct port_list *portlist;
2467
2468         portlist = ea_endpoint->ep_portlist;
2469         while(portlist) {
2470                 if (port_id == portlist->port_id)
2471                         break;
2472                 portlist = portlist->next;
2473         }
2474         if (!portlist) {
2475                 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);
2476                 return;
2477         }
2478
2479 //      PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2480         switch(message_type) {
2481                 case MESSAGE_TONE_EOF: /* tone is end of file */
2482                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2483                 if (e_action) {
2484                         if (e_action->index == ACTION_VBOX_PLAY) {
2485                                 vbox_message_eof();
2486                         }
2487                         if (e_action->index == ACTION_EFI) {
2488                                 efi_message_eof();
2489                         }
2490                 }
2491                 break;
2492
2493                 case MESSAGE_TONE_COUNTER: /* counter info received */
2494                 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);
2495                 if (e_action)
2496                 if (e_action->index == ACTION_VBOX_PLAY) {
2497                         e_vbox_counter = param->counter.current;
2498                         if (param->counter.max >= 0)
2499                                 e_vbox_counter_max = param->counter.max;
2500                 }
2501                 break;
2502
2503                 /* PORT sends SETUP message */
2504                 case MESSAGE_SETUP:
2505                 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);
2506                 if (e_state!=EPOINT_STATE_IDLE) {
2507                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2508                         break;
2509                 }
2510                 port_setup(portlist, message_type, param);
2511                 break;
2512
2513                 /* PORT sends INFORMATION message */
2514                 case MESSAGE_INFORMATION: /* additional digits received */
2515                 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);
2516                 port_information(portlist, message_type, param);
2517                 break;
2518
2519                 /* PORT sends FACILITY message */
2520                 case MESSAGE_FACILITY:
2521                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2522                 port_facility(portlist, message_type, param);
2523                 break;
2524
2525                 case MESSAGE_3PTY:
2526                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming 3PTY facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2527                 port_3pty(portlist, message_type, param);
2528                 break;
2529
2530                 case MESSAGE_TRANSFER:
2531                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming TRANSFER request (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2532                 port_transfer(portlist, message_type, param);
2533                 break;
2534
2535                 /* PORT sends DTMF message */
2536                 case MESSAGE_DTMF: /* dtmf digits received */
2537                 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);
2538                 port_dtmf(portlist, message_type, param);
2539                 break;
2540
2541                 /* PORT sends CRYPT message */
2542                 case MESSAGE_CRYPT: /* crypt response received */
2543                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2544                 port_crypt(portlist, message_type, param);
2545                 break;
2546
2547                 /* PORT sends MORE message */
2548                 case MESSAGE_OVERLAP:
2549                 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);
2550                 if (e_state != EPOINT_STATE_OUT_SETUP) {
2551                         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);
2552                         break;
2553                 }
2554                 port_overlap(portlist, message_type, param);
2555                 break;
2556
2557                 /* PORT sends PROCEEDING message */
2558                 case MESSAGE_PROCEEDING: /* port is proceeding */
2559                 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);
2560                 if (e_state!=EPOINT_STATE_OUT_SETUP
2561                  && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2562                         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);
2563                         break;
2564                 }
2565                 port_proceeding(portlist, message_type, param);
2566                 break;
2567
2568                 /* PORT sends ALERTING message */
2569                 case MESSAGE_ALERTING:
2570                 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);
2571                 if (e_state!=EPOINT_STATE_OUT_SETUP
2572                  && e_state!=EPOINT_STATE_OUT_OVERLAP
2573                  && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2574                         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);
2575                         break;
2576                 }
2577                 port_alerting(portlist, message_type, param);
2578                 break;
2579
2580                 /* PORT sends CONNECT message */
2581                 case MESSAGE_CONNECT:
2582                 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);
2583                 if (e_state!=EPOINT_STATE_OUT_SETUP
2584                  && e_state!=EPOINT_STATE_OUT_OVERLAP
2585                  && e_state!=EPOINT_STATE_OUT_PROCEEDING
2586                  && e_state!=EPOINT_STATE_OUT_ALERTING) {
2587                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2588                         break;
2589                 }
2590                 port_connect(portlist, message_type, param);
2591                 break;
2592
2593                 /* PORT sends DISCONNECT message */
2594                 case MESSAGE_DISCONNECT: /* port is disconnected */
2595                 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);
2596                 port_disconnect_release(portlist, message_type, param);
2597                 break;
2598
2599                 /* PORT sends a RELEASE message */
2600                 case MESSAGE_RELEASE: /* port releases */
2601                 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);
2602                 /* portlist is release at port_disconnect_release, thanx Paul */
2603                 port_disconnect_release(portlist, message_type, param);
2604                 break;
2605
2606                 /* PORT sends a TIMEOUT message */
2607                 case MESSAGE_TIMEOUT:
2608                 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);
2609                 port_timeout(portlist, message_type, param);
2610                 break; /* release */
2611
2612                 /* PORT sends a NOTIFY message */
2613                 case MESSAGE_NOTIFY:
2614                 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);
2615                 port_notify(portlist, message_type, param);
2616                 break;
2617
2618                 /* PORT sends a PROGRESS message */
2619                 case MESSAGE_PROGRESS:
2620                 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);
2621                 port_progress(portlist, message_type, param);
2622                 break;
2623
2624                 /* PORT sends a SUSPEND message */
2625                 case MESSAGE_SUSPEND:
2626                 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);
2627                 port_suspend(portlist, message_type, param);
2628                 break; /* suspend */
2629
2630                 /* PORT sends a RESUME message */
2631                 case MESSAGE_RESUME:
2632                 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);
2633                 port_resume(portlist, message_type, param);
2634                 break;
2635
2636 #if 0
2637                 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2638                 /* port assigns bchannel */
2639                 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2640                 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);
2641                 /* only one port is expected to be connected to bchannel */
2642                 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2643                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2644                 break;
2645 #endif
2646
2647                 /* PORT requests DTMF */
2648                 case MESSAGE_ENABLEKEYPAD:
2649                 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);
2650                 port_enablekeypad(portlist, message_type, param);
2651                 break;
2652
2653                 case MESSAGE_DISABLE_DEJITTER:
2654                 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);
2655                 port_disable_dejitter(portlist, message_type, param);
2656                 break;
2657
2658                 case MESSAGE_UPDATEBRIDGE:
2659                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming updatebridge message (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2660                 port_updatebridge(portlist, message_type, param);
2661                 break;
2662
2663                 case MESSAGE_VOOTP:
2664                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming vootp message (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2665                 port_vootp(portlist, message_type, param);
2666                 break;
2667
2668
2669                 default:
2670                 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);
2671         }
2672
2673         /* Note: this endpoint may be destroyed, so we MUST return */
2674 }
2675
2676
2677 /* messages from join
2678  */
2679 /* join MESSAGE_CRYPT */
2680 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2681 {
2682 #ifdef WITH_CRYPT
2683         switch(param->crypt.type) {
2684                 /* message from remote port to "crypt manager" */
2685                 case CU_ACTK_REQ:           /* activate key-exchange */
2686                 case CU_ACTS_REQ:            /* activate shared key */
2687                 case CU_DACT_REQ:          /* deactivate */
2688                 case CU_INFO_REQ:         /* request last info message */
2689                 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2690                 break;
2691
2692                 /* message from "crypt manager" to user */
2693                 case CU_ACTK_CONF:          /* key-echange done */
2694                 case CU_ACTS_CONF:          /* shared key done */
2695                 case CU_DACT_CONF:           /* deactivated */
2696                 case CU_DACT_IND:           /* deactivated */
2697                 case CU_ERROR_IND:         /* receive error message */
2698                 case CU_INFO_IND:         /* receive info message */
2699                 case CU_INFO_CONF:         /* receive info message */
2700                 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2701                 break;
2702
2703                 default:
2704                 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);
2705         }
2706 #endif
2707 }
2708
2709 /* join MESSAGE_INFORMATION */
2710 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2711 {
2712         struct lcr_msg *message;
2713
2714         e_overlap = 1;
2715
2716         while(portlist) {
2717                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2718                 memcpy(&message->param.information, &param->information, sizeof(struct dialing_info));
2719                 message_put(message);
2720                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2721                 portlist = portlist->next;
2722         }
2723 }
2724
2725 /* join MESSAGE_FACILITY */
2726 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2727 {
2728         struct lcr_msg *message;
2729
2730         if (!e_ext.facility && e_ext.number[0]) {
2731                 return;
2732         }
2733
2734         while(portlist) {
2735                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2736                 memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
2737                 message_put(message);
2738                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2739                 portlist = portlist->next;
2740         }
2741 }
2742
2743 /* join MESSAGE_MORE */
2744 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2745 {
2746         struct lcr_msg *message;
2747
2748         new_state(EPOINT_STATE_IN_OVERLAP);
2749         
2750         /* own dialtone */
2751         if (e_join_pattern && e_ext.own_setup) {
2752                 /* disconnect audio */
2753                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2754                 message->param.audiopath = 0;
2755                 message_put(message);
2756         }
2757         if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2758                         if (e_dialinginfo.id[0])
2759                                 set_tone(portlist, "dialing");
2760                         else
2761                                 set_tone(portlist, "dialtone");
2762                         return;
2763         }
2764         if (e_dialinginfo.id[0]) {
2765                 set_tone(portlist, "dialing");
2766         } else {
2767                 if (e_ext.number[0])
2768                         set_tone(portlist, "dialpbx");
2769                 else
2770                         set_tone(portlist, "dialtone");
2771         }
2772 }
2773
2774 /* join MESSAGE_PROCEEDING */
2775 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2776 {
2777         struct lcr_msg *message;
2778
2779         new_state(EPOINT_STATE_IN_PROCEEDING);
2780
2781         /* own proceeding tone */
2782         if (e_join_pattern) {
2783                 /* connect / disconnect audio */
2784                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2785                 if (e_ext.own_proceeding)
2786                         message->param.audiopath = 0;
2787                 else
2788                         message->param.audiopath = 1;
2789                 message_put(message);
2790         }
2791 //                      UCPY(e_join_tone, "proceeding");
2792         if (portlist) {
2793                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2794                 message_put(message);
2795                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2796         }
2797         set_tone(portlist, "proceeding");
2798 }
2799
2800 /* join MESSAGE_ALERTING */
2801 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2802 {
2803         struct lcr_msg *message;
2804
2805         new_state(EPOINT_STATE_IN_ALERTING);
2806
2807         /* own alerting tone */
2808         if (e_join_pattern) {
2809                 /* connect / disconnect audio */
2810                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2811                 if (e_ext.own_alerting)
2812                         message->param.audiopath = 0;
2813                 else
2814                         message->param.audiopath = 1;
2815                 message_put(message);
2816         }
2817         if (portlist) {
2818                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2819                 message_put(message);
2820                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2821         }
2822         if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2823                 set_tone(portlist, "ringing");
2824                 return;
2825         }
2826         if (e_ext.number[0])
2827                 set_tone(portlist, "ringpbx");
2828         else
2829                 set_tone(portlist, "ringing");
2830
2831         if (e_ext.number[0])
2832                 e_dtmf = 1; /* allow dtmf */
2833 }
2834
2835 /* join MESSAGE_CONNECT */
2836 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2837 {
2838         struct lcr_msg *message;
2839         time_t now;
2840
2841         new_state(EPOINT_STATE_CONNECT);
2842 //                      UCPY(e_join_tone, "");
2843 //                      
2844         if (e_ext.number[0])
2845                 e_dtmf = 1; /* allow dtmf */
2846
2847         e_powerdial_on = 0;
2848         unsched_timer(&e_powerdial_timeout);
2849         memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_callerinfo));
2850         if(portlist) {
2851                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2852                 memcpy(&message->param, param, sizeof(union parameter));
2853
2854                 /* screen clip if prefix is required */
2855                 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2856                         SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2857                         SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2858                         message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2859                 }
2860
2861                 /* use internal caller id */
2862                 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2863                         SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2864                         message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2865                 }
2866
2867                 /* handle restricted caller ids */
2868                 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);
2869                 /* display callerid if desired for extension */
2870                 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));
2871
2872                 /* use conp, if enabld */
2873 //              if (!e_ext.centrex)
2874 //                      message->param.connectinfo.name[0] = '\0';
2875
2876                 /* send connect */
2877                 message_put(message);
2878                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2879         }
2880         set_tone(portlist, NULL);
2881         e_join_pattern = 0;
2882         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2883         message->param.audiopath = 1;
2884         message_put(message);
2885         time(&now);
2886         e_start = now;
2887 }
2888
2889 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2890 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2891 {
2892         char cause[16];
2893         struct lcr_msg *message;
2894         struct port_list *portlist = NULL;
2895         time_t now;
2896
2897
2898         /* be sure that we are active */
2899         notify_active();
2900         e_tx_state = NOTIFY_STATE_ACTIVE;
2901
2902         /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
2903         if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2904                 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
2905
2906                 /* set time for power dialing */
2907                 schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
2908                 e_powercount++;
2909
2910                 /* set redial tone */
2911                 if (ea_endpoint->ep_portlist) {
2912                         e_join_pattern = 0;
2913                 }
2914                 set_tone(ea_endpoint->ep_portlist, "redial");
2915                 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);
2916                 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2917                 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2918                         new_state(EPOINT_STATE_IN_PROCEEDING);
2919                         if (ea_endpoint->ep_portlist) {
2920                                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2921                                 message_put(message);
2922                                 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2923                         }
2924 /* caused the error, that the first knock sound was not there */
2925 /*                                      set_tone(portlist, "proceeding"); */
2926                 }
2927                 /* send display of powerdialing */
2928                 if (e_ext.display_dialing) {
2929                         portlist = ea_endpoint->ep_portlist;
2930                         while (portlist) {
2931                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2932                                 if (e_powerlimit)
2933                                         SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2934                                 else
2935                                         SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2936                                 message_put(message);
2937                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2938                                 portlist = portlist->next;
2939                         }
2940                 }
2941                 return;
2942         }
2943
2944         /* set stop time */
2945         time(&now);
2946         e_stop = now;
2947
2948         if ((e_state!=EPOINT_STATE_CONNECT
2949           && e_state!=EPOINT_STATE_OUT_DISCONNECT
2950           && e_state!=EPOINT_STATE_IN_OVERLAP
2951           && e_state!=EPOINT_STATE_IN_PROCEEDING
2952           && e_state!=EPOINT_STATE_IN_ALERTING)
2953          || !ea_endpoint->ep_portlist) { /* or no port */
2954                 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
2955                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
2956                 return; /* must exit here */
2957         }
2958         /* save cause */
2959         if (!e_join_cause) {
2960                 e_join_cause = param->disconnectinfo.cause;
2961                 e_join_location = param->disconnectinfo.location;
2962         }
2963
2964         /* on release we need the audio again! */
2965         if (message_type == MESSAGE_RELEASE) {
2966                 e_join_pattern = 0;
2967                 ea_endpoint->ep_join_id = 0;
2968         }
2969         /* disconnect and select tone */
2970         new_state(EPOINT_STATE_OUT_DISCONNECT);
2971         SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2972         /* if own_cause, we must release the join */
2973         if (e_ext.own_cause /* own cause */
2974          || !e_join_pattern) { /* no patterns */
2975                 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);
2976                 if (message_type != MESSAGE_RELEASE)
2977                         release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2978                 e_join_pattern = 0;
2979         } else { /* else we enable audio */
2980                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2981                 message->param.audiopath = 1;
2982                 message_put(message);
2983         }
2984         /* send disconnect message */
2985         SCPY(e_tone, cause);
2986         portlist = ea_endpoint->ep_portlist;
2987         while(portlist) {
2988                 set_tone(portlist, cause);
2989                 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2990                 portlist = portlist->next;
2991         }
2992 }
2993
2994 /* join MESSAGE_SETUP */
2995 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
2996 {
2997         struct lcr_msg *message;
2998 //      struct interface        *interface;
2999
3000         /* if we already in setup state, we just update the dialing with new digits */
3001         if (e_state == EPOINT_STATE_OUT_SETUP
3002          || e_state == EPOINT_STATE_OUT_OVERLAP) {
3003                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3004                 /* if digits changed, what we have already dialed */
3005                 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
3006                         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);
3007                         /* release all ports */
3008                         while((portlist = ea_endpoint->ep_portlist)) {
3009                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3010                                 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3011                                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3012                                 message_put(message);
3013                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3014                                 ea_endpoint->free_portlist(portlist);
3015                         }
3016
3017                         /* disconnect audio */
3018                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3019                         message->param.audiopath = 0;
3020                         message_put(message);
3021
3022                         /* get dialing info */
3023                         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
3024                         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3025                         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
3026                         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
3027                         new_state(EPOINT_STATE_OUT_OVERLAP);
3028
3029                         /* get time */
3030                         schedule_timer(&e_redial_timeout, 1, 0);
3031                         return;
3032                 }
3033                 /* if we have a pending redial, so we just adjust the dialing number */
3034                 if (e_redial_timeout.active) {
3035                         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);
3036                         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3037                         return;
3038                 }
3039                 if (!ea_endpoint->ep_portlist) {
3040                         PERROR("ERROR: overlap dialing to a NULL port relation\n");
3041                 }
3042                 if (ea_endpoint->ep_portlist->next) {
3043                         PERROR("ERROR: overlap dialing to a port_list port relation\n");
3044                 }
3045                 if (e_state == EPOINT_STATE_OUT_SETUP) {
3046                         /* queue digits */
3047                         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);
3048                         SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3049                         
3050                 } else {
3051                         /* get what we have not dialed yet */
3052                         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));
3053                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3054                         SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3055                         message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3056                         message_put(message);
3057                         logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3058                 }
3059                 /* always store what we have dialed or queued */
3060                 memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3061                 
3062                 return;
3063         }
3064         if (e_state != EPOINT_STATE_IDLE) {
3065                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3066                 return;
3067         }
3068         /* if an internal extension is dialed, copy that number */
3069         if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3070                 SCPY(e_ext.number, param->setup.dialinginfo.id);
3071         /* if an internal extension is dialed, get extension's info about caller */
3072         if (e_ext.number[0]) {
3073                 if (!read_extension(&e_ext, e_ext.number)) {
3074                         e_ext.number[0] = '\0';
3075                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3076                 }
3077         }
3078
3079         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
3080         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3081         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
3082         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
3083         memcpy(&e_rtpinfo, &param->setup.rtpinfo, sizeof(e_rtpinfo));
3084
3085         /* process (voice over) data calls */
3086         if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3087                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3088                 memset(&e_capainfo, 0, sizeof(e_capainfo));
3089                 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3090                 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3091                 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3092         }
3093
3094         new_state(EPOINT_STATE_OUT_SETUP);
3095         /* call special setup routine */
3096         out_setup(0);
3097 }
3098
3099 /* join MESSAGE_mISDNSIGNAL */
3100 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3101 {
3102         struct lcr_msg *message;
3103
3104         while(portlist) {
3105                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3106                 memcpy(&message->param, param, sizeof(union parameter));
3107                 message_put(message);
3108                 portlist = portlist->next;
3109         }
3110 }
3111
3112 /* join MESSAGE_BRIDE */
3113 void EndpointAppPBX::join_bridge(struct port_list *portlist, int message_type, union parameter *param)
3114 {
3115         struct lcr_msg *message;
3116
3117         while(portlist) {
3118                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
3119                 memcpy(&message->param, param, sizeof(union parameter));
3120                 message_put(message);
3121                 portlist = portlist->next;
3122         }
3123 }
3124
3125 /* join MESSAGE_NOTIFY */
3126 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3127 {
3128         struct lcr_msg *message;
3129         int new_state;
3130
3131         if (param->notifyinfo.notify) {
3132                 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3133 //              /* if notification was generated locally, we turn hold music on/off */ 
3134 //              if (param->notifyinfo.local)
3135 // 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)
3136                 {
3137                         if (e_hold) {
3138                                 /* unhold if */
3139                                 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3140                                         if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3141                                                 while(portlist) {
3142                                                         set_tone(portlist, "");
3143                                                         portlist = portlist->next;
3144                                                 }
3145                                         }
3146                                         portlist = ea_endpoint->ep_portlist;
3147                                         e_hold = 0;
3148                                 }
3149                         } else {
3150                                 /* hold if */
3151                                 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3152                                         while(portlist) {
3153                                                 set_tone(portlist, "hold");
3154                                                 portlist = portlist->next;
3155                                         }
3156                                         portlist = ea_endpoint->ep_portlist;
3157                                         e_hold = 1;
3158                                 }
3159                         }
3160                 }
3161                 /* save new state */
3162                 e_tx_state = new_state;
3163         }
3164
3165         /* notify port(s) about it */
3166         while(portlist) {
3167                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3168                 memcpy(&message->param.notifyinfo, &param->notifyinfo, sizeof(struct notify_info));
3169                 /* handle restricted caller ids */
3170                 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3171                 /* display callerid if desired for extension */
3172                 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));
3173                 message_put(message);
3174                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3175                 portlist = portlist->next;
3176         }
3177 }
3178
3179 /* join MESSAGE_DTMF */
3180 void EndpointAppPBX::join_dtmf(struct port_list *portlist, int message_type, union parameter *param)
3181 {
3182         struct lcr_msg *message;
3183
3184         while(portlist) {
3185                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DTMF);
3186                 memcpy(&message->param, param, sizeof(union parameter));
3187                 message_put(message);
3188                 portlist = portlist->next;
3189         }
3190 }
3191
3192 /* join MESSAGE_DISABLE_DEJITTER */
3193 void EndpointAppPBX::join_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param)
3194 {
3195         struct lcr_msg *message;
3196
3197         while(portlist) {
3198                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISABLE_DEJITTER);
3199                 memcpy(&message->param, param, sizeof(union parameter));
3200                 message_put(message);
3201                 portlist = portlist->next;
3202         }
3203 }
3204
3205 /* JOIN sends messages to the endpoint
3206  */
3207 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3208 {
3209         struct port_list *portlist;
3210         struct lcr_msg *message;
3211
3212         if (!join_id) {
3213                 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3214                 return;
3215         }
3216
3217         portlist = ea_endpoint->ep_portlist;
3218
3219 //      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);
3220         switch(message_type) {
3221                 /* JOIN SENDS TONE message */
3222                 case MESSAGE_TONE:
3223                 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);
3224                 set_tone(portlist, param->tone.name);
3225                 break;
3226
3227                 /* JOIN SENDS CRYPT message */
3228                 case MESSAGE_CRYPT:
3229                 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);
3230                 join_crypt(portlist, message_type, param);
3231                 break;
3232
3233                 /* JOIN sends INFORMATION message */
3234                 case MESSAGE_INFORMATION:
3235                 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);
3236                 join_information(portlist, message_type, param);
3237                 break;
3238
3239                 /* JOIN sends FACILITY message */
3240                 case MESSAGE_FACILITY:
3241                 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);
3242                 join_facility(portlist, message_type, param);
3243                 break;
3244
3245                 /* JOIN sends OVERLAP message */
3246                 case MESSAGE_OVERLAP:
3247                 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);
3248                 if (e_state!=EPOINT_STATE_IN_SETUP
3249                  && e_state!=EPOINT_STATE_IN_OVERLAP) {
3250                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3251                         break;
3252                 }
3253                 join_overlap(portlist, message_type, param);
3254                 break;
3255
3256                 /* JOIN sends PROCEEDING message */
3257                 case MESSAGE_PROCEEDING:
3258                 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);
3259                 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3260                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3261                         break;
3262                 }
3263                 join_proceeding(portlist, message_type, param);
3264                 break;
3265
3266                 /* JOIN sends ALERTING message */
3267                 case MESSAGE_ALERTING:
3268                 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);
3269                 if (e_state!=EPOINT_STATE_IN_OVERLAP
3270                  && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3271                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3272                         break;
3273                 }
3274                 join_alerting(portlist, message_type, param);
3275                 break;
3276
3277                 /* JOIN sends CONNECT message */
3278                 case MESSAGE_CONNECT:
3279                 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);
3280                 if (e_state!=EPOINT_STATE_IN_OVERLAP
3281                  && e_state!=EPOINT_STATE_IN_PROCEEDING
3282                  && e_state!=EPOINT_STATE_IN_ALERTING) {
3283                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3284                         break;
3285                 }
3286                 join_connect(portlist, message_type, param);
3287                 break;
3288
3289                 /* JOIN sends DISCONNECT/RELEASE message */
3290                 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3291                 case MESSAGE_RELEASE: /* JOIN releases */
3292                 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);
3293                 join_disconnect_release(message_type, param);
3294                 break;
3295
3296                 /* JOIN sends SETUP message */
3297                 case MESSAGE_SETUP:
3298                 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);
3299                 join_setup(portlist, message_type, param);
3300                 break;
3301
3302                 /* JOIN sends special mISDNSIGNAL message */
3303                 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3304                 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);
3305                 join_mISDNsignal(portlist, message_type, param);
3306                 break;
3307
3308                 /* JOIN sends bridge message */
3309                 case MESSAGE_BRIDGE: /* bride message to port */
3310                 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);
3311                 join_bridge(portlist, message_type, param);
3312                 break;
3313
3314                 /* JOIN has pattern available */
3315                 case MESSAGE_PATTERN: /* indicating pattern available */
3316                 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);
3317                 if (!e_join_pattern) {
3318                         PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3319                         e_join_pattern = 1;
3320                         SCPY(e_tone, "");
3321                         while(portlist) {
3322                                 set_tone(portlist, NULL);
3323                                 portlist = portlist->next;
3324                         }
3325                         /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3326                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3327                         message->param.audiopath = 1;
3328                         message_put(message);
3329                 }
3330                 break;
3331
3332                 /* JOIN has no pattern available */
3333                 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3334                 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);
3335                 if (e_join_pattern) {
3336                         PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3337                         e_join_pattern = 0;
3338                         /* disconnect our audio tx and rx */
3339                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3340                         message->param.audiopath = 0;
3341                         message_put(message);
3342                 }
3343                 break;
3344
3345 #if 0
3346                 /* JOIN (dunno at the moment) */
3347                 case MESSAGE_REMOTE_AUDIO:
3348                 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);
3349                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3350                 message->param.audiopath = param->channel;
3351                 message_put(message);
3352                 break;
3353 #endif
3354
3355                 /* JOIN sends a notify message */
3356                 case MESSAGE_NOTIFY:
3357                 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);
3358                 join_notify(portlist, message_type, param);
3359                 break;
3360
3361                 /* JOIN wants keypad / dtmf */
3362                 case MESSAGE_ENABLEKEYPAD:
3363                 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);
3364                 e_enablekeypad = 1;
3365                 e_dtmf = 1;
3366                 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3367                 end_trace();
3368                 break;
3369
3370                 /* JOIN sends a DTMF message */
3371                 case MESSAGE_DTMF:
3372                 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);
3373                 join_dtmf(portlist, message_type, param);
3374                 break;
3375
3376                 /* JOIN sends a DISABLE_DEJITTER message */
3377                 case MESSAGE_DISABLE_DEJITTER:
3378                 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);
3379                 join_disable_dejitter(portlist, message_type, param);
3380                 break;
3381
3382                 default:
3383                 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);
3384         }
3385 }
3386
3387
3388 /* pick_join will connect the first incoming call found. the endpoint
3389  * will receivce a MESSAGE_CONNECT.
3390  */
3391 int match_list(char *list, char *item)
3392 {
3393         char *end, *next = NULL;
3394
3395         /* no list make matching */
3396         if (!list)
3397                 return(1);
3398
3399         while(42) {
3400                 /* eliminate white spaces */
3401                 while (*list > '\0' && *list <= ' ')
3402                         list++;
3403                 if (*list == ',') {
3404                         list++;
3405                         continue;
3406                 }
3407                 /* if end of list is reached, we return */
3408                 if (list[0] == '\0')
3409                         return(0);
3410                 /* if we have more than one entry (left) */
3411                 if ((end = strchr(list, ',')))
3412                         next = end + 1;
3413                 else
3414                         next = end = strchr(list, '\0');
3415                 while (*(end-1) <= ' ')
3416                         end--;
3417                 /* if string part matches item */
3418                 if (!strncmp(list, item, end-list))
3419                         return(1);
3420                 list = next;
3421         }
3422 }
3423
3424 void EndpointAppPBX::pick_join(char *extensions)
3425 {
3426         struct lcr_msg *message;
3427         struct port_list *portlist;
3428         class Port *port;
3429         class EndpointAppPBX *eapp, *found;
3430         class Join *join;
3431         class JoinPBX *joinpbx;
3432         struct join_relation *relation;
3433
3434         /* find an endpoint that is ringing internally or vbox with higher priority */
3435         found = NULL;
3436         eapp = apppbx_first;
3437         while(eapp) {
3438                 if (eapp!=this && ea_endpoint->ep_portlist) {
3439                         portlist = eapp->ea_endpoint->ep_portlist;
3440                         while(portlist) {
3441                                 if ((port = find_port_id(portlist->port_id))) {
3442                                         if (port->p_type == PORT_TYPE_VBOX_OUT) {
3443                                                 if (match_list(extensions, eapp->e_ext.number)) {
3444                                                         found = eapp;
3445                                                         break;
3446                                                 }
3447                                         }
3448                                         if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT
3449                                          && port->p_state==PORT_STATE_OUT_ALERTING)
3450                                                 if (match_list(extensions, eapp->e_ext.number)) {
3451                                                         found = eapp;
3452                                                 }
3453                                 }
3454                                 portlist = portlist->next;
3455                         }
3456                         if (portlist)
3457                                 break;
3458                 }
3459                 eapp = eapp->next;
3460         }
3461
3462         /* if no endpoint found */
3463         if (!found) {
3464                 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);
3465 reject:
3466                 set_tone(ea_endpoint->ep_portlist, "cause_10");
3467                 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3468                 new_state(EPOINT_STATE_OUT_DISCONNECT);
3469                 return;
3470         }
3471         eapp = found;
3472
3473         if (ea_endpoint->ep_join_id) {
3474                 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3475                 goto reject;
3476         }
3477         if (!eapp->ea_endpoint->ep_join_id) {
3478                 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3479                 goto reject;
3480         }
3481         join = find_join_id(eapp->ea_endpoint->ep_join_id);
3482         if (!join) {
3483                 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3484                 goto reject;
3485         }
3486         if (join->j_type != JOIN_TYPE_PBX) {
3487                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3488                 goto reject;
3489         }
3490         joinpbx = (class JoinPBX *)join;
3491         relation = joinpbx->j_relation;
3492         if (!relation) {
3493                 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3494                 goto reject;
3495         }
3496         while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
3497                 relation = relation->next;
3498                 if (!relation) {
3499                         PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3500                         goto reject;
3501                 }
3502         }
3503
3504         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3505
3506         if (options.deb & DEBUG_EPOINT) {
3507                 class Join *debug_c = join_first;
3508                 class Endpoint *debug_e = epoint_first;
3509                 class Port *debug_p = port_first;
3510
3511                 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3512
3513                 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3514                 while(debug_c) {
3515                         PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3516                         debug_c = debug_c->next;
3517                 }
3518                 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3519                 while(debug_e) {
3520                         PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3521                         debug_e = debug_e->next;
3522                 }
3523                 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3524                 while(debug_p) {
3525                         PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3526                         debug_p = debug_p->next;
3527                 }
3528         }
3529
3530         /* relink join */
3531         ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3532         relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3533         eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3534
3535         /* connnecting our endpoint */
3536         new_state(EPOINT_STATE_CONNECT);
3537         if (e_ext.number[0])
3538                 e_dtmf = 1;
3539         set_tone(ea_endpoint->ep_portlist, NULL);
3540
3541         /* now we send a release to the ringing endpoint */
3542         message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3543         message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3544         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3545         message_put(message);
3546
3547         /* we send a connect to the join with our caller id */
3548         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3549         SCPY(message->param.connectinfo.id, e_callerinfo.id);
3550         message->param.connectinfo.present = e_callerinfo.present;
3551         message->param.connectinfo.screen = e_callerinfo.screen;
3552         message->param.connectinfo.itype = e_callerinfo.itype;
3553         message->param.connectinfo.ntype = e_callerinfo.ntype;
3554         message_put(message);
3555
3556         /* we send a connect to our port with the remote callerid */
3557         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3558         SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3559         message->param.connectinfo.present = eapp->e_callerinfo.present;
3560         message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3561         message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3562         message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3563         /* handle restricted caller ids */
3564         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);
3565         /* display callerid if desired for extension */
3566         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));
3567         message_put(message);
3568
3569         /* we send a connect to the audio path (not for vbox) */
3570         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3571         message->param.audiopath = 1;
3572         message_put(message);
3573
3574         /* beeing paranoid, we make call update */
3575         trigger_work(&joinpbx->j_updatebridge);
3576
3577         if (options.deb & DEBUG_EPOINT) {
3578                 class Join *debug_c = join_first;
3579                 class Endpoint *debug_e = epoint_first;
3580                 class Port *debug_p = port_first;
3581
3582                 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3583
3584                 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3585                 while(debug_c) {
3586                         PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3587                         debug_c = debug_c->next;
3588                 }
3589                 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3590                 while(debug_e) {
3591                         PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3592                         debug_e = debug_e->next;
3593                 }
3594                 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3595                 while(debug_p) {
3596                         PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3597                         debug_p = debug_p->next;
3598                 }
3599         }
3600 }
3601
3602
3603 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3604  */
3605 int EndpointAppPBX::join_join_dss1(void)
3606 {
3607 #ifdef WITH_MISDN
3608         struct lcr_msg *message;
3609         struct join_relation *add_relation, *remove_relation;
3610         struct join_relation **add_relation_pointer, **remove_relation_pointer;
3611         class Join *our_join, *other_join, *add_join, *remove_join;
3612         class JoinPBX *our_joinpbx, *other_joinpbx, *add_joinpbx, *remove_joinpbx;
3613         class EndpointAppPBX *other_eapp, *remove_eapp;
3614         class Port *our_port, *other_port;
3615         class Pdss1 *our_pdss1, *other_pdss1;
3616         class Endpoint *temp_epoint;
3617
3618         /* are we a candidate to join a join? */
3619         our_join = find_join_id(ea_endpoint->ep_join_id);
3620         if (!our_join) {
3621                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3622                 return -1;
3623         }
3624         if (our_join->j_type != JOIN_TYPE_PBX) {
3625                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3626                 return -1;
3627         }
3628         our_joinpbx = (class JoinPBX *)our_join;
3629         if (!ea_endpoint->ep_portlist) {
3630                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3631                 return -1;
3632         }
3633         if (!e_ext.number[0]) {
3634                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3635                 return -1;
3636         }
3637         our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3638         if (!our_port) {
3639                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3640                 return -1;
3641         }
3642         if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
3643                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3644                 return -1;
3645         }
3646         our_pdss1 = (class Pdss1 *)our_port;
3647
3648         /* find an endpoint that has the same mISDNport/ces that we are on */
3649         other_eapp = apppbx_first;
3650         while(other_eapp) {
3651                 if (other_eapp == this) {
3652                         other_eapp = other_eapp->next;
3653                         continue;
3654                 }
3655                 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);
3656                 if (other_eapp->e_ext.number[0] /* has terminal */
3657                  && other_eapp->ea_endpoint->ep_portlist /* has port */
3658                  && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3659                         other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3660                         if (other_port) { /* port still exists */
3661                                 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3662                                  || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3663                                         other_pdss1 = (class Pdss1 *)other_port;
3664                                         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);
3665                                         if (1 //other_pdss1->p_m_hold /* port is on hold */
3666                                          && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3667                                          && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3668                                                 break;
3669                                 } else {
3670                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3671                                 }
3672                         } else {
3673                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3674                         }
3675                 }
3676                 other_eapp = other_eapp->next;
3677         }
3678         if (!other_eapp) {
3679                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3680                 return -1;
3681         }
3682         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3683
3684         /* if we have the same join */
3685         if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3686                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3687                 return -1;
3688         }
3689         other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3690         if (!other_join) {
3691                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3692                 return -1;
3693         }
3694         if (other_join->j_type != JOIN_TYPE_PBX) {
3695                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3696                 return -1;
3697         }
3698         other_joinpbx = (class JoinPBX *)other_join;
3699         if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3700                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3701                 return -1;
3702         }
3703
3704         /* now find out which is ACTIVE-IDLE and which is ACTIVE-HELD */
3705         if (our_pdss1->p_m_hold && !other_pdss1->p_m_hold) {
3706                 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);
3707                 remove_eapp = this;
3708                 remove_join = our_join;
3709                 remove_joinpbx = our_joinpbx;
3710                 add_join = other_join;
3711                 add_joinpbx = other_joinpbx;
3712         } else {
3713                 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);
3714                 remove_eapp = other_eapp;
3715                 remove_join = other_join;
3716                 remove_joinpbx = other_joinpbx;
3717                 add_join = our_join;
3718                 add_joinpbx = our_joinpbx;
3719         }
3720
3721         /* remove relation to endpoint for join on hold */
3722         remove_relation = remove_joinpbx->j_relation;
3723         remove_relation_pointer = &remove_joinpbx->j_relation;
3724         while(remove_relation) {
3725                 if (remove_relation->epoint_id == remove_eapp->ea_endpoint->ep_serial) {
3726                         /* detach other endpoint */
3727                         *remove_relation_pointer = remove_relation->next;
3728                         FREE(remove_relation, sizeof(struct join_relation));
3729                         cmemuse--;
3730                         remove_relation = *remove_relation_pointer;
3731                         remove_eapp->ea_endpoint->ep_join_id = 0;
3732                         continue;
3733                 }
3734
3735                 /* change join/hold pointer of endpoint to the new join */
3736                 temp_epoint = find_epoint_id(remove_relation->epoint_id);
3737                 if (temp_epoint) {
3738                         if (temp_epoint->ep_join_id == remove_join->j_serial)
3739                                 temp_epoint->ep_join_id = add_join->j_serial;
3740                 }
3741
3742                 remove_relation_pointer = &remove_relation->next;
3743                 remove_relation = remove_relation->next;
3744         }
3745         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint removed, other enpoints on join relinked.\n", ea_endpoint->ep_serial);
3746
3747         /* join call relations */
3748         add_relation = add_joinpbx->j_relation;
3749         add_relation_pointer = &add_joinpbx->j_relation;
3750         while(add_relation) {
3751                 add_relation_pointer = &add_relation->next;
3752                 add_relation = add_relation->next;
3753         }
3754         *add_relation_pointer = remove_joinpbx->j_relation;
3755         remove_joinpbx->j_relation = NULL;
3756         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3757
3758         /* release endpoint */
3759         message = message_create(remove_joinpbx->j_serial, remove_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3760         message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3761         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3762         message_put(message);
3763         
3764         /* if we are not a partyline, we get partyline state from other join */
3765         add_joinpbx->j_partyline += remove_joinpbx->j_partyline; 
3766
3767         /* remove empty join */
3768         delete remove_join;
3769         PDEBUG(DEBUG_EPOINT, "EPOINT(%d)join completely removed!\n", ea_endpoint->ep_serial);
3770
3771         /* mixer must update */
3772         trigger_work(&add_joinpbx->j_updatebridge);
3773
3774         /* we send a retrieve to that endpoint */
3775         // mixer will update the hold-state of the join and send it to the endpoints is changes
3776 #else
3777         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
3778 #endif
3779
3780         return 0;
3781 }
3782
3783 /* join calls (look for a join that is on hold (same fxs interface/terminal))
3784  */
3785 int EndpointAppPBX::join_join_fxs(void)
3786 {
3787 #ifdef WITH_MISDN
3788         struct lcr_msg *message;
3789         struct join_relation *add_relation, *remove_relation;
3790         struct join_relation **add_relation_pointer, **remove_relation_pointer;
3791         class Join *our_join, *other_join, *add_join, *remove_join;
3792         class JoinPBX *our_joinpbx, *other_joinpbx, *add_joinpbx, *remove_joinpbx;
3793         class EndpointAppPBX *other_eapp, *remove_eapp;
3794         class Port *our_port, *other_port;
3795         class Pfxs *our_fxs, *other_fxs;
3796         class Endpoint *temp_epoint;
3797
3798         /* are we a candidate to join a join? */
3799         our_join = find_join_id(ea_endpoint->ep_join_id);
3800         if (!our_join) {
3801                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3802                 return -1;
3803         }
3804         if (our_join->j_type != JOIN_TYPE_PBX) {
3805                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3806                 return -1;
3807         }
3808         our_joinpbx = (class JoinPBX *)our_join;
3809         if (!ea_endpoint->ep_portlist) {
3810                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3811                 return -1;
3812         }
3813         if (!e_ext.number[0]) {
3814                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3815                 return -1;
3816         }
3817         our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3818         if (!our_port) {
3819                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3820                 return -1;
3821         }
3822         if ((our_port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) {
3823                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not fxs.\n", ea_endpoint->ep_serial);
3824                 return -1;
3825         }
3826         our_fxs = (class Pfxs *)our_port;
3827
3828         /* find an endpoint that has the same mISDNport that we are on */
3829         other_eapp = apppbx_first;
3830         while(other_eapp) {
3831                 if (other_eapp == this) {
3832                         other_eapp = other_eapp->next;
3833                         continue;
3834                 }
3835                 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);
3836                 if (other_eapp->e_ext.number[0] /* has terminal */
3837                  && other_eapp->ea_endpoint->ep_portlist /* has port */
3838                  && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3839                         other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3840                         if (other_port) { /* port still exists */
3841                                 if (other_port->p_type==PORT_TYPE_POTS_FXS_OUT
3842                                  || other_port->p_type==PORT_TYPE_POTS_FXS_IN) { /* port is FXS */
3843                                         other_fxs = (class Pfxs *)other_port;
3844                                         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);
3845                                         if (1 //other_fxs->p_m_hold /* port is on hold */
3846                                          && other_fxs->p_m_mISDNport == our_fxs->p_m_mISDNport) /* same isdn interface */
3847                                                 break;
3848                                 } else {
3849                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3850                                 }
3851                         } else {
3852                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3853                         }
3854                 }
3855                 other_eapp = other_eapp->next;
3856         }
3857         if (!other_eapp) {
3858                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same FXS terminal.\n", ea_endpoint->ep_serial);
3859                 return -1;
3860         }
3861         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3862
3863         /* if we have the same join */
3864         if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3865                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3866                 return -1;
3867         }
3868         other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3869         if (!other_join) {
3870                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3871                 return -1;
3872         }
3873         if (other_join->j_type != JOIN_TYPE_PBX) {
3874                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3875                 return -1;
3876         }
3877         other_joinpbx = (class JoinPBX *)other_join;
3878         if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3879                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3880                 return -1;
3881         }
3882
3883         /* now find out which is ACTIVE-IDLE and which is ACTIVE-HELD */
3884         if (our_fxs->p_m_hold && !other_fxs->p_m_hold) {
3885                 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);
3886                 remove_eapp = this;
3887                 remove_join = our_join;
3888                 remove_joinpbx = our_joinpbx;
3889                 add_join = other_join;
3890                 add_joinpbx = other_joinpbx;
3891         } else {
3892                 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);
3893                 remove_eapp = other_eapp;
3894                 remove_join = other_join;
3895                 remove_joinpbx = other_joinpbx;
3896                 add_join = our_join;
3897                 add_joinpbx = our_joinpbx;
3898         }
3899
3900         /* remove relation to endpoint for join on hold */
3901         remove_relation = remove_joinpbx->j_relation;
3902         remove_relation_pointer = &remove_joinpbx->j_relation;
3903         while(remove_relation) {
3904                 if (remove_relation->epoint_id == remove_eapp->ea_endpoint->ep_serial) {
3905                         /* detach other endpoint */
3906                         *remove_relation_pointer = remove_relation->next;
3907                         FREE(remove_relation, sizeof(struct join_relation));
3908                         cmemuse--;
3909                         remove_relation = *remove_relation_pointer;
3910                         remove_eapp->ea_endpoint->ep_join_id = 0;
3911                         continue;
3912                 }
3913
3914                 /* change join/hold pointer of endpoint to the new join */
3915                 temp_epoint = find_epoint_id(remove_relation->epoint_id);
3916                 if (temp_epoint) {
3917                         if (temp_epoint->ep_join_id == remove_join->j_serial)
3918                                 temp_epoint->ep_join_id = add_join->j_serial;
3919                 }
3920
3921                 remove_relation_pointer = &remove_relation->next;
3922                 remove_relation = remove_relation->next;
3923         }
3924         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint removed, other enpoints on join relinked.\n", ea_endpoint->ep_serial);
3925
3926         /* join call relations */
3927         add_relation = add_joinpbx->j_relation;
3928         add_relation_pointer = &add_joinpbx->j_relation;
3929         while(add_relation) {
3930                 add_relation_pointer = &add_relation->next;
3931                 add_relation = add_relation->next;
3932         }
3933         *add_relation_pointer = remove_joinpbx->j_relation;
3934         remove_joinpbx->j_relation = NULL;
3935         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3936
3937         /* release endpoint */
3938         message = message_create(remove_joinpbx->j_serial, remove_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3939         message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3940         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3941         message_put(message);
3942         
3943         /* if we are not a partyline, we get partyline state from other join */
3944         add_joinpbx->j_partyline += remove_joinpbx->j_partyline; 
3945
3946         /* remove empty join */
3947         delete remove_join;
3948         PDEBUG(DEBUG_EPOINT, "EPOINT(%d)join completely removed!\n", ea_endpoint->ep_serial);
3949
3950         /* mixer must update */
3951         trigger_work(&add_joinpbx->j_updatebridge);
3952
3953         /* we send a retrieve to that endpoint */
3954         // mixer will update the hold-state of the join and send it to the endpoints is changes
3955 #else
3956         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
3957 #endif
3958
3959         return 0;
3960 }
3961
3962 int EndpointAppPBX::join_3pty_dss1(void)
3963 {
3964 #ifdef WITH_MISDN
3965         class Join *our_join, *other_join;
3966         class JoinPBX *our_joinpbx, *other_joinpbx;
3967         class EndpointAppPBX *other_eapp;
3968         class Port *our_port, *other_port;
3969         class Pdss1 *our_pdss1, *other_pdss1;
3970
3971         /* are we a candidate to join a join? */
3972         our_join = find_join_id(ea_endpoint->ep_join_id);
3973         if (!our_join) {
3974                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3975                 return -1;
3976         }
3977         if (our_join->j_type != JOIN_TYPE_PBX) {
3978                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3979                 return -1;
3980         }
3981         our_joinpbx = (class JoinPBX *)our_join;
3982         if (!ea_endpoint->ep_portlist) {
3983                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3984                 return -1;
3985         }
3986         if (!e_ext.number[0]) {
3987                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3988                 return -1;
3989         }
3990         our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3991         if (!our_port) {
3992                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3993                 return -1;
3994         }
3995         if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
3996                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3997                 return -1;
3998         }
3999         our_pdss1 = (class Pdss1 *)our_port;
4000
4001         /* find an endpoint that has the same mISDNport/ces that we are on */
4002         other_eapp = apppbx_first;
4003         while(other_eapp) {
4004                 if (other_eapp == this) {
4005                         other_eapp = other_eapp->next;
4006                         continue;
4007                 }
4008                 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);
4009                 if (other_eapp->e_ext.number[0] /* has terminal */
4010                  && other_eapp->ea_endpoint->ep_portlist /* has port */
4011                  && other_eapp->ea_endpoint->ep_join_id) { /* has join */
4012                         other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
4013                         if (other_port) { /* port still exists */
4014                                 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
4015                                  || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
4016                                         other_pdss1 = (class Pdss1 *)other_port;
4017                                         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);
4018                                         if (1 //other_pdss1->p_m_hold /* port is on hold */
4019                                          && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
4020                                          && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
4021                                                 break;
4022                                 } else {
4023                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
4024                                 }
4025                         } else {
4026                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
4027                         }
4028                 }
4029                 other_eapp = other_eapp->next;
4030         }
4031         if (!other_eapp) {
4032                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
4033                 return -1;
4034         }
4035         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
4036
4037         /* if we have the same join */
4038         if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
4039                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
4040                 return -1;
4041         }
4042         other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4043         if (!other_join) {
4044                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4045                 return -1;
4046         }
4047         if (other_join->j_type != JOIN_TYPE_PBX) {
4048                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4049                 return -1;
4050         }
4051         other_joinpbx = (class JoinPBX *)other_join;
4052         if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
4053                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4054                 return -1;
4055         }
4056
4057         if (our_joinpbx->j_3pty) {
4058                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join already doing 3PTY.\n", ea_endpoint->ep_serial);
4059                 return -1;
4060         }
4061         if (other_joinpbx->j_3pty) {
4062                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join already doing 3PTY.\n", ea_endpoint->ep_serial);
4063                 return -1;
4064         }
4065
4066         /* set 3PTY bridge */
4067         other_joinpbx->j_3pty = our_joinpbx->j_serial;
4068         our_joinpbx->j_3pty = other_joinpbx->j_serial;
4069
4070         /* mixer must update */
4071         trigger_work(&our_joinpbx->j_updatebridge);
4072         trigger_work(&other_joinpbx->j_updatebridge);
4073
4074         /* we send a retrieve to that endpoint */
4075         // mixer will update the hold-state of the join and send it to the endpoints is changes
4076 #else
4077         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
4078 #endif
4079
4080         return 0;
4081 }
4082
4083 int EndpointAppPBX::join_3pty_fxs(void)
4084 {
4085 #ifdef WITH_MISDN
4086         class Join *our_join, *other_join;
4087         class JoinPBX *our_joinpbx, *other_joinpbx;
4088         class EndpointAppPBX *other_eapp;
4089         class Port *our_port, *other_port;
4090         class Pfxs *our_fxs, *other_fxs;
4091
4092         /* are we a candidate to join a join? */
4093         our_join = find_join_id(ea_endpoint->ep_join_id);
4094         if (!our_join) {
4095                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4096                 return -1;
4097         }
4098         if (our_join->j_type != JOIN_TYPE_PBX) {
4099                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
4100                 return -1;
4101         }
4102         our_joinpbx = (class JoinPBX *)our_join;
4103         if (!ea_endpoint->ep_portlist) {
4104                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
4105                 return -1;
4106         }
4107         if (!e_ext.number[0]) {
4108                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
4109                 return -1;
4110         }
4111         our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
4112         if (!our_port) {
4113                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
4114                 return -1;
4115         }
4116         if ((our_port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) {
4117                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not FXS pots.\n", ea_endpoint->ep_serial);
4118                 return -1;
4119         }
4120         our_fxs = (class Pfxs *)our_port;
4121
4122         /* find an endpoint that has the same mISDNport that we are on */
4123         other_eapp = apppbx_first;
4124         while(other_eapp) {
4125                 if (other_eapp == this) {
4126                         other_eapp = other_eapp->next;
4127                         continue;
4128                 }
4129                 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);
4130                 if (other_eapp->e_ext.number[0] /* has terminal */
4131                  && other_eapp->ea_endpoint->ep_portlist /* has port */
4132                  && other_eapp->ea_endpoint->ep_join_id) { /* has join */
4133                         other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
4134                         if (other_port) { /* port still exists */
4135                                 if (other_port->p_type==PORT_TYPE_POTS_FXS_OUT
4136                                  || other_port->p_type==PORT_TYPE_POTS_FXS_IN) { /* port is isdn nt-mode */
4137                                         other_fxs = (class Pfxs *)other_port;
4138                                         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);
4139                                         if (1 //other_fxs->p_m_hold /* port is on hold */
4140                                          && other_fxs->p_m_mISDNport == our_fxs->p_m_mISDNport) /* same pots interface */
4141                                                 break;
4142                                 } else {
4143                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
4144                                 }
4145                         } else {
4146                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
4147                         }
4148                 }
4149                 other_eapp = other_eapp->next;
4150         }
4151         if (!other_eapp) {
4152                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same FXS terminal.\n", ea_endpoint->ep_serial);
4153                 return -1;
4154         }
4155         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
4156
4157         /* if we have the same join */
4158         if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
4159                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
4160                 return -1;
4161         }
4162         other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4163         if (!other_join) {
4164                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4165                 return -1;
4166         }
4167         if (other_join->j_type != JOIN_TYPE_PBX) {
4168                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4169                 return -1;
4170         }
4171         other_joinpbx = (class JoinPBX *)other_join;
4172         if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
4173                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4174                 return -1;
4175         }
4176
4177         if (our_joinpbx->j_3pty) {
4178                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join already doing 3PTY.\n", ea_endpoint->ep_serial);
4179                 return -1;
4180         }
4181         if (other_joinpbx->j_3pty) {
4182                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join already doing 3PTY.\n", ea_endpoint->ep_serial);
4183                 return -1;
4184         }
4185
4186         /* set 3PTY bridge */
4187         other_joinpbx->j_3pty = our_joinpbx->j_serial;
4188         our_joinpbx->j_3pty = other_joinpbx->j_serial;
4189
4190         /* mixer must update */
4191         trigger_work(&our_joinpbx->j_updatebridge);
4192         trigger_work(&other_joinpbx->j_updatebridge);
4193
4194         /* we send a retrieve to that endpoint */
4195         // mixer will update the hold-state of the join and send it to the endpoints is changes
4196 #else
4197         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
4198 #endif
4199
4200         return 0;
4201 }
4202
4203 int EndpointAppPBX::split_3pty(void)
4204 {
4205 #ifdef WITH_MISDN
4206         class Join *our_join, *other_join;
4207         class JoinPBX *our_joinpbx, *other_joinpbx;
4208
4209         /* are we a candidate to join a join? */
4210         our_join = find_join_id(ea_endpoint->ep_join_id);
4211         if (!our_join) {
4212                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4213                 return -1;
4214         }
4215         if (our_join->j_type != JOIN_TYPE_PBX) {
4216                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: join is not a pbx join.\n", ea_endpoint->ep_serial);
4217                 return -1;
4218         }
4219         our_joinpbx = (class JoinPBX *)our_join;
4220
4221         if (!our_joinpbx->j_3pty) {
4222                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: we don't have a 3PTY.\n", ea_endpoint->ep_serial);
4223                 return -1;
4224         }
4225
4226         other_join = find_join_id(our_joinpbx->j_3pty);
4227         if (!other_join) {
4228                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4229                 return -1;
4230         }
4231         if (other_join->j_type != JOIN_TYPE_PBX) {
4232                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: join is not a pbx join.\n", ea_endpoint->ep_serial);
4233                 return -1;
4234         }
4235         other_joinpbx = (class JoinPBX *)other_join;
4236
4237         our_joinpbx->j_3pty = 0;
4238         other_joinpbx->j_3pty = 0;
4239
4240         /* mixer must update */
4241         trigger_work(&our_joinpbx->j_updatebridge);
4242         trigger_work(&other_joinpbx->j_updatebridge);
4243
4244         /* we send a retrieve to that endpoint */
4245         // mixer will update the hold-state of the join and send it to the endpoints is changes
4246 #else
4247         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: no mISDN support anyway.\n", ea_endpoint->ep_serial);
4248 #endif
4249
4250         return 0;
4251 }
4252
4253 /* check if we have an external call
4254  * this is used to check for encryption ability
4255  */
4256 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
4257 {
4258         struct join_relation *relation;
4259         class Join *join;
4260         class JoinPBX *joinpbx;
4261         class Endpoint *epoint;
4262
4263         /* some paranoia check */
4264         if (!ea_endpoint->ep_portlist) {
4265                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4266                 *errstr = "No Call";
4267                 return(1);
4268         }
4269         if (!e_ext.number[0]) {
4270                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4271                 *errstr = "No Call";
4272                 return(1);
4273         }
4274
4275         /* check if we have a join with 2 parties */
4276         join = find_join_id(ea_endpoint->ep_join_id);
4277         if (!join) {
4278                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4279                 *errstr = "No Call";
4280                 return(1);
4281         }
4282         if (join->j_type != JOIN_TYPE_PBX) {
4283                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4284                 *errstr = "No PBX Call";
4285                 return(1);
4286         }
4287         joinpbx = (class JoinPBX *)join;
4288         relation = joinpbx->j_relation;
4289         if (!relation) {
4290                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4291                 *errstr = "No Call";
4292                 return(1);
4293         }
4294         if (!relation->next) {
4295                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4296                 *errstr = "No Call";
4297                 return(1);
4298         }
4299         if (relation->next->next) {
4300                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4301                 *errstr = "Err: Conference";
4302                 return(1);
4303         }
4304         if (relation->epoint_id == ea_endpoint->ep_serial) {
4305                 relation = relation->next;
4306                 if (relation->epoint_id == ea_endpoint->ep_serial) {
4307                         PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4308                         *errstr = "Software Error";
4309                         return(1);
4310                 }
4311         }
4312
4313         /* check remote port for external call */
4314         epoint = find_epoint_id(relation->epoint_id);
4315         if (!epoint) {
4316                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4317                 *errstr = "No Call";
4318                 return(1);
4319         }
4320         if (!epoint->ep_portlist) {
4321                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4322                 *errstr = "No Call";
4323                 return(1);
4324         }
4325         *port = find_port_id(epoint->ep_portlist->port_id);
4326         if (!(*port)) {
4327                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4328                 *errstr = "No Call";
4329                 return(1);
4330         }
4331         if (((*port)->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) { /* port is not external isdn */
4332                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4333                 *errstr = "No Ext Call";
4334                 return(1);
4335         }
4336         if ((*port)->p_state != PORT_STATE_CONNECT) {
4337                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4338                 *errstr = "No Ext Connect";
4339                 return(1);
4340         }
4341         return(0);
4342 }
4343
4344 int EndpointAppPBX::vootp_on(int on)
4345 {
4346 #ifndef WITH_VOOTP
4347         set_tone(ea_endpoint->ep_portlist, "crypt_off");
4348 #else
4349         if (!e_ext.otp_ident[0]) {
4350                 set_tone(ea_endpoint->ep_portlist, "crypt_off");
4351                 return -EINVAL;
4352         }
4353         if(ea_endpoint->ep_portlist) {
4354                 struct lcr_msg *message;
4355
4356                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_VOOTP);
4357                 message->param.vootp.enable = on;
4358                 SCPY(message->param.vootp.id, e_ext.otp_ident);
4359                 message_put(message);
4360         }
4361         if (!on)
4362                 set_tone(ea_endpoint->ep_portlist, "crypt_off");
4363 #endif
4364
4365         return 0;
4366 }
4367
4368 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
4369 {
4370         const char *logtext = "unknown";
4371         char buffer[64];
4372
4373         switch(message_type) {
4374                 case MESSAGE_SETUP:
4375                 trace_header("SETUP", dir);
4376                 if (dir == DIRECTION_OUT)
4377                         add_trace("to", NULL, "CH(%lu)", port_id);
4378                 if (dir == DIRECTION_IN)
4379                         add_trace("from", NULL, "CH(%lu)", port_id);
4380                 if (param->setup.callerinfo.extension[0])
4381                         add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4382                 if (param->setup.callerinfo.interface[0])
4383                         add_trace("interface", "from", "%s", param->setup.callerinfo.interface);
4384                 if (param->setup.dialinginfo.interfaces[0])
4385                         add_trace("interface", "to", "%s", param->setup.dialinginfo.interfaces);
4386                 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4387                 switch(param->setup.callerinfo.present) {
4388                         case INFO_PRESENT_RESTRICTED:
4389                         add_trace("caller id", "present", "restricted");
4390                         break;
4391                         case INFO_PRESENT_ALLOWED:
4392                         add_trace("caller id", "present", "allowed");
4393                         break;
4394                         default:
4395                         add_trace("caller id", "present", "not available");
4396                 }
4397                 if (param->setup.callerinfo.ntype2) {
4398                         add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
4399                         switch(param->setup.callerinfo.present) {
4400                                 case INFO_PRESENT_RESTRICTED:
4401                                 add_trace("caller id2", "present", "restricted");
4402                                 break;
4403                                 case INFO_PRESENT_ALLOWED:
4404                                 add_trace("caller id2", "present", "allowed");
4405                                 break;
4406                                 default:
4407                                 add_trace("caller id2", "present", "not available");
4408                         }
4409                 }
4410                 if (param->setup.redirinfo.id[0]) {
4411                         add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4412                         switch(param->setup.redirinfo.present) {
4413                                 case INFO_PRESENT_RESTRICTED:
4414                                 add_trace("redir'ing", "present", "restricted");
4415                                 break;
4416                                 case INFO_PRESENT_ALLOWED:
4417                                 add_trace("redir'ing", "present", "allowed");
4418                                 break;
4419                                 default:
4420                                 add_trace("redir'ing", "present", "not available");
4421                         }
4422                 }
4423                 if (param->setup.dialinginfo.id[0])
4424                         add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4425                 if (param->setup.dialinginfo.keypad[0])
4426                         add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
4427                 if (param->setup.dialinginfo.display[0])
4428                         add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
4429                 if (param->setup.dialinginfo.sending_complete)
4430                         add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
4431                 end_trace();
4432                 break;
4433
4434                 case MESSAGE_OVERLAP:
4435                 trace_header("SETUP ACKNOWLEDGE", dir);
4436                 if (dir == DIRECTION_OUT)
4437                         add_trace("to", NULL, "CH(%lu)", port_id);
4438                 if (dir == DIRECTION_IN)
4439                         add_trace("from", NULL, "CH(%lu)", port_id);
4440                 end_trace();
4441                 break;
4442
4443                 case MESSAGE_PROCEEDING:
4444                 trace_header("PROCEEDING", dir);
4445                 if (dir == DIRECTION_OUT)
4446                         add_trace("to", NULL, "CH(%lu)", port_id);
4447                 if (dir == DIRECTION_IN)
4448                         add_trace("from", NULL, "CH(%lu)", port_id);
4449                 end_trace();
4450                 break;
4451
4452                 case MESSAGE_ALERTING:
4453                 trace_header("ALERTING", dir);
4454                 if (dir == DIRECTION_OUT)
4455                         add_trace("to", NULL, "CH(%lu)", port_id);
4456                 if (dir == DIRECTION_IN)
4457                         add_trace("from", NULL, "CH(%lu)", port_id);
4458                 end_trace();
4459                 break;
4460
4461                 case MESSAGE_CONNECT:
4462                 trace_header("CONNECT", dir);
4463                 if (dir == DIRECTION_OUT)
4464                         add_trace("to", NULL, "CH(%lu)", port_id);
4465                 if (dir == DIRECTION_IN)
4466                         add_trace("from", NULL, "CH(%lu)", port_id);
4467                 if (param->connectinfo.extension[0])
4468                         add_trace("extension", NULL, "%s", param->connectinfo.extension);
4469                 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4470                 switch(param->connectinfo.present) {
4471                         case INFO_PRESENT_RESTRICTED:
4472                         add_trace("connect id", "present", "restricted");
4473                         break;
4474                         case INFO_PRESENT_ALLOWED:
4475                         add_trace("connect id", "present", "allowed");
4476                         break;
4477                         default:
4478                         add_trace("connect id", "present", "not available");
4479                 }
4480                 if (param->connectinfo.display[0])
4481                         add_trace("display", NULL, "%s", param->connectinfo.display);
4482                 end_trace();
4483                 break;
4484
4485                 case MESSAGE_DISCONNECT:
4486                 case MESSAGE_RELEASE:
4487                 if (message_type == MESSAGE_DISCONNECT)
4488                         trace_header("DISCONNECT", dir);
4489                 else
4490                         trace_header("RELEASE", dir);
4491                 if (dir == DIRECTION_OUT)
4492                         add_trace("to", NULL, "CH(%lu)", port_id);
4493                 if (dir == DIRECTION_IN)
4494                         add_trace("from", NULL, "CH(%lu)", port_id);
4495                 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4496                 switch(param->disconnectinfo.location) {
4497                         case LOCATION_USER:
4498                         add_trace("cause", "location", "0-User");
4499                         break;
4500                         case LOCATION_PRIVATE_LOCAL:
4501                         add_trace("cause", "location", "1-Local-PBX");
4502                         break;
4503                         case LOCATION_PUBLIC_LOCAL:
4504                         add_trace("cause", "location", "2-Local-Exchange");
4505                         break;
4506                         case LOCATION_TRANSIT:
4507                         add_trace("cause", "location", "3-Transit");
4508                         break;
4509                         case LOCATION_PUBLIC_REMOTE:
4510                         add_trace("cause", "location", "4-Remote-Exchange");
4511                         break;
4512                         case LOCATION_PRIVATE_REMOTE:
4513                         add_trace("cause", "location", "5-Remote-PBX");
4514                         break;
4515                         case LOCATION_INTERNATIONAL:
4516                         add_trace("cause", "location", "7-International-Exchange");
4517                         break;
4518                         case LOCATION_BEYOND:
4519                         add_trace("cause", "location", "10-Beyond-Interworking");
4520                         break;
4521                         default:
4522                         add_trace("cause", "location", "%d", param->disconnectinfo.location);
4523                 }
4524                 if (param->disconnectinfo.display[0])
4525                         add_trace("display", NULL, "%s", param->disconnectinfo.display);
4526                 end_trace();
4527                 break;
4528
4529                 case MESSAGE_NOTIFY:
4530                 switch(param->notifyinfo.notify) {
4531                         case 0x00:
4532                         logtext = "NULL";
4533                         break;
4534                         case 0x80:
4535                         logtext = "USER_SUSPENDED";
4536                         break;
4537                         case 0x82:
4538                         logtext = "BEARER_SERVICE_CHANGED";
4539                         break;
4540                         case 0x81:
4541                         logtext = "USER_RESUMED";
4542                         break;
4543                         case 0xc2:
4544                         logtext = "CONFERENCE_ESTABLISHED";
4545                         break;
4546                         case 0xc3:
4547                         logtext = "CONFERENCE_DISCONNECTED";
4548                         break;
4549                         case 0xc4:
4550                         logtext = "OTHER_PARTY_ADDED";
4551                         break;
4552                         case 0xc5:
4553                         logtext = "ISOLATED";
4554                         break;
4555                         case 0xc6:
4556                         logtext = "REATTACHED";
4557                         break;
4558                         case 0xc7:
4559                         logtext = "OTHER_PARTY_ISOLATED";
4560                         break;
4561                         case 0xc8:
4562                         logtext = "OTHER_PARTY_REATTACHED";
4563                         break;
4564                         case 0xc9:
4565                         logtext = "OTHER_PARTY_SPLIT";
4566                         break;
4567                         case 0xca:
4568                         logtext = "OTHER_PARTY_DISCONNECTED";
4569                         break;
4570                         case 0xcb:
4571                         logtext = "CONFERENCE_FLOATING";
4572                         break;
4573                         case 0xcc:
4574                         logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4575                         break;
4576                         case 0xcf:
4577                         logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4578                         break;
4579                         case 0xe0:
4580                         logtext = "CALL_IS_A_WAITING_CALL";
4581                         break;
4582                         case 0xe8:
4583                         logtext = "DIVERSION_ACTIVATED";
4584                         break;
4585                         case 0xe9:
4586                         logtext = "RESERVED_CT_1";
4587                         break;
4588                         case 0xea:
4589                         logtext = "RESERVED_CT_2";
4590                         break;
4591                         case 0xee:
4592                         logtext = "REVERSE_CHARGING";
4593                         break;
4594                         case 0xf9:
4595                         logtext = "REMOTE_HOLD";
4596                         break;
4597                         case 0xfa:
4598                         logtext = "REMOTE_RETRIEVAL";
4599                         break;
4600                         case 0xfb:
4601                         logtext = "CALL_IS_DIVERTING";
4602                         break;
4603                         default:
4604                         SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4605                         logtext = buffer;
4606
4607                 }
4608                 trace_header("NOTIFY", dir);
4609                 if (dir == DIRECTION_OUT)
4610                         add_trace("to", NULL, "CH(%lu)", port_id);
4611                 if (dir == DIRECTION_IN)
4612                         add_trace("from", NULL, "CH(%lu)", port_id);
4613                 if (param->notifyinfo.notify)
4614                         add_trace("indicator", NULL, "%s", logtext);
4615                 if (param->notifyinfo.id[0]) {
4616                         add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4617                         switch(param->notifyinfo.present) {
4618                                 case INFO_PRESENT_RESTRICTED:
4619                                 add_trace("redir'on", "present", "restricted");
4620                                 break;
4621                                 case INFO_PRESENT_ALLOWED:
4622                                 add_trace("redir'on", "present", "allowed");
4623                                 break;
4624                                 default:
4625                                 add_trace("redir'on", "present", "not available");
4626                         }
4627                 }
4628                 if (param->notifyinfo.display[0])
4629                         add_trace("display", NULL, "%s", param->notifyinfo.display);
4630                 end_trace();
4631                 break;
4632
4633                 case MESSAGE_PROGRESS:
4634                 switch(param->progressinfo.progress) {
4635                         case 0x01:
4636                         logtext = "Call is not end to end ISDN";
4637                         break;
4638                         case 0x02:
4639                         logtext = "Destination address is non-ISDN";
4640                         break;
4641                         case 0x03:
4642                         logtext = "Origination address is non-ISDN";
4643                         break;
4644                         case 0x04:
4645                         logtext = "Call has returned to the ISDN";
4646                         break;
4647                         case 0x08:
4648                         logtext = "In-band info or pattern available";
4649                         break;
4650                         default:
4651                         SPRINT(buffer, "%d", param->progressinfo.progress);
4652                         logtext = buffer;
4653
4654                 }
4655                 trace_header("PROGRESS", dir);
4656                 if (dir == DIRECTION_OUT)
4657                         add_trace("to", NULL, "CH(%lu)", port_id);
4658                 if (dir == DIRECTION_IN)
4659                         add_trace("from", NULL, "CH(%lu)", port_id);
4660                 add_trace("indicator", NULL, "%s", logtext);
4661                 switch(param->progressinfo.location) {
4662                         case LOCATION_USER:
4663                         add_trace("cause", "location", "0-User");
4664                         break;
4665                         case LOCATION_PRIVATE_LOCAL:
4666                         add_trace("cause", "location", "1-Local-PBX");
4667                         break;
4668                         case LOCATION_PUBLIC_LOCAL:
4669                         add_trace("cause", "location", "2-Local-Exchange");
4670                         break;
4671                         case LOCATION_TRANSIT:
4672                         add_trace("cause", "location", "3-Transit");
4673                         break;
4674                         case LOCATION_PUBLIC_REMOTE:
4675                         add_trace("cause", "location", "4-Remote-Exchange");
4676                         break;
4677                         case LOCATION_PRIVATE_REMOTE:
4678                         add_trace("cause", "location", "5-Remote-PBX");
4679                         break;
4680                         case LOCATION_INTERNATIONAL:
4681                         add_trace("cause", "location", "7-International-Exchange");
4682                         break;
4683                         case LOCATION_BEYOND:
4684                         add_trace("cause", "location", "10-Beyond-Interworking");
4685                         break;
4686                         default:
4687                         add_trace("cause", "location", "%d", param->progressinfo.location);
4688                 }
4689                 end_trace();
4690                 break;
4691
4692                 case MESSAGE_INFORMATION:
4693                 trace_header("INFORMATION", dir);
4694                 if (dir == DIRECTION_OUT)
4695                         add_trace("to", NULL, "CH(%lu)", port_id);
4696                 if (dir == DIRECTION_IN)
4697                         add_trace("from", NULL, "CH(%lu)", port_id);
4698                 if (param->information.id[0])
4699                         add_trace("dialing", NULL, "%s", param->information.id);
4700                 if (param->information.display[0])
4701                         add_trace("display", NULL, "%s", param->information.display);
4702                 if (param->information.sending_complete)
4703                         add_trace("complete", NULL, "true", param->information.sending_complete);
4704                 end_trace();
4705                 break;
4706
4707                 case MESSAGE_FACILITY:
4708                 trace_header("FACILITY", dir);
4709                 if (dir == DIRECTION_OUT)
4710                         add_trace("to", NULL, "CH(%lu)", port_id);
4711                 if (dir == DIRECTION_IN)
4712                         add_trace("from", NULL, "CH(%lu)", port_id);
4713                 end_trace();
4714                 break;
4715
4716                 case MESSAGE_TONE:
4717                 trace_header("TONE", dir);
4718                 if (dir == DIRECTION_OUT)
4719                         add_trace("to", NULL, "CH(%lu)", port_id);
4720                 if (dir == DIRECTION_IN)
4721                         add_trace("from", NULL, "CH(%lu)", port_id);
4722                 if (param->tone.name[0]) {
4723                         add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4724                         add_trace("name", NULL, "%s", param->tone.name);
4725                 } else
4726                         add_trace("off", NULL, NULL);
4727                 end_trace();
4728                 break;
4729
4730                 case MESSAGE_SUSPEND:
4731                 case MESSAGE_RESUME:
4732                 if (message_type == MESSAGE_SUSPEND)
4733                         trace_header("SUSPEND", dir);
4734                 else
4735                         trace_header("RESUME", dir);
4736                 if (dir == DIRECTION_OUT)
4737                         add_trace("to", NULL, "CH(%lu)", port_id);
4738                 if (dir == DIRECTION_IN)
4739                         add_trace("from", NULL, "CH(%lu)", port_id);
4740                 if (param->parkinfo.len)
4741                         add_trace("length", NULL, "%d", param->parkinfo.len);
4742                 end_trace();
4743                 break;
4744
4745 #if 0
4746                 case MESSAGE_BCHANNEL:
4747                 trace_header("BCHANNEL", dir);
4748                 switch(param->bchannel.type) {
4749                         case BCHANNEL_REQUEST:
4750                         add_trace("type", NULL, "request");
4751                         break;
4752                         case BCHANNEL_ASSIGN:
4753                         add_trace("type", NULL, "assign");
4754                         break;
4755                         case BCHANNEL_ASSIGN_ACK:
4756                         add_trace("type", NULL, "assign_ack");
4757                         break;
4758                         case BCHANNEL_REMOVE:
4759                         add_trace("type", NULL, "remove");
4760                         break;
4761                         case BCHANNEL_REMOVE_ACK:
4762                         add_trace("type", NULL, "remove_ack");
4763                         break;
4764                 }
4765                 if (param->bchannel.addr)
4766                         add_trace("address", NULL, "%x", param->bchannel.addr);
4767                 end_trace();
4768                 break;
4769 #endif
4770
4771                 case MESSAGE_3PTY:
4772                 if (param->threepty.begin)
4773                         trace_header("Begin3PTY", dir);
4774                 if (param->threepty.end)
4775                         trace_header("End3PTY", dir);
4776                 if (param->threepty.invoke)
4777                         add_trace("action", NULL, "invoke");
4778                 if (param->threepty.result)
4779                         add_trace("action", NULL, "result");
4780                 if (param->threepty.error)
4781                         add_trace("action", NULL, "error");
4782                 add_trace("invoke-id", NULL, "%d", param->threepty.invoke_id);
4783                 end_trace();
4784                 break;
4785
4786                 case MESSAGE_TRANSFER:
4787                 trace_header("TRANSFER", dir);
4788                 end_trace();
4789                 break;
4790
4791                 case MESSAGE_DISABLE_DEJITTER:
4792                 trace_header("DISBALE_DEJITTER", dir);
4793                 if (param->queue)
4794                         add_trace("queue", NULL, "%d", param->queue);
4795                 end_trace();
4796                 break;
4797
4798                 default:
4799                 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4800         }
4801 }
4802
4803 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4804 {
4805         struct lcr_msg *message;
4806
4807         if (!portlist)
4808                 return;
4809         if (!portlist->port_id)
4810                 return;
4811
4812         if (!e_connectedmode) {
4813                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4814                 message->param.disconnectinfo.cause = cause;
4815                 message->param.disconnectinfo.location = location;
4816                 if (display[0])
4817                         SCPY(message->param.disconnectinfo.display, display);
4818                 else
4819                         SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4820         } else {
4821                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4822                 if (display[0])
4823                         SCPY(message->param.notifyinfo.display, display);
4824                 else
4825                         SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4826         }
4827         message_put(message);
4828         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
4829 }
4830