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