fixes, debugging for usleep problems.
[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                 /* port assigns bchannel */
2905                 case MESSAGE_BCHANNEL: /* indicates the assigned bchannel  */
2906                 case MESSAGE_BCHANNEL_FREE: /* requests bchannel back (e.g. when call is holded) */
2907                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
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
2913
2914                 default:
2915                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received a wrong message: %d\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, message);
2916         }
2917
2918         /* Note: this endpoint may be destroyed, so we MUST return */
2919 }
2920
2921
2922 /* messages from join
2923  */
2924 /* join MESSAGE_CRYPT */
2925 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2926 {
2927         switch(param->crypt.type)
2928         {
2929                 /* message from remote port to "crypt manager" */
2930                 case CU_ACTK_REQ:           /* activate key-exchange */
2931                 case CU_ACTS_REQ:            /* activate shared key */
2932                 case CU_DACT_REQ:          /* deactivate */
2933                 case CU_INFO_REQ:         /* request last info message */
2934                 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2935                 break;
2936
2937                 /* message from "crypt manager" to user */
2938                 case CU_ACTK_CONF:          /* key-echange done */
2939                 case CU_ACTS_CONF:          /* shared key done */
2940                 case CU_DACT_CONF:           /* deactivated */
2941                 case CU_DACT_IND:           /* deactivated */
2942                 case CU_ERROR_IND:         /* receive error message */
2943                 case CU_INFO_IND:         /* receive info message */
2944                 case CU_INFO_CONF:         /* receive info message */
2945                 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2946                 break;
2947
2948                 default:
2949                 PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
2950         }
2951 }
2952
2953 /* join MESSAGE_INFORMATION */
2954 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2955 {
2956         struct message *message;
2957
2958         e_overlap = 1;
2959
2960         while(portlist)
2961         {
2962                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2963                 memcpy(&message->param.information, &param->information, sizeof(struct dialing_info));
2964                 message_put(message);
2965                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2966                 portlist = portlist->next;
2967         }
2968 }
2969
2970 /* join MESSAGE_FACILITY */
2971 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2972 {
2973         struct message *message;
2974
2975         if (!e_ext.facility)
2976         {
2977                 return;
2978         }
2979
2980         while(portlist)
2981         {
2982                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2983                 memcpy(&message->param.facilityinfo, &param->facilityinfo, sizeof(struct facility_info));
2984                 message_put(message);
2985                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2986                 portlist = portlist->next;
2987         }
2988 }
2989
2990 /* join MESSAGE_MORE */
2991 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2992 {
2993         struct message *message;
2994
2995         new_state(EPOINT_STATE_IN_OVERLAP);
2996         
2997         /* own dialtone */
2998         if (e_join_pattern && e_ext.own_setup)
2999         {
3000                 /* disconnect audio */
3001                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3002                 message->param.audiopath = CHANNEL_STATE_HOLD;
3003                 message_put(message);
3004         }
3005         if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3006         {
3007                         set_tone(portlist, "dialtone");
3008                         return;
3009         }
3010         if (e_ext.number[0])
3011                 set_tone(portlist, "dialpbx");
3012         else
3013                 set_tone(portlist, "dialtone");
3014 }
3015
3016 /* join MESSAGE_PROCEEDING */
3017 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
3018 {
3019         struct message *message;
3020
3021         new_state(EPOINT_STATE_IN_PROCEEDING);
3022
3023         /* own proceeding tone */
3024         if (e_join_pattern)
3025         {
3026                 /* connect / disconnect audio */
3027                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3028                 if (e_ext.own_proceeding)
3029                         message->param.audiopath = CHANNEL_STATE_HOLD;
3030                 else
3031                         message->param.audiopath = CHANNEL_STATE_CONNECT;
3032                 message_put(message);
3033         }
3034 //                      UCPY(e_join_tone, "proceeding");
3035         if (portlist)
3036         {
3037                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3038                 message_put(message);
3039                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3040         }
3041         set_tone(portlist, "proceeding");
3042 }
3043
3044 /* join MESSAGE_ALERTING */
3045 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
3046 {
3047         struct message *message;
3048
3049         new_state(EPOINT_STATE_IN_ALERTING);
3050
3051         /* own alerting tone */
3052         if (e_join_pattern)
3053         {
3054                 /* connect / disconnect audio */
3055                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3056                 if (e_ext.own_alerting)
3057                         message->param.audiopath = CHANNEL_STATE_HOLD;
3058                 else
3059                         message->param.audiopath = CHANNEL_STATE_CONNECT;
3060                 message_put(message);
3061         }
3062         if (portlist)
3063         {
3064                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
3065                 message_put(message);
3066                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3067         }
3068         if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL)
3069         {
3070                 set_tone(portlist, "ringing");
3071                 return;
3072         }
3073         if (e_ext.number[0])
3074                 set_tone(portlist, "ringpbx");
3075         else
3076                 set_tone(portlist, "ringing");
3077 }
3078
3079 /* join MESSAGE_CONNECT */
3080 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
3081 {
3082         struct message *message;
3083         struct interface        *interface;
3084
3085         new_state(EPOINT_STATE_CONNECT);
3086 //                      UCPY(e_join_tone, "");
3087         if (e_ext.number[0])
3088                 e_dtmf = 1; /* allow dtmf */
3089         e_powerdialing = 0;
3090         memcpy(&e_connectinfo, &param->connectinfo, sizeof(e_callerinfo));
3091         if(portlist)
3092         {
3093                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3094                 memcpy(&message->param, param, sizeof(union parameter));
3095                 /* screen incoming caller id */
3096                 interface = interface_first;
3097                 while(interface)
3098                 {
3099                         if (!strcmp(e_connectinfo.interface, interface->name))
3100                         {
3101                                 break;
3102                         }
3103                         interface = interface->next;
3104                 }
3105                 if (interface)
3106                         screen(1, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
3107                 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(e_connectinfo));
3108
3109                 /* screen clip if prefix is required */
3110                 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0])
3111                 {
3112                         SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
3113                         SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype));
3114                         message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3115                 }
3116
3117                 /* use internal caller id */
3118                 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore))
3119                 {
3120                         SCPY(message->param.connectinfo.id, e_connectinfo.extension);
3121                         message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
3122                 }
3123
3124                 /* handle restricted caller ids */
3125                 apply_callerid_restriction(e_ext.anon_ignore, message->param.connectinfo.id, &message->param.connectinfo.ntype, &message->param.connectinfo.present, &message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name);
3126                 /* display callerid if desired for extension */
3127                 SCPY(message->param.connectinfo.display, apply_callerid_display(message->param.connectinfo.id, message->param.connectinfo.itype, message->param.connectinfo.ntype, message->param.connectinfo.present, message->param.connectinfo.screen, message->param.connectinfo.extension, message->param.connectinfo.name));
3128
3129                 /* use conp, if enabld */
3130                 if (!e_ext.centrex)
3131                         message->param.connectinfo.name[0] = '\0';
3132
3133                 /* send connect */
3134                 message_put(message);
3135                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3136         }
3137         set_tone(portlist, NULL);
3138         e_join_pattern = 0;
3139         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3140         message->param.audiopath = CHANNEL_STATE_CONNECT;
3141         message_put(message);
3142         e_start = now;
3143 }
3144
3145 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
3146 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
3147 {
3148         char cause[16];
3149         struct message *message;
3150         struct port_list *portlist = NULL;
3151
3152
3153         /* be sure that we are active */
3154         notify_active();
3155         e_tx_state = NOTIFY_STATE_ACTIVE;
3156
3157         /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
3158         if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1))
3159         {
3160                 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3161
3162                 /* set time for power dialing */
3163                 e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
3164                 e_powercount++;
3165
3166                 /* set redial tone */
3167                 if (ea_endpoint->ep_portlist)
3168                 {
3169                         e_join_pattern = 0;
3170                 }
3171                 set_tone(ea_endpoint->ep_portlist, "redial");
3172                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') redialing in %d seconds\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, (int)e_powerdelay);
3173                 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
3174                 if (e_state==EPOINT_STATE_IN_OVERLAP)
3175                 {
3176                         new_state(EPOINT_STATE_IN_PROCEEDING);
3177                         if (ea_endpoint->ep_portlist)
3178                         {
3179                                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
3180                                 message_put(message);
3181                                 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3182                         }
3183 /* caused the error, that the first knock sound was not there */
3184 /*                                      set_tone(portlist, "proceeding"); */
3185                 }
3186                 /* send display of powerdialing */
3187                 if (e_ext.display_dialing)
3188                 {
3189                         portlist = ea_endpoint->ep_portlist;
3190                         while (portlist)
3191                         {
3192                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3193                                 if (e_powerlimit)
3194                                         SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
3195                                 else
3196                                         SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
3197                                 message_put(message);
3198                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3199                                 portlist = portlist->next;
3200                         }
3201                 }
3202                 return;
3203         }
3204
3205         /* set stop time */
3206         e_stop = now;
3207
3208         if ((e_state!=EPOINT_STATE_CONNECT
3209           && e_state!=EPOINT_STATE_OUT_DISCONNECT
3210           && e_state!=EPOINT_STATE_IN_OVERLAP
3211           && e_state!=EPOINT_STATE_IN_PROCEEDING
3212           && e_state!=EPOINT_STATE_IN_ALERTING)
3213          || !ea_endpoint->ep_portlist) /* or no port */
3214         {
3215                 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
3216                 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
3217                 return; /* must exit here */
3218         }
3219         /* save cause */
3220         if (!e_join_cause)
3221         {
3222                 e_join_cause = param->disconnectinfo.cause;
3223                 e_join_location = param->disconnectinfo.location;
3224         }
3225
3226         /* on release we need the audio again! */
3227         if (message_type == MESSAGE_RELEASE)
3228         {
3229                 e_join_pattern = 0;
3230                 ea_endpoint->ep_join_id = 0;
3231         }
3232         /* disconnect and select tone */
3233         new_state(EPOINT_STATE_OUT_DISCONNECT);
3234         SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
3235         /* if own_cause, we must release the join */
3236         if (e_ext.own_cause /* own cause */
3237          || !e_join_pattern) /* no patterns */
3238         {
3239                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have own cause or we have no patterns. (own_cause=%d pattern=%d)\n", ea_endpoint->ep_serial, e_ext.own_cause, e_join_pattern);
3240                 if (message_type != MESSAGE_RELEASE)
3241                         release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
3242                 e_join_pattern = 0;
3243         } else /* else we enable audio */
3244         {
3245                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3246                 message->param.audiopath = CHANNEL_STATE_CONNECT;
3247                 message_put(message);
3248         }
3249         /* send disconnect message */
3250         SCPY(e_tone, cause);
3251         portlist = ea_endpoint->ep_portlist;
3252         while(portlist)
3253         {
3254                 set_tone(portlist, cause);
3255                 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3256                 portlist = portlist->next;
3257         }
3258 }
3259
3260 /* join MESSAGE_SETUP */
3261 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3262 {
3263         struct message *message;
3264         struct interface        *interface;
3265
3266         /* if we already in setup state, we just update the dialing with new digits */
3267         if (e_state == EPOINT_STATE_OUT_SETUP
3268          || e_state == EPOINT_STATE_OUT_OVERLAP)
3269         {
3270                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3271                 /* if digits changed, what we have already dialed */
3272                 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id)))
3273                 {
3274                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have dialed digits which have been changed or we have a new multidial, so we must redial.\n", ea_endpoint->ep_serial);
3275                         /* release all ports */
3276                         while((portlist = ea_endpoint->ep_portlist))
3277                         {
3278                                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3279                                 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3280                                 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3281                                 message_put(message);
3282                                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3283                                 ea_endpoint->free_portlist(portlist);
3284                         }
3285
3286                         /* disconnect audio */
3287                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3288                         message->param.audiopath = CHANNEL_STATE_HOLD;
3289                         message_put(message);
3290
3291                         /* get dialing info */
3292                         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
3293                         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3294                         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
3295                         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
3296                         new_state(EPOINT_STATE_OUT_OVERLAP);
3297
3298                         /* get time */
3299                         e_redial = now_d + 1; /* set redial one second in the future */
3300                         return;
3301                 }
3302                 /* if we have a pending redial, so we just adjust the dialing number */
3303                 if (e_redial)
3304                 {
3305                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) redial in progress, so we update the dialing number to %s.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3306                         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3307                         return;
3308                 }
3309                 if (!ea_endpoint->ep_portlist)
3310                 {
3311                         PERROR("ERROR: overlap dialing to a NULL port relation\n");
3312                 }
3313                 if (ea_endpoint->ep_portlist->next)
3314                 {
3315                         PERROR("ERROR: overlap dialing to a port_list port relation\n");
3316                 }
3317                 if (e_state == EPOINT_STATE_OUT_SETUP)
3318                 {
3319                         /* queue digits */
3320                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) digits '%s' are queued because we didn't receive a setup acknowledge.\n", ea_endpoint->ep_serial, param->setup.dialinginfo.id);
3321                         SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3322                         
3323                 } else
3324                 {
3325                         /* get what we have not dialed yet */
3326                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have already dialed '%s', we received '%s', what's left '%s'.\n", ea_endpoint->ep_serial, e_dialinginfo.id, param->setup.dialinginfo.id, param->setup.dialinginfo.id+strlen(e_dialinginfo.id));
3327                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3328                         SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3329                         message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3330                         message_put(message);
3331                         logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3332                 }
3333                 /* always store what we have dialed or queued */
3334                 memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3335                 
3336                 return;
3337         }
3338         if (e_state != EPOINT_STATE_IDLE)
3339         {
3340                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3341                 return;
3342         }
3343         /* if an internal extension is dialed, copy that number */
3344         if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3345                 SCPY(e_ext.number, param->setup.dialinginfo.id);
3346         /* if an internal extension is dialed, get extension's info about caller */
3347         if (e_ext.number[0]) 
3348         {
3349                 if (!read_extension(&e_ext, e_ext.number))
3350                 {
3351                         e_ext.number[0] = '\0';
3352                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3353                 }
3354         }
3355
3356         memcpy(&e_callerinfo, &param->setup.callerinfo, sizeof(e_callerinfo));
3357         memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
3358         memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
3359         memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
3360
3361         /* screen incoming caller id */
3362         interface = interface_first;
3363         while(interface)
3364         {
3365                 if (!strcmp(e_callerinfo.interface, interface->name))
3366                 {
3367                         break;
3368                 }
3369                 interface = interface->next;
3370         }
3371         if (interface)
3372                 screen(1, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
3373
3374         /* process (voice over) data calls */
3375         if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO)
3376         {
3377                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3378                 memset(&e_capainfo, 0, sizeof(e_capainfo));
3379                 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3380                 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3381                 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3382         }
3383
3384         new_state(EPOINT_STATE_OUT_SETUP);
3385         /* call special setup routine */
3386         out_setup();
3387 }
3388
3389 /* join MESSAGE_mISDNSIGNAL */
3390 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3391 {
3392         struct message *message;
3393
3394         while(portlist)
3395         {
3396                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3397                 memcpy(&message->param, param, sizeof(union parameter));
3398                 message_put(message);
3399                 portlist = portlist->next;
3400         }
3401 }
3402
3403 /* join MESSAGE_NOTIFY */
3404 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3405 {
3406         struct message *message;
3407         int new_state;
3408
3409         if (param->notifyinfo.notify)
3410         {
3411                 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3412 //              /* if notification was generated locally, we turn hold music on/off */ 
3413 //              if (param->notifyinfo.local)
3414 // NOTE: we always assume that we send hold music on suspension of call, because we don't track if audio is available or not (we assume that we always have no audio, to make it easier)
3415                 {
3416                         if (e_hold)
3417                         {
3418                                 /* unhold if */
3419                                 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND)
3420                                 {
3421                                         while(portlist)
3422                                         {
3423                                                 set_tone(portlist, "");
3424                                                 portlist = portlist->next;
3425                                         }
3426                                         portlist = ea_endpoint->ep_portlist;
3427                                         e_hold = 0;
3428                                 }
3429                         } else {
3430                                 /* hold if */
3431                                 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND)
3432                                 {
3433                                         while(portlist)
3434                                         {
3435                                                 set_tone(portlist, "hold");
3436                                                 portlist = portlist->next;
3437                                         }
3438                                         portlist = ea_endpoint->ep_portlist;
3439                                         e_hold = 1;
3440                                 }
3441                         }
3442                 }
3443                 /* save new state */
3444                 e_tx_state = new_state;
3445         }
3446
3447         /* notify port(s) about it */
3448         while(portlist)
3449         {
3450                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3451                 memcpy(&message->param.notifyinfo, &param->notifyinfo, sizeof(struct notify_info));
3452                 /* handle restricted caller ids */
3453                 apply_callerid_restriction(e_ext.anon_ignore, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3454                 /* display callerid if desired for extension */
3455                 SCPY(message->param.notifyinfo.display, apply_callerid_display(message->param.notifyinfo.id, message->param.notifyinfo.itype, message->param.notifyinfo.ntype, message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL));
3456                 message_put(message);
3457                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3458                 portlist = portlist->next;
3459         }
3460 }
3461
3462 /* call sends messages to the endpoint
3463  */
3464 void EndpointAppPBX::ea_message_join(unsigned long join_id, int message_type, union parameter *param)
3465 {
3466         struct port_list *portlist;
3467         struct message *message;
3468
3469         if (!join_id)
3470         {
3471                 PERROR("EPOINT(%d) error: call == NULL.\n", ea_endpoint->ep_serial);
3472                 return;
3473         }
3474
3475         portlist = ea_endpoint->ep_portlist;
3476
3477         /* send MESSAGE_DATA to port */
3478         if (message_type == MESSAGE_DATA)
3479         {
3480                 if (join_id == ea_endpoint->ep_join_id) // still linked with call
3481                 {
3482                         /* skip if no port relation */
3483                         if (!portlist)
3484                                 return;
3485                         /* skip if more than one port relation */
3486                         if (portlist->next)
3487                                 return;
3488                         /* forward audio data to port */
3489                         message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3490                         return;
3491                 }
3492         }
3493
3494 //      PDEBUG(DEBUG_EPOINT, "EPOINT(%d) received message %d for active call (terminal %s, caller id %s state=%d)\n", ea_endpoint->ep_serial, message, e_ext.number, e_callerinfo.id, e_state);
3495         switch(message_type)
3496         {
3497                 /* CALL SENDS CRYPT message */
3498                 case MESSAGE_CRYPT:
3499                 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);
3500                 join_crypt(portlist, message_type, param);
3501                 break;
3502
3503                 /* CALL sends INFORMATION message */
3504                 case MESSAGE_INFORMATION:
3505                 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);
3506                 join_information(portlist, message_type, param);
3507                 break;
3508
3509                 /* CALL sends FACILITY message */
3510                 case MESSAGE_FACILITY:
3511                 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);
3512                 join_facility(portlist, message_type, param);
3513                 break;
3514
3515                 /* CALL sends OVERLAP message */
3516                 case MESSAGE_OVERLAP:
3517                 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);
3518                 if (e_state!=EPOINT_STATE_IN_SETUP
3519                  && e_state!=EPOINT_STATE_IN_OVERLAP)
3520                 {
3521                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3522                         break;
3523                 }
3524                 join_overlap(portlist, message_type, param);
3525                 break;
3526
3527                 /* CALL sends PROCEEDING message */
3528                 case MESSAGE_PROCEEDING:
3529                 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);
3530                 if(e_state!=EPOINT_STATE_IN_OVERLAP)
3531                 {
3532                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3533                         break;
3534                 }
3535                 join_proceeding(portlist, message_type, param);
3536                 break;
3537
3538                 /* CALL sends ALERTING message */
3539                 case MESSAGE_ALERTING:
3540                 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);
3541                 if (e_state!=EPOINT_STATE_IN_OVERLAP
3542                  && e_state!=EPOINT_STATE_IN_PROCEEDING)
3543                 {
3544                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3545                         break;
3546                 }
3547                 join_alerting(portlist, message_type, param);
3548                 break;
3549
3550                 /* CALL sends CONNECT message */
3551                 case MESSAGE_CONNECT:
3552                 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);
3553                 if (e_state!=EPOINT_STATE_IN_OVERLAP
3554                  && e_state!=EPOINT_STATE_IN_PROCEEDING
3555                  && e_state!=EPOINT_STATE_IN_ALERTING)
3556                 {
3557                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3558                         break;
3559                 }
3560                 join_connect(portlist, message_type, param);
3561                 break;
3562
3563                 /* CALL sends DISCONNECT/RELEASE message */
3564                 case MESSAGE_DISCONNECT: /* call disconnect */
3565                 case MESSAGE_RELEASE: /* call releases */
3566                 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);
3567                 join_disconnect_release(message_type, param);
3568                 break;
3569
3570                 /* CALL sends SETUP message */
3571                 case MESSAGE_SETUP:
3572                 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);
3573                 join_setup(portlist, message_type, param);
3574                 break;
3575
3576                 /* CALL sends special mISDNSIGNAL message */
3577                 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3578                 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);
3579                 join_mISDNsignal(portlist, message_type, param);
3580                 break;
3581
3582                 /* call requests bchannel */
3583                 case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
3584                 case MESSAGE_BCHANNEL_FREE: /* indicates that the bchannel is free */
3585                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel request.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3586                 /* only one port is expected to be connected to bchannel */
3587                 if (!portlist)
3588                         break;
3589                 if (portlist->next)
3590                         break;
3591                 e_join_pattern = 1;
3592                 SCPY(e_tone, "");
3593                 set_tone(portlist, NULL);
3594                 message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
3595                 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3596                 break;
3597
3598                 /* CALL has pattern available */
3599                 case MESSAGE_PATTERN: /* indicating pattern available */
3600                 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);
3601                 if (!e_join_pattern)
3602                 {
3603                         PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3604                         e_join_pattern = 1;
3605                         SCPY(e_tone, "");
3606                         while(portlist)
3607                         {
3608                                 set_tone(portlist, NULL);
3609                                 portlist = portlist->next;
3610                         }
3611                         /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3612                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3613                         message->param.audiopath = CHANNEL_STATE_CONNECT;
3614                         message_put(message);
3615 //                      /* tell remote epoint to connect audio also, because we like to hear the patterns */
3616 //                      message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_REMOTE_AUDIO);
3617 //                      message->param.audiopath = CHANNEL_STATE_CONNECT;
3618 //                      message_put(message);
3619 // patterns are available, remote already connected audio
3620                 }
3621                 break;
3622
3623                 /* CALL has no pattern available */
3624                 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3625                 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);
3626                 if (e_join_pattern)
3627                 {
3628                         PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3629                         e_join_pattern = 0;
3630                         /* disconnect our audio tx and rx */
3631                         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3632                         message->param.audiopath = CHANNEL_STATE_HOLD;
3633                         message_put(message);
3634                 }
3635                 break;
3636
3637 #if 0
3638                 /* CALL (dunno at the moment) */
3639                 case MESSAGE_REMOTE_AUDIO:
3640                 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);
3641                 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3642                 message->param.audiopath = param->channel;
3643                 message_put(message);
3644                 break;
3645 #endif
3646
3647                 /* CALL sends a notify message */
3648                 case MESSAGE_NOTIFY:
3649                 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);
3650                 join_notify(portlist, message_type, param);
3651                 break;
3652
3653                 default:
3654                 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);
3655         }
3656 }
3657
3658
3659 /* pick_join will connect the first incoming call found. the endpoint
3660  * will receivce a MESSAGE_CONNECT.
3661  */
3662 int match_list(char *list, char *item)
3663 {
3664         char *end, *next = NULL;
3665
3666         /* no list make matching */
3667         if (!list)
3668                 return(1);
3669
3670         while(42)
3671         {
3672                 /* eliminate white spaces */
3673                 while (*list <= ' ')
3674                         list++;
3675                 if (*list == ',')
3676                 {
3677                         list++;
3678                         continue;
3679                 }
3680                 /* if end of list is reached, we return */
3681                 if (list[0] == '\0')
3682                         return(0);
3683                 /* if we have more than one entry (left) */
3684                 if ((end = strchr(list, ',')))
3685                         next = end + 1;
3686                 else
3687                         next = end = strchr(list, '\0');
3688                 while (*(end-1) <= ' ')
3689                         end--;
3690                 /* if string part matches item */
3691                 if (!strncmp(list, item, end-list))
3692                         return(1);
3693                 list = next;
3694         }
3695 }
3696
3697 void EndpointAppPBX::pick_join(char *extensions)
3698 {
3699         struct message *message;
3700         struct port_list *portlist;
3701         class Port *port;
3702         class EndpointAppPBX *eapp, *found;
3703         class Join *join;
3704         class JoinPBX *joinpbx;
3705         struct join_relation *relation;
3706         int vbox;
3707
3708         /* find an endpoint that is ringing internally or vbox with higher priority */
3709         vbox = 0;
3710         found = NULL;
3711         eapp = apppbx_first;
3712         while(eapp)
3713         {
3714                 if (eapp!=this && ea_endpoint->ep_portlist)
3715                 {
3716                         portlist = eapp->ea_endpoint->ep_portlist;
3717                         while(portlist)
3718                         {
3719                                 if ((port = find_port_id(portlist->port_id)))
3720                                 {
3721                                         if (port->p_type == PORT_TYPE_VBOX_OUT)
3722                                         {
3723                                                 if (match_list(extensions, eapp->e_ext.number))
3724                                                 {
3725                                                         found = eapp;
3726                                                         vbox = 1;
3727                                                         break;
3728                                                 }
3729                                         }
3730                                         if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT)
3731                                          && port->p_state==PORT_STATE_OUT_ALERTING)
3732                                                 if (match_list(extensions, eapp->e_ext.number))
3733                                                 {
3734                                                         found = eapp;
3735                                                 }
3736                                 }
3737                                 portlist = portlist->next;
3738                         }
3739                         if (portlist)
3740                                 break;
3741                 }
3742                 eapp = eapp->next;
3743         }
3744
3745         /* if no endpoint found */
3746         if (!found)
3747         {
3748                 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);
3749 reject:
3750                 set_tone(ea_endpoint->ep_portlist, "cause_10");
3751                 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3752                 new_state(EPOINT_STATE_OUT_DISCONNECT);
3753                 return;
3754         }
3755         eapp = found;
3756
3757         if (ea_endpoint->ep_join_id)
3758         {
3759                 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3760                 goto reject;
3761         }
3762         if (!eapp->ea_endpoint->ep_join_id)
3763         {
3764                 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3765                 goto reject;
3766         }
3767         join = find_join_id(eapp->ea_endpoint->ep_join_id);
3768         if (!join)
3769         {
3770                 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3771                 goto reject;
3772         }
3773         if (join->j_type != JOIN_TYPE_PBX)
3774         {
3775                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3776                 goto reject;
3777         }
3778         joinpbx = (class JoinPBX *)join;
3779         relation = joinpbx->j_relation;
3780         if (!relation)
3781         {
3782                 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3783                 goto reject;
3784         }
3785         while (relation->epoint_id != eapp->ea_endpoint->ep_serial)
3786         {
3787                 relation = relation->next;
3788                 if (!relation)
3789                 {
3790                         PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3791                         goto reject;
3792                 }
3793         }
3794
3795         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3796
3797         if (options.deb & DEBUG_EPOINT)
3798         {
3799                 class Join *debug_c = join_first;
3800                 class Endpoint *debug_e = epoint_first;
3801                 class Port *debug_p = port_first;
3802
3803                 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3804
3805                 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3806                 while(debug_c)
3807                 {
3808                         PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3809                         debug_c = debug_c->next;
3810                 }
3811                 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3812                 while(debug_e)
3813                 {
3814                         PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3815                         debug_e = debug_e->next;
3816                 }
3817                 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3818                 while(debug_p)
3819                 {
3820                         PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3821                         debug_p = debug_p->next;
3822                 }
3823         }
3824
3825         /* relink join */
3826         ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3827         relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3828         eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3829
3830         /* connnecting our endpoint */
3831         new_state(EPOINT_STATE_CONNECT);
3832         e_dtmf = 1;
3833         set_tone(ea_endpoint->ep_portlist, NULL);
3834
3835         /* now we send a release to the ringing endpoint */
3836         message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3837         message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3838         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3839         message_put(message);
3840
3841         /* we send a connect to the join with our caller id */
3842         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3843         SCPY(message->param.connectinfo.id, e_callerinfo.id);
3844         message->param.connectinfo.present = e_callerinfo.present;
3845         message->param.connectinfo.screen = e_callerinfo.screen;
3846         message->param.connectinfo.itype = e_callerinfo.itype;
3847         message->param.connectinfo.ntype = e_callerinfo.ntype;
3848         message_put(message);
3849
3850         /* we send a connect to our port with the remote callerid */
3851         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3852         SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3853         message->param.connectinfo.present = eapp->e_callerinfo.present;
3854         message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3855         message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3856         message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3857         /* handle restricted caller ids */
3858         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);
3859         /* display callerid if desired for extension */
3860         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));
3861         message_put(message);
3862
3863         /* we send a connect to the audio path (not for vbox) */
3864         message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3865         message->param.audiopath = CHANNEL_STATE_CONNECT;
3866         message_put(message);
3867
3868         /* beeing paranoid, we make call update */
3869         joinpbx->j_updatebridge = 1;
3870
3871         if (options.deb & DEBUG_EPOINT)
3872         {
3873                 class Join *debug_c = join_first;
3874                 class Endpoint *debug_e = epoint_first;
3875                 class Port *debug_p = port_first;
3876
3877                 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3878
3879                 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3880                 while(debug_c)
3881                 {
3882                         PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3883                         debug_c = debug_c->next;
3884                 }
3885                 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3886                 while(debug_e)
3887                 {
3888                         PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3889                         debug_e = debug_e->next;
3890                 }
3891                 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3892                 while(debug_p)
3893                 {
3894                         PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3895                         debug_p = debug_p->next;
3896                 }
3897         }
3898 }
3899
3900
3901 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3902  */
3903 void EndpointAppPBX::join_join(void)
3904 {
3905         struct message *message;
3906         struct join_relation *our_relation, *other_relation;
3907         struct join_relation **our_relation_pointer, **other_relation_pointer;
3908         class Join *our_join, *other_join;
3909         class JoinPBX *our_joinpbx, *other_joinpbx;
3910         class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3911         class Port *our_port, *other_port;
3912         class Pdss1 *our_pdss1, *other_pdss1;
3913
3914         /* are we a candidate to join a join */
3915         our_join = find_join_id(ea_endpoint->ep_join_id);
3916         if (!our_join)
3917         {
3918                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3919                 return;
3920         }
3921         if (our_join->j_type != JOIN_TYPE_PBX)
3922         {
3923                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3924                 return;
3925         }
3926         our_joinpbx = (class JoinPBX *)our_join;
3927         if (!ea_endpoint->ep_portlist)
3928         {
3929                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3930                 return;
3931         }
3932         if (!e_ext.number[0])
3933         {
3934                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3935                 return;
3936         }
3937         our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3938         if (!our_port)
3939         {
3940                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3941                 return;
3942         }
3943         if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1)
3944         {
3945                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3946                 return;
3947         }
3948         our_pdss1 = (class Pdss1 *)our_port;
3949
3950         /* find an endpoint that is on hold and has the same mISDNport that we are on */
3951         other_eapp = apppbx_first;
3952         while(other_eapp)
3953         {
3954                 if (other_eapp == this)
3955                 {
3956                         other_eapp = other_eapp->next;
3957                         continue;
3958                 }
3959                 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);
3960                 if (other_eapp->e_ext.number[0] /* has terminal */
3961                  && other_eapp->ea_endpoint->ep_portlist /* has port */
3962                  && other_eapp->ea_endpoint->ep_join_id) /* has join */
3963                 {
3964                         other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3965                         if (other_port) /* port still exists */
3966                         {
3967                                 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3968                                  || other_port->p_type==PORT_TYPE_DSS1_NT_IN) /* port is isdn nt-mode */
3969                                 {
3970                                         other_pdss1 = (class Pdss1 *)other_port;
3971                                         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);
3972                                         if (other_pdss1->p_m_hold /* port is on hold */
3973                                          && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3974                                          && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3975                                                 break;
3976                                 } else
3977                                 {
3978                                         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3979                                 }
3980                         } else
3981                         {
3982                                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3983                         }
3984                 }
3985                 other_eapp = other_eapp->next;
3986         }
3987         if (!other_eapp)
3988         {
3989                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
3990                 return;
3991         }
3992         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
3993
3994         /* if we have the same join */
3995         if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id)
3996         {
3997                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
3998                 return;
3999         }
4000         other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
4001         if (!other_join)
4002         {
4003                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
4004                 return;
4005         }
4006         if (other_join->j_type != JOIN_TYPE_PBX)
4007         {
4008                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
4009                 return;
4010         }
4011         other_joinpbx = (class JoinPBX *)other_join;
4012         if (our_joinpbx->j_partyline && other_joinpbx->j_partyline)
4013         {
4014                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
4015                 return;
4016         }
4017
4018         /* remove relation to endpoint for join on hold */
4019         other_relation = other_joinpbx->j_relation;
4020         other_relation_pointer = &other_joinpbx->j_relation;
4021         while(other_relation)
4022         {
4023                 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial)
4024                 {
4025                 /* detach other endpoint on hold */
4026                         *other_relation_pointer = other_relation->next;
4027                         FREE(other_relation, sizeof(struct join_relation));
4028                         cmemuse--;
4029                         other_relation = *other_relation_pointer;
4030                         other_eapp->ea_endpoint->ep_join_id = NULL;
4031                         continue;
4032                 }
4033
4034                 /* change join/hold pointer of endpoint to the new join */
4035                 temp_epoint = find_epoint_id(other_relation->epoint_id);
4036                 if (temp_epoint)
4037                 {
4038                         if (temp_epoint->ep_join_id == other_join->j_serial)
4039                                 temp_epoint->ep_join_id = our_join->j_serial;
4040                 }
4041
4042                 other_relation_pointer = &other_relation->next;
4043                 other_relation = other_relation->next;
4044         }
4045         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
4046
4047         /* join call relations */
4048         our_relation = our_joinpbx->j_relation;
4049         our_relation_pointer = &our_joinpbx->j_relation;
4050         while(our_relation)
4051         {
4052                 our_relation_pointer = &our_relation->next;
4053                 our_relation = our_relation->next;
4054         }
4055         *our_relation_pointer = other_joinpbx->j_relation;
4056         other_joinpbx->j_relation = NULL;
4057         PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
4058
4059         /* release endpoint on hold */
4060         message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
4061         message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
4062         message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
4063         message_put(message);
4064         
4065         /* if we are not a partyline, we get partyline state from other join */
4066         our_joinpbx->j_partyline += other_joinpbx->j_partyline; 
4067
4068         /* remove empty join */
4069         delete other_join;
4070         PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
4071
4072         /* mixer must update */
4073         our_joinpbx->j_updatebridge = 1; /* update mixer flag */
4074
4075         /* we send a retrieve to that endpoint */
4076         // mixer will update the hold-state of the join and send it to the endpoints is changes
4077 }
4078
4079
4080 /* check if we have an external call
4081  * this is used to check for encryption ability
4082  */
4083 int EndpointAppPBX::check_external(char **errstr, class Port **port)
4084 {
4085         struct join_relation *relation;
4086         class Join *join;
4087         class JoinPBX *joinpbx;
4088         class Endpoint *epoint;
4089
4090         /* some paranoia check */
4091         if (!ea_endpoint->ep_portlist)
4092         {
4093                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
4094                 *errstr = "No Call";
4095                 return(1);
4096         }
4097         if (!e_ext.number[0])
4098         {
4099                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
4100                 *errstr = "No Call";
4101                 return(1);
4102         }
4103
4104         /* check if we have a join with 2 parties */
4105         join = find_join_id(ea_endpoint->ep_join_id);
4106         if (!join)
4107         {
4108                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
4109                 *errstr = "No Call";
4110                 return(1);
4111         }
4112         if (join->j_type != JOIN_TYPE_PBX)
4113         {
4114                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
4115                 *errstr = "No PBX Call";
4116                 return(1);
4117         }
4118         joinpbx = (class JoinPBX *)join;
4119         relation = joinpbx->j_relation;
4120         if (!relation)
4121         {
4122                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4123                 *errstr = "No Call";
4124                 return(1);
4125         }
4126         if (!relation->next)
4127         {
4128                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4129                 *errstr = "No Call";
4130                 return(1);
4131         }
4132         if (relation->next->next)
4133         {
4134                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4135                 *errstr = "Err: Conference";
4136                 return(1);
4137         }
4138         if (relation->epoint_id == ea_endpoint->ep_serial)
4139         {
4140                 relation = relation->next;
4141                 if (relation->epoint_id == ea_endpoint->ep_serial)
4142                 {
4143                         PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4144                         *errstr = "Software Error";
4145                         return(1);
4146                 }
4147         }
4148
4149         /* check remote port for external call */
4150         epoint = find_epoint_id(relation->epoint_id);
4151         if (!epoint)
4152         {
4153                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4154                 *errstr = "No Call";
4155                 return(1);
4156         }
4157         if (!epoint->ep_portlist)
4158         {
4159                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4160                 *errstr = "No Call";
4161                 return(1);
4162         }
4163         *port = find_port_id(epoint->ep_portlist->port_id);
4164         if (!(*port))
4165         {
4166                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4167                 *errstr = "No Call";
4168                 return(1);
4169         }
4170         if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) /* port is not external isdn */
4171         {
4172                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4173                 *errstr = "No Ext Call";
4174                 return(1);
4175         }
4176         if ((*port)->p_state != PORT_STATE_CONNECT)
4177         {
4178                 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4179                 *errstr = "No Ext Connect";
4180                 return(1);
4181         }
4182         return(0);
4183 }
4184
4185 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned long port_id, int dir)
4186 {
4187         char *logtext = "unknown";
4188         char buffer[64];
4189
4190         switch(message_type)
4191         {
4192                 case MESSAGE_SETUP:
4193                 trace_header("SETUP", dir);
4194                 if (dir == DIRECTION_OUT)
4195                         add_trace("to", NULL, "CH(%lu)", port_id);
4196                 if (dir == DIRECTION_IN)
4197                         add_trace("from", NULL, "CH(%lu)", port_id);
4198                 if (param->setup.callerinfo.extension[0])
4199                         add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4200                 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype));
4201                 switch(param->setup.callerinfo.present)
4202                 {
4203                         case INFO_PRESENT_RESTRICTED:
4204                         add_trace("caller id", "present", "restricted");
4205                         break;
4206                         case INFO_PRESENT_ALLOWED:
4207                         add_trace("caller id", "present", "allowed");
4208                         break;
4209                         default:
4210                         add_trace("caller id", "present", "not available");
4211                 }
4212                 if (param->setup.redirinfo.id[0])
4213                 {
4214                         add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype));
4215                         switch(param->setup.redirinfo.present)
4216                         {
4217                                 case INFO_PRESENT_RESTRICTED:
4218                                 add_trace("redir'ing", "present", "restricted");
4219                                 break;
4220                                 case INFO_PRESENT_ALLOWED:
4221                                 add_trace("redir'ing", "present", "allowed");
4222                                 break;
4223                                 default:
4224                                 add_trace("redir'ing", "present", "not available");
4225                         }
4226                 }
4227                 if (param->setup.dialinginfo.id[0])
4228                         add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4229                 end_trace();
4230                 break;
4231
4232                 case MESSAGE_OVERLAP:
4233                 trace_header("SETUP ACKNOWLEDGE", dir);
4234                 if (dir == DIRECTION_OUT)
4235                         add_trace("to", NULL, "CH(%lu)", port_id);
4236                 if (dir == DIRECTION_IN)
4237                         add_trace("from", NULL, "CH(%lu)", port_id);
4238                 end_trace();
4239                 break;
4240
4241                 case MESSAGE_PROCEEDING:
4242                 trace_header("PROCEEDING", dir);
4243                 if (dir == DIRECTION_OUT)
4244                         add_trace("to", NULL, "CH(%lu)", port_id);
4245                 if (dir == DIRECTION_IN)
4246                         add_trace("from", NULL, "CH(%lu)", port_id);
4247                 end_trace();
4248                 break;
4249
4250                 case MESSAGE_ALERTING:
4251                 trace_header("ALERTING", dir);
4252                 if (dir == DIRECTION_OUT)
4253                         add_trace("to", NULL, "CH(%lu)", port_id);
4254                 if (dir == DIRECTION_IN)
4255                         add_trace("from", NULL, "CH(%lu)", port_id);
4256                 end_trace();
4257                 break;
4258
4259                 case MESSAGE_CONNECT:
4260                 trace_header("CONNECT", dir);
4261                 if (dir == DIRECTION_OUT)
4262                         add_trace("to", NULL, "CH(%lu)", port_id);
4263                 if (dir == DIRECTION_IN)
4264                         add_trace("from", NULL, "CH(%lu)", port_id);
4265                 if (param->connectinfo.extension[0])
4266                         add_trace("extension", NULL, "%s", param->connectinfo.extension);
4267                 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype));
4268                 switch(param->connectinfo.present)
4269                 {
4270                         case INFO_PRESENT_RESTRICTED:
4271                         add_trace("connect id", "present", "restricted");
4272                         break;
4273                         case INFO_PRESENT_ALLOWED:
4274                         add_trace("connect id", "present", "allowed");
4275                         break;
4276                         default:
4277                         add_trace("connect id", "present", "not available");
4278                 }
4279                 end_trace();
4280                 break;
4281
4282                 case MESSAGE_DISCONNECT:
4283                 case MESSAGE_RELEASE:
4284                 if (message_type == MESSAGE_DISCONNECT)
4285                         trace_header("DISCONNECT", dir);
4286                 else
4287                         trace_header("RELEASE", dir);
4288                 if (dir == DIRECTION_OUT)
4289                         add_trace("to", NULL, "CH(%lu)", port_id);
4290                 if (dir == DIRECTION_IN)
4291                         add_trace("from", NULL, "CH(%lu)", port_id);
4292                 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4293                 switch(param->disconnectinfo.location)
4294                 {
4295                         case LOCATION_USER:
4296                         add_trace("cause", "location", "0-User");
4297                         break;
4298                         case LOCATION_PRIVATE_LOCAL:
4299                         add_trace("cause", "location", "1-Local-PBX");
4300                         break;
4301                         case LOCATION_PUBLIC_LOCAL:
4302                         add_trace("cause", "location", "2-Local-Exchange");
4303                         break;
4304                         case LOCATION_TRANSIT:
4305                         add_trace("cause", "location", "3-Transit");
4306                         break;
4307                         case LOCATION_PUBLIC_REMOTE:
4308                         add_trace("cause", "location", "4-Remote-PBX");
4309                         break;
4310                         case LOCATION_PRIVATE_REMOTE:
4311                         add_trace("cause", "location", "5-Remote-Exchange");
4312                         break;
4313                         case LOCATION_INTERNATIONAL:
4314                         add_trace("cause", "location", "7-International-Exchange");
4315                         break;
4316                         case LOCATION_BEYOND:
4317                         add_trace("cause", "location", "10-Beyond-Interworking");
4318                         break;
4319                         default:
4320                         add_trace("cause", "location", "%d", param->disconnectinfo.location);
4321                 }
4322                 end_trace();
4323                 break;
4324
4325                 case MESSAGE_NOTIFY:
4326                 switch(param->notifyinfo.notify)
4327                 {
4328                         case 0x00:
4329                         logtext = "NULL";
4330                         break;
4331                         case 0x80:
4332                         logtext = "USER_SUSPENDED";
4333                         break;
4334                         case 0x82:
4335                         logtext = "BEARER_SERVICE_CHANGED";
4336                         break;
4337                         case 0x81:
4338                         logtext = "USER_RESUMED";
4339                         break;
4340                         case 0xc2:
4341                         logtext = "CONFERENCE_ESTABLISHED";
4342                         break;
4343                         case 0xc3:
4344                         logtext = "CONFERENCE_DISCONNECTED";
4345                         break;
4346                         case 0xc4:
4347                         logtext = "OTHER_PARTY_ADDED";
4348                         break;
4349                         case 0xc5:
4350                         logtext = "ISOLATED";
4351                         break;
4352                         case 0xc6:
4353                         logtext = "REATTACHED";
4354                         break;
4355                         case 0xc7:
4356                         logtext = "OTHER_PARTY_ISOLATED";
4357                         break;
4358                         case 0xc8:
4359                         logtext = "OTHER_PARTY_REATTACHED";
4360                         break;
4361                         case 0xc9:
4362                         logtext = "OTHER_PARTY_SPLIT";
4363                         break;
4364                         case 0xca:
4365                         logtext = "OTHER_PARTY_DISCONNECTED";
4366                         break;
4367                         case 0xcb:
4368                         logtext = "CONFERENCE_FLOATING";
4369                         break;
4370                         case 0xcc:
4371                         logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4372                         break;
4373                         case 0xcf:
4374                         logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4375                         break;
4376                         case 0xe0:
4377                         logtext = "CALL_IS_A_WAITING_CALL";
4378                         break;
4379                         case 0xe8:
4380                         logtext = "DIVERSION_ACTIVATED";
4381                         break;
4382                         case 0xe9:
4383                         logtext = "RESERVED_CT_1";
4384                         break;
4385                         case 0xea:
4386                         logtext = "RESERVED_CT_2";
4387                         break;
4388                         case 0xee:
4389                         logtext = "REVERSE_CHARGING";
4390                         break;
4391                         case 0xf9:
4392                         logtext = "REMOTE_HOLD";
4393                         break;
4394                         case 0xfa:
4395                         logtext = "REMOTE_RETRIEVAL";
4396                         break;
4397                         case 0xfb:
4398                         logtext = "CALL_IS_DIVERTING";
4399                         break;
4400                         default:
4401                         SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4402                         logtext = buffer;
4403
4404                 }
4405                 trace_header("NOTIFY", dir);
4406                 if (dir == DIRECTION_OUT)
4407                         add_trace("to", NULL, "CH(%lu)", port_id);
4408                 if (dir == DIRECTION_IN)
4409                         add_trace("from", NULL, "CH(%lu)", port_id);
4410                 if (param->notifyinfo.notify)
4411                         add_trace("indicator", NULL, "%s", logtext);
4412                 if (param->notifyinfo.id[0])
4413                 {
4414                         add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype));
4415                         switch(param->notifyinfo.present)
4416                         {
4417                                 case INFO_PRESENT_RESTRICTED:
4418                                 add_trace("redir'on", "present", "restricted");
4419                                 break;
4420                                 case INFO_PRESENT_ALLOWED:
4421                                 add_trace("redir'on", "present", "allowed");
4422                                 break;
4423                                 default:
4424                                 add_trace("redir'on", "present", "not available");
4425                         }
4426                 }
4427                 if (param->notifyinfo.display[0])
4428                         add_trace("display", NULL, "%s", param->notifyinfo.display);
4429                 end_trace();
4430                 break;
4431
4432                 case MESSAGE_INFORMATION:
4433                 trace_header("INFORMATION", dir);
4434                 if (dir == DIRECTION_OUT)
4435                         add_trace("to", NULL, "CH(%lu)", port_id);
4436                 if (dir == DIRECTION_IN)
4437                         add_trace("from", NULL, "CH(%lu)", port_id);
4438                 add_trace("dialing", NULL, "%s", param->information.id);
4439                 end_trace();
4440                 break;
4441
4442                 case MESSAGE_FACILITY:
4443                 trace_header("FACILITY", dir);
4444                 if (dir == DIRECTION_OUT)
4445                         add_trace("to", NULL, "CH(%lu)", port_id);
4446                 if (dir == DIRECTION_IN)
4447                         add_trace("from", NULL, "CH(%lu)", port_id);
4448                 end_trace();
4449                 break;
4450
4451                 case MESSAGE_TONE:
4452                 trace_header("TONE", dir);
4453                 if (dir == DIRECTION_OUT)
4454                         add_trace("to", NULL, "CH(%lu)", port_id);
4455                 if (dir == DIRECTION_IN)
4456                         add_trace("from", NULL, "CH(%lu)", port_id);
4457                 if (param->tone.name[0])
4458                 {
4459                         add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4460                         add_trace("name", NULL, "%s", param->tone.name);
4461                 } else
4462                         add_trace("off", NULL, NULL);
4463                 end_trace();
4464                 break;
4465
4466                 case MESSAGE_SUSPEND:
4467                 case MESSAGE_RESUME:
4468                 if (message_type == MESSAGE_SUSPEND)
4469                         trace_header("SUSPEND", dir);
4470                 else
4471                         trace_header("RESUME", dir);
4472                 if (dir == DIRECTION_OUT)
4473                         add_trace("to", NULL, "CH(%lu)", port_id);
4474                 if (dir == DIRECTION_IN)
4475                         add_trace("from", NULL, "CH(%lu)", port_id);
4476                 if (param->parkinfo.len)
4477                         add_trace("length", NULL, "%d", param->parkinfo.len);
4478                 end_trace();
4479                 break;
4480
4481                 case MESSAGE_BCHANNEL:
4482                 case MESSAGE_BCHANNEL_FREE:
4483                 trace_header("BCHANNEL", dir);
4484                 if (param->bchannel.addr)
4485                         add_trace("address", NULL, "%x", param->bchannel.addr);
4486                 end_trace();
4487                 break;
4488
4489                 default:
4490                 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4491         }
4492 }
4493
4494 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, char *display)
4495 {
4496         struct message *message;
4497
4498         if (!portlist)
4499                 return;
4500         if (!portlist->port_id)
4501                 return;
4502
4503         if (!e_connectedmode)
4504         {
4505                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4506                 message->param.disconnectinfo.cause = cause;
4507                 message->param.disconnectinfo.location = location;
4508                 if (display[0])
4509                         SCPY(message->param.disconnectinfo.display, display);
4510                 else
4511                         SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4512         } else
4513         {
4514                 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4515                 if (display[0])
4516                         SCPY(message->param.notifyinfo.display, display);
4517                 else
4518                         SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4519         }
4520         message_put(message);
4521         logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
4522 }
4523
4524