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