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