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