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