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