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