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