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