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