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