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