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