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