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