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