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