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