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