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