1 /*****************************************************************************\
3 ** Linux Call Router **
5 **---------------------------------------------------------------------------**
6 ** Copyright: Andreas Eversberg **
8 ** The EndpointAppPBX implements PBX4Linux **
10 \*****************************************************************************/
15 class EndpointAppPBX *apppbx_first = NULL;
17 int action_timeout(struct lcr_timer *timer, void *instance, int index);
18 int match_timeout(struct lcr_timer *timer, void *instance, int index);
19 int redial_timeout(struct lcr_timer *timer, void *instance, int index);
20 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index);
21 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index);
22 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index);
23 int password_timeout(struct lcr_timer *timer, void *instance, int index);
24 int callback_timeout(struct lcr_timer *timer, void *instance, int index);
27 * EndpointAppPBX constructor
29 EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin, EAPP_TYPE_PBX)
31 class EndpointAppPBX **apppointer;
34 memset(&e_crypt_handler, 0, sizeof(e_crypt_handler));
35 add_timer(&e_crypt_handler, crypt_handler, this, 0);
37 memset(&e_vbox_refresh, 0, sizeof(e_vbox_refresh));
38 add_timer(&e_vbox_refresh, vbox_refresh, this, 0);
39 memset(&e_action_timeout, 0, sizeof(e_action_timeout));
40 add_timer(&e_action_timeout, action_timeout, this, 0);
41 memset(&e_match_timeout, 0, sizeof(e_match_timeout));
42 add_timer(&e_match_timeout, match_timeout, this, 0);
43 memset(&e_redial_timeout, 0, sizeof(e_redial_timeout));
44 add_timer(&e_redial_timeout, redial_timeout, this, 0);
45 memset(&e_powerdial_timeout, 0, sizeof(e_powerdial_timeout));
46 add_timer(&e_powerdial_timeout, powerdial_timeout, this, 0);
47 memset(&e_cfnr_timeout, 0, sizeof(e_cfnr_timeout));
48 add_timer(&e_cfnr_timeout, cfnr_timeout, this, 0);
49 memset(&e_cfnr_call_timeout, 0, sizeof(e_cfnr_call_timeout));
50 add_timer(&e_cfnr_call_timeout, cfnr_call_timeout, this, 0);
51 memset(&e_callback_timeout, 0, sizeof(e_callback_timeout));
52 add_timer(&e_callback_timeout, callback_timeout, this, 0);
53 memset(&e_password_timeout, 0, sizeof(e_password_timeout));
54 add_timer(&e_password_timeout, password_timeout, this, 0);
57 /* add application to chain */
59 apppointer = &apppbx_first;
61 apppointer = &((*apppointer)->next);
65 memset(&e_ext, 0, sizeof(struct extension));
66 // *************** NOTE: also change value in read_extension() **************
67 e_ext.rights = 4; /* international */
68 e_ext.rx_gain = e_ext.tx_gain = 0;
69 e_state = EPOINT_STATE_IDLE;
70 e_ext.number[0] = '\0';
71 e_extension_interface[0] = '\0';
72 memset(&e_callerinfo, 0, sizeof(struct caller_info));
73 memset(&e_dialinginfo, 0, sizeof(struct dialing_info));
74 memset(&e_connectinfo, 0, sizeof(struct connect_info));
75 memset(&e_redirinfo, 0, sizeof(struct redir_info));
76 memset(&e_capainfo, 0, sizeof(struct capa_info));
77 memset(&e_rtpinfo, 0, sizeof(struct rtp_info));
80 e_ruleset = ruleset_main;
82 e_rule = e_ruleset->rule_first;
85 e_match_to_action = NULL;
87 e_extdialing = e_dialinginfo.id;
91 // e_join_tone[0] = e_hold_tone[0] = '\0';
92 e_join_pattern /*= e_hold_pattern*/ = 0;
94 e_adminid = 0; // will be set, if call was initiated via admin socket
97 e_cbdialing[0] = '\0';
100 memset(&e_callbackinfo, 0, sizeof(struct caller_info));
106 e_multipoint_cause = 0;
107 e_multipoint_location = 0;
108 e_dialing_queue[0] = '\0';
111 e_crypt_state = CM_ST_NULL;
112 e_crypt_keyengine_busy = 0;
113 e_crypt_info[0] = '\0';
117 e_tx_state = NOTIFY_STATE_ACTIVE;
118 e_rx_state = NOTIFY_STATE_ACTIVE;
119 e_join_cause = e_join_location = 0;
120 /*********************************
121 *********************************
122 ********* ATTENTION *************
123 *********************************
124 *********************************/
125 /* if you add new values, that must be initialized, also check if they must
126 * be initialized when doing callback
132 * EpointAppPBX destructor
134 EndpointAppPBX::~EndpointAppPBX(void)
136 class EndpointAppPBX *temp, **tempp;
139 del_timer(&e_crypt_handler);
141 del_timer(&e_vbox_refresh);
142 del_timer(&e_action_timeout);
143 del_timer(&e_match_timeout);
144 del_timer(&e_redial_timeout);
145 del_timer(&e_powerdial_timeout);
146 del_timer(&e_cfnr_timeout);
147 del_timer(&e_cfnr_call_timeout);
148 del_timer(&e_callback_timeout);
149 del_timer(&e_password_timeout);
153 tempp = &apppbx_first;
162 FATAL("Endpoint not in endpoint's list.\n");
169 * trace header for application
171 void EndpointAppPBX::trace_header(const char *name, int direction)
175 char msgtext[sizeof(_trace.name)];
179 /* init trace with given values */
182 numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
186 ea_endpoint->ep_serial,
193 /* set new endpoint state
195 void EndpointAppPBX::new_state(int state)
198 if (e_state != state) {
199 trace_header("NEW STATE", DIRECTION_NONE);
200 add_trace("state", "old", "%s", state_name[e_state]);
201 add_trace("state", "new", "%s", state_name[state]);
209 /* release join and port (as specified)
211 void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force)
213 struct port_list *portlist;
214 struct lcr_msg *message;
217 /* message to test call */
218 admin_call_response(e_adminid, ADMIN_CALL_RELEASE, "", joincause, joinlocation, 0);
220 /* if a release is pending */
221 if (release==RELEASE_JOIN || release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
222 PDEBUG(DEBUG_EPOINT, "EPOINT(%d): do pending release (joincause %d location %d)\n", ea_endpoint->ep_serial, joincause, joinlocation);
223 if (ea_endpoint->ep_join_id) {
224 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_RELEASE);
225 message->param.disconnectinfo.cause = joincause;
226 message->param.disconnectinfo.location = joinlocation;
227 message_put(message);
228 ea_endpoint->ep_join_id = 0;
232 if (release != RELEASE_PORT_JOINONLY) {
234 join_release(e_hold_id, ea_endpoint->ep_serial, 1, joinlocation, joincause);
239 if (release==RELEASE_ALL || release==RELEASE_PORT_JOINONLY) {
240 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release (portcause %d portlocation)\n", ea_endpoint->ep_serial, portcause, portlocation);
241 while((portlist = ea_endpoint->ep_portlist)) {
242 if (portlist->port_id) {
243 SPRINT(cause, "cause_%02x", portcause);
244 set_tone(portlist, cause);
245 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
246 message->param.disconnectinfo.cause = portcause;
247 message->param.disconnectinfo.location = portlocation;
248 message->param.disconnectinfo.force = force; // set, if port should release imediately
249 message_put(message);
250 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
252 ea_endpoint->free_portlist(portlist);
255 /* if callback is enabled, call back with the given caller id */
256 if (e_callback_timeout.active) {
257 /* reset some stuff */
258 new_state(EPOINT_STATE_IDLE);
259 memset(&e_connectinfo, 0, sizeof(struct connect_info));
260 memset(&e_redirinfo, 0, sizeof(struct redir_info));
261 e_start = e_stop = 0;
262 e_ruleset = ruleset_main;
264 e_rule = e_ruleset->rule_first;
266 unsched_timer(&e_action_timeout);
267 unsched_timer(&e_match_timeout);
268 unsched_timer(&e_cfnr_timeout);
269 unsched_timer(&e_cfnr_call_timeout);
270 e_match_to_action = NULL;
272 e_extdialing = e_dialinginfo.id;
278 e_multipoint_cause = 0;
279 e_multipoint_location = 0;
280 e_dialing_queue[0] = '\0';
283 e_crypt_state = CM_ST_NULL;
284 e_crypt_keyengine_busy = 0;
285 e_crypt_info[0] = '\0';
290 e_tx_state = NOTIFY_STATE_ACTIVE;
291 e_rx_state = NOTIFY_STATE_ACTIVE;
292 e_join_cause = e_join_location = 0;
294 /* the caller info of the callback user */
295 memcpy(&e_callbackinfo, &e_callerinfo, sizeof(e_callbackinfo));
296 memset(&e_dialinginfo, 0, sizeof(e_dialinginfo));
297 /* create dialing by callerinfo */
298 if (e_ext.number[0] && e_extension_interface[0]) {
299 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to internal: %s interface %s\n", ea_endpoint->ep_serial, e_ext.number, e_extension_interface);
300 /* create callback to the current terminal */
301 SCPY(e_dialinginfo.id, e_ext.number);
302 SCPY(e_dialinginfo.interfaces, e_extension_interface);
303 e_dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
304 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
307 SCPY(e_dialinginfo.id, e_cbto);
309 /* numberrize caller id and use it to dial to the callback */
310 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
312 e_dialinginfo.itype = INFO_ITYPE_ISDN;
313 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
314 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) preparing callback to external: %s\n", ea_endpoint->ep_serial, e_dialinginfo.id);
319 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
320 if (--ea_endpoint->ep_use <= 0) /* when e_lock is 0, the endpoint will be deleted */
321 trigger_work(&ea_endpoint->ep_delete);
327 /* cancel callerid if restricted, unless anon-ignore is enabled at extension or port is of type external (so called police gets caller id :)*/
328 void apply_callerid_restriction(struct extension *ext, char *id, int *ntype, int *present, int *screen, char *extension, char *name)
330 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");
332 /* caller id is not restricted, so we do nothing */
333 if (*present != INFO_PRESENT_RESTRICTED)
336 /* only extensions are restricted */
340 /* if we enabled anonymouse ignore */
341 if (ext->anon_ignore)
344 /* else we remove the caller id */
348 *ntype = INFO_NTYPE_UNKNOWN;
350 // *screen = INFO_SCREEN_USER;
351 // maybe we should not make voip address anonymous
354 // maybe it's no fraud to present extension id
356 // extension[0] = '\0';
361 /* used display message to display callerid as available */
362 char *EndpointAppPBX::apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name)
364 static char display[81];
367 const char *cid = numberrize_callerinfo(id, ntype, options.national, options.international);
369 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");
378 /* NOTE: is caller is is not available for this extesion, it has been removed by apply_callerid_restriction already */
380 /* internal extension's caller id */
381 if (extension[0] && e_ext.display_int) {
383 SCAT(display, extension);
386 if (itype == INFO_ITYPE_VBOX)
387 SCAT(display, "(vbox)");
389 SCAT(display, "(int)");
392 /* external caller id */
393 if (!extension[0] && e_ext.display_ext) {
396 if (present == INFO_PRESENT_RESTRICTED)
397 SCAT(display, "anonymous");
399 SCAT(display, "unknown");
406 /* display if callerid is anonymouse but available due anon-ignore */
407 if (e_ext.display_anon && present==INFO_PRESENT_RESTRICTED) {
409 SCAT(display, "unknown");
412 SCAT(display, " anon");
415 /* display if callerid is anonymouse but available due anon-ignore */
416 if (e_ext.display_fake && screen==INFO_SCREEN_USER && ntype!=INFO_NTYPE_NOTPRESENT) {
419 if (present == INFO_PRESENT_RESTRICTED)
420 SCAT(display, "anonymous");
422 SCAT(display, "unknown");
427 SCAT(display, " fake");
431 if (name[0] && e_ext.display_name) {
432 if (!display[0] && cid[0])
443 * uses the current state to notify activity
445 void EndpointAppPBX::notify_active(void)
447 struct port_list *portlist = ea_endpoint->ep_portlist;
448 struct lcr_msg *message;
452 case NOTIFY_STATE_ACTIVE:
453 /* we are already active, so we don't do anything */
456 case NOTIFY_STATE_SUSPEND:
457 notify = INFO_NOTIFY_USER_RESUMED;
459 set_tone(portlist, NULL);
460 portlist = portlist->next;
462 portlist = ea_endpoint->ep_portlist;
465 case NOTIFY_STATE_HOLD:
466 notify = INFO_NOTIFY_REMOTE_RETRIEVAL;
468 set_tone(portlist, NULL);
469 portlist = portlist->next;
471 portlist = ea_endpoint->ep_portlist;
474 case NOTIFY_STATE_CONFERENCE:
475 notify = INFO_NOTIFY_CONFERENCE_DISCONNECTED;
477 set_tone(portlist, NULL);
478 portlist = portlist->next;
480 portlist = ea_endpoint->ep_portlist;
484 PERROR("unknown e_tx_state = %d\n", e_tx_state);
489 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
490 message->param.notifyinfo.notify = notify;
491 message_put(message);
492 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
493 portlist = portlist->next;
499 * keypad functions during call. one example to use this is to put a call on hold or start a conference
501 void EndpointAppPBX::keypad_function(char digit)
504 /* we must be in a call, in order to send messages to the call */
505 if (e_ext.number[0] == '\0') {
506 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) IGNORING keypad received not from extension.\n", ea_endpoint->ep_serial);
511 /* join conference */
513 if (ea_endpoint->ep_join_id == 0) {
514 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad received during connect but not during a call.\n", ea_endpoint->ep_serial);
517 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join call with call on hold\n", ea_endpoint->ep_serial);
524 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
528 /* crypt key-exchange */
530 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) key exchange encryption selected.\n", ea_endpoint->ep_serial);
536 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
542 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
547 /* set tone pattern for port */
548 void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
550 struct lcr_msg *message;
555 /* store for suspended processes */
559 if (e_join_pattern /* pattern are provided */
560 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_SETUP)
561 && !(e_ext.own_setup && e_state == EPOINT_STATE_IN_OVERLAP)
562 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_IN_PROCEEDING)
563 && !(e_ext.own_alerting && e_state == EPOINT_STATE_IN_ALERTING)
564 && !(e_ext.own_cause && e_state == EPOINT_STATE_IN_DISCONNECT)
565 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_SETUP)
566 && !(e_ext.own_setup && e_state == EPOINT_STATE_OUT_OVERLAP)
567 && !(e_ext.own_proceeding && e_state == EPOINT_STATE_OUT_PROCEEDING)
568 && !(e_ext.own_alerting && e_state == EPOINT_STATE_OUT_ALERTING)
569 && !(e_ext.own_cause && e_state == EPOINT_STATE_OUT_DISCONNECT)
570 && tone[0] && !!strncmp(tone,"crypt_*",6)) {
571 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) tone not provided since patterns are available\n", ea_endpoint->ep_serial);
576 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_TONE);
577 SCPY(message->param.tone.dir, e_ext.tones_dir);
578 SCPY(message->param.tone.name, tone);
579 message_put(message);
580 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
582 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port to notify tone.\n", ea_endpoint->ep_serial);
588 /* outgoing setup to port(s)
589 * ports will be created and a setup is sent if everything is ok. otherwhise
590 * the endpoint is destroyed.
592 void EndpointAppPBX::out_setup(int cfnr)
594 struct dialing_info dialinginfo;
596 struct port_list *portlist;
597 struct lcr_msg *message;
599 int cause = CAUSE_RESSOURCEUNAVAIL;
602 struct interface *interface;
604 struct mISDNport *mISDNport;
608 class EndpointAppPBX *atemp;
609 // char allowed_ports[256];
611 char ifname[sizeof(e_ext.interfaces)],
613 struct port_settings port_settings;
616 struct admin_list *admin;
619 int mode = B_MODE_TRANSPARENT;
621 /* set bchannel mode */
622 mode = e_capainfo.source_mode;
624 /* create settings for creating port */
625 memset(&port_settings, 0, sizeof(port_settings));
627 SCPY(port_settings.tones_dir, e_ext.tones_dir);
629 SCPY(port_settings.tones_dir, options.tones_dir);
630 port_settings.no_seconds = e_ext.no_seconds;
632 /* 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 */
634 /* check what dialinginfo.itype we got */
635 switch(e_dialinginfo.itype) {
636 /* *********************** call to extension or vbox */
637 case INFO_ITYPE_ISDN_EXTENSION:
638 /* check if we deny incoming calls when we use an extension */
639 if (e_ext.noknocking) {
640 atemp = apppbx_first;
643 if (!strcmp(atemp->e_ext.number, e_ext.number))
648 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
649 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
650 return; /* must exit here */
653 /* FALL THROUGH !!!! */
654 case INFO_ITYPE_VBOX:
655 /* get dialed extension's info */
656 // SCPY(exten, e_dialinginfo.id);
657 // if (strchr(exten, ','))
658 // *strchr(exten, ',') = '\0';
659 // if (!read_extension(&e_ext, exten))
660 if (!read_extension(&e_ext, e_dialinginfo.id)) {
661 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
662 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
663 return; /* must exit here */
665 e_dialinginfo.sending_complete = 1;
667 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
668 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
673 /* string from unconditional call forward (cfu) */
676 /* present to forwarded party */
677 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
678 e_callerinfo.present = INFO_PRESENT_ALLOWED;
680 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
684 /* string from busy call forward (cfb) */
687 class EndpointAppPBX *checkapp = apppbx_first;
689 if (checkapp != this) { /* any other endpoint except our own */
690 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
691 /* present to forwarded party */
692 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
693 e_callerinfo.present = INFO_PRESENT_ALLOWED;
695 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
699 checkapp = checkapp->next;
703 /* string from no-response call forward (cfnr) */
706 /* when cfnr is done, out_setup() will setup the call */
708 /* present to forwarded party */
709 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
710 e_callerinfo.present = INFO_PRESENT_ALLOWED;
714 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
715 schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
716 schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* call one second after release */
717 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);
721 /* call to all internal interfaces */
722 p = e_ext.interfaces;
723 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
727 while(*p!=',' && *p!='\0')
732 /* search interface */
733 interface = hunt_interface(ifname);
735 trace_header("INTERFACE (not found)", DIRECTION_NONE);
736 add_trace("interface", NULL, "%s", ifname);
740 /* found interface */
741 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
743 if (interface->gsm_bs) {
744 SPRINT(portname, "%s-%d-out", interface->name, 0);
745 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
746 earlyb = (interface->is_earlyb == IS_YES);
750 if (interface->gsm_ms) {
751 SPRINT(portname, "%s-%d-out", interface->name, 0);
752 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
753 earlyb = (interface->is_earlyb == IS_YES);
757 if (interface->sip) {
758 SPRINT(portname, "%s-%d-out", interface->name, 0);
759 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
760 earlyb = (interface->is_earlyb == IS_YES);
765 /* hunt for mISDNport and create Port */
766 mISDNport = hunt_port(ifname, &channel);
768 trace_header("INTERFACE (busy)", DIRECTION_NONE);
769 add_trace("interface", NULL, "%s", ifname);
774 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
777 port = ss5_hunt_line(mISDNport);
780 if (mISDNport->ifport->remote) {
783 if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
788 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
789 add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
793 port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
795 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);
796 earlyb = mISDNport->earlyb;
798 trace_header("INTERFACE (has no function)", DIRECTION_NONE);
799 add_trace("interface", NULL, "%s", ifname);
805 FATAL("Failed to create Port instance\n");
806 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
807 memset(&dialinginfo, 0, sizeof(dialinginfo));
808 SCPY(dialinginfo.id, e_dialinginfo.id);
809 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
810 dialinginfo.ntype = e_dialinginfo.ntype;
811 /* create port_list relation */
812 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
814 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
816 goto check_anycall_intern;
819 if (e_callerinfo.id[0] && e_ext.display_name) {
820 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
822 SCPY(e_callerinfo.name, dirname);
824 // dss1 = (class Pdss1 *)port;
826 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
827 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
828 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
829 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
830 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
831 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
832 memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
833 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
834 //terminal if (e_dialinginfo.id)
835 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
836 /* handle restricted caller ids */
837 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);
838 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);
839 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);
840 /* display callerid if desired for extension */
841 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));
842 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
843 /* use cnip, if enabld */
844 // if (!e_ext.centrex)
845 // message->param.setup.callerinfo.name[0] = '\0';
846 /* screen clip if prefix is required */
847 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
848 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
849 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
850 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
852 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
853 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
854 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
855 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
857 /* use internal caller id */
858 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
859 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
860 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
861 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
863 message_put(message);
864 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
868 /* string from parallel call forward (cfp) */
871 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
872 e_callerinfo.present = INFO_PRESENT_ALLOWED;
873 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
877 vbox_only: /* entry point for answering machine only */
878 cfu_only: /* entry point for cfu */
879 cfb_only: /* entry point for cfb */
880 cfnr_only: /* entry point for cfnr */
881 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
885 /* only if vbox should be dialed, and terminal is given */
886 if (!strcmp(p, "vbox") && e_ext.number[0]) {
887 /* go to the end of p */
890 /* answering vbox call */
891 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
893 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
894 FATAL("No memory for VBOX Port instance\n");
895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
896 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
899 while(*p!=',' && *p!='\0')
904 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
906 /* hunt for mISDNport and create Port */
907 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
909 /* creating EXTERNAL port*/
910 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
913 port = ss5_hunt_line(mISDNport);
916 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);
918 FATAL("No memory for Port instance\n");
919 earlyb = mISDNport->earlyb;
924 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
925 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
930 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
931 goto check_anycall_intern;
933 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
934 memset(&dialinginfo, 0, sizeof(dialinginfo));
935 SCPY(dialinginfo.id, cfp);
936 dialinginfo.itype = INFO_ITYPE_ISDN;
937 dialinginfo.ntype = e_dialinginfo.ntype;
938 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
940 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
942 goto check_anycall_intern;
944 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
945 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
946 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
947 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
948 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
949 /* if clip is hidden */
950 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
951 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
952 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
953 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
954 message->param.setup.callerinfo.present = e_ext.callerid_present;
955 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
957 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
958 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
959 //terminal if (e_dialinginfo.id)
960 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
961 /* handle restricted caller ids */
962 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);
963 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);
964 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);
965 /* display callerid if desired for extension */
966 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));
967 message_put(message);
968 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
972 check_anycall_intern:
973 /* now we have all ports created */
975 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
977 if (!ea_endpoint->ep_join_id)
979 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
980 return; /* must exit here */
984 /* *********************** external call */
986 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
987 /* call to extenal interfaces */
988 if (e_dialinginfo.keypad[0])
989 p = e_dialinginfo.keypad;
991 p = e_dialinginfo.id;
995 while(*p!=',' && *p!='\0')
1000 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");
1001 /* search interface */
1002 interface = hunt_interface(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL);
1004 trace_header("INTERFACE (not found)", DIRECTION_NONE);
1005 add_trace("interface", NULL, "%s", ifname);
1007 goto check_anycall_extern;
1009 /* found interface */
1011 if (interface->gsm_bs) {
1012 SPRINT(portname, "%s-%d-out", interface->name, 0);
1013 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
1014 earlyb = (interface->is_earlyb == IS_YES);
1018 if (interface->gsm_ms) {
1019 SPRINT(portname, "%s-%d-out", interface->name, 0);
1020 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
1021 earlyb = (interface->is_earlyb == IS_YES);
1025 if (interface->sip) {
1026 SPRINT(portname, "%s-%d-out", interface->name, 0);
1027 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
1028 earlyb = (interface->is_earlyb == IS_YES);
1033 /* hunt for mISDNport and create Port */
1034 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
1036 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1037 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
1039 goto check_anycall_extern;
1041 /* creating EXTERNAL port*/
1042 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1045 port = ss5_hunt_line(mISDNport);
1048 if (mISDNport->ifport->remote) {
1049 admin = admin_first;
1051 if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
1053 admin = admin->next;
1056 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
1057 add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
1061 port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
1063 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);
1064 earlyb = mISDNport->earlyb;
1066 trace_header("INTERFACE (has no function)", DIRECTION_NONE);
1067 add_trace("interface", NULL, "%s", ifname);
1073 FATAL("No memory for Port instance\n");
1074 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1075 memset(&dialinginfo, 0, sizeof(dialinginfo));
1076 if (e_dialinginfo.keypad[0])
1077 SCPY(dialinginfo.keypad, number);
1079 SCPY(dialinginfo.id, number);
1080 dialinginfo.itype = INFO_ITYPE_ISDN;
1081 dialinginfo.ntype = e_dialinginfo.ntype;
1082 dialinginfo.sending_complete = e_dialinginfo.sending_complete;
1083 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1085 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1087 goto check_anycall_extern;
1089 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1090 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1091 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1092 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1093 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1094 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1095 memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
1096 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1097 //terminal if (e_dialinginfo.id)
1098 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1099 /* handle restricted caller ids */
1100 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);
1101 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);
1102 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);
1103 /* display callerid if desired for extension */
1104 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));
1105 message_put(message);
1106 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1110 check_anycall_extern:
1111 /* now we have all ports created */
1113 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1115 if (!ea_endpoint->ep_join_id)
1117 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1118 return; /* must exit here */
1125 int action_timeout(struct lcr_timer *timer, void *instance, int index)
1127 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1129 if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
1132 unsched_timer(&ea->e_redial_timeout);
1133 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
1134 ea->e_multipoint_cause = 0;
1135 ea->e_multipoint_location = 0;
1136 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1137 ea->e_join_pattern = 0;
1138 ea->process_dialing(1);
1139 /* we must exit, because our endpoint might be gone */
1144 int match_timeout(struct lcr_timer *timer, void *instance, int index)
1146 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1148 if (!ea->e_action) {
1149 unsched_timer(&ea->e_redial_timeout);
1150 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
1151 ea->process_dialing(0);
1152 /* we must exit, because our endpoint might be gone */
1158 int redial_timeout(struct lcr_timer *timer, void *instance, int index)
1160 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1162 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
1164 ea->new_state(EPOINT_STATE_OUT_SETUP);
1165 /* call special setup routine */
1171 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
1173 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1175 /* leave power dialing on */
1176 ea->e_powerdial_on = 1;
1177 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
1180 ea->e_ruleset = ruleset_main;
1182 ea->e_rule = ea->e_ruleset->rule_first;
1183 ea->e_action = NULL;
1184 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1185 ea->process_dialing(0);
1190 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
1192 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1193 struct port_list *portlist;
1194 struct lcr_msg *message;
1196 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
1198 /* release all ports */
1199 while((portlist = ea->ea_endpoint->ep_portlist)) {
1200 message = message_create(ea->ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1201 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1202 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1203 message_put(message);
1204 ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1205 ea->ea_endpoint->free_portlist(portlist);
1208 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1209 message->param.audiopath = 0;
1210 message_put(message);
1211 /* indicate no patterns */
1212 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1213 message_put(message);
1214 /* set setup state, since we have no response from the new join */
1215 ea->new_state(EPOINT_STATE_OUT_SETUP);
1220 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
1222 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1224 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea->ea_endpoint->ep_serial, ea->e_ext.cfnr);
1230 int callback_timeout(struct lcr_timer *timer, void *instance, int index)
1232 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1234 if (ea->e_state == EPOINT_STATE_IDLE) {
1235 /* epoint is idle, check callback */
1236 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
1237 ea->new_state(EPOINT_STATE_OUT_SETUP);
1244 int password_timeout(struct lcr_timer *timer, void *instance, int index)
1246 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1248 if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
1249 struct port_list *portlist;
1251 ea->e_ruleset = ruleset_main;
1253 ea->e_rule = ea->e_ruleset->rule_first;
1254 ea->e_action = NULL;
1255 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
1256 ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
1258 ea->e_connectedmode = 0;
1260 ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
1261 portlist = ea->ea_endpoint->ep_portlist;
1263 ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1264 ea->set_tone(portlist, "cause_10");
1271 /* doing a hookflash */
1272 void EndpointAppPBX::hookflash(void)
1277 /* be sure that we are active */
1279 e_tx_state = NOTIFY_STATE_ACTIVE;
1281 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1283 if (ea_endpoint->ep_use > 1) {
1284 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1287 /* dialtone after pressing the hash key */
1288 process_hangup(e_join_cause, e_join_location);
1289 e_multipoint_cause = 0;
1290 e_multipoint_location = 0;
1291 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1293 port->set_echotest(0);
1295 if (ea_endpoint->ep_join_id) {
1296 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1298 e_ruleset = ruleset_main;
1300 e_rule = e_ruleset->rule_first;
1302 new_state(EPOINT_STATE_IN_OVERLAP);
1303 e_connectedmode = 1;
1304 SCPY(e_dialinginfo.id, e_ext.prefix);
1305 e_extdialing = e_dialinginfo.id;
1307 if (e_dialinginfo.id[0]) {
1308 set_tone(ea_endpoint->ep_portlist, "dialing");
1311 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1319 /* messages from port
1321 /* port MESSAGE_SETUP */
1322 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1324 struct lcr_msg *message;
1326 int writeext; /* flags need to write extension after modification */
1329 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1331 portlist->port_type = param->setup.port_type;
1332 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1333 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1334 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1335 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1336 memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
1338 /* convert (inter-)national number type */
1339 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
1340 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1342 // e_dtmf = param->setup.dtmf;
1343 /* screen incoming caller id */
1344 if (e_callerinfo.interface[0]) {
1345 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, e_callerinfo.interface);
1346 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, e_callerinfo.interface);
1349 /* process extension */
1350 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1351 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1352 /* port makes call from extension */
1353 SCPY(e_callerinfo.extension, e_callerinfo.id);
1354 SCPY(e_ext.number, e_callerinfo.extension);
1355 SCPY(e_extension_interface, e_callerinfo.interface);
1357 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1360 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1361 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1363 /* get extension's info about caller */
1364 if (!read_extension(&e_ext, e_ext.number)) {
1365 /* extension doesn't exist */
1366 trace_header("EXTENSION (not created)", DIRECTION_IN);
1367 add_trace("extension", NULL, "%s", e_ext.number);
1369 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1370 new_state(EPOINT_STATE_OUT_DISCONNECT);
1371 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1372 e_ext.number[0] = '\0'; /* no terminal */
1377 /* put prefix (next) in front of e_dialinginfo.id */
1378 if (e_ext.next[0]) {
1379 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1380 SCPY(e_dialinginfo.id, buffer);
1381 e_ext.next[0] = '\0';
1383 } else if (e_ext.prefix[0]) {
1384 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1385 SCPY(e_dialinginfo.id, buffer);
1388 /* screen caller id by extension's config */
1389 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1391 SCPY(e_callerinfo.name, e_ext.name);
1392 /* use caller id (or if exist: id_next_call) for this call */
1393 if (e_ext.id_next_call_present >= 0) {
1394 SCPY(e_callerinfo.id, e_ext.id_next_call);
1395 /* if we restrict the pesentation */
1396 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1397 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1398 else e_callerinfo.present = e_ext.id_next_call_present;
1399 e_callerinfo.ntype = e_ext.id_next_call_type;
1400 e_ext.id_next_call_present = -1;
1403 SCPY(e_callerinfo.id, e_ext.callerid);
1404 /* if we restrict the pesentation */
1405 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1406 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1407 else e_callerinfo.present = e_ext.callerid_present;
1408 e_callerinfo.ntype = e_ext.callerid_type;
1410 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1412 /* extension is written */
1414 write_extension(&e_ext, e_ext.number);
1416 /* set volume of rx and tx */
1417 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1418 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1419 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1420 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1421 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1422 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1423 message_put(message);
1426 /* start recording if enabled */
1427 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1428 /* check if we are a terminal */
1429 if (e_ext.number[0] == '\0')
1430 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1432 port = find_port_id(portlist->port_id);
1434 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1438 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1439 /* no terminal identification */
1440 e_ext.number[0] = '\0';
1441 e_extension_interface[0] = '\0';
1442 memset(&e_ext, 0, sizeof(e_ext));
1443 e_ext.rights = 4; /* right to dial internat */
1447 e_ruleset = ruleset_main;
1449 e_rule = e_ruleset->rule_first;
1451 e_extdialing = e_dialinginfo.id;
1452 new_state(EPOINT_STATE_IN_SETUP);
1453 if (e_dialinginfo.id[0]) {
1454 set_tone(portlist, "dialing");
1456 if (e_ext.number[0])
1457 set_tone(portlist, "dialpbx");
1459 set_tone(portlist, "dialtone");
1462 if (e_state == EPOINT_STATE_IN_SETUP) {
1463 /* request MORE info, if not already at higher state */
1464 new_state(EPOINT_STATE_IN_OVERLAP);
1465 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1466 message_put(message);
1467 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1471 /* port MESSAGE_INFORMATION */
1472 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1474 struct lcr_msg *message;
1476 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1478 /* ignore information message without digit information */
1479 if (!param->information.id[0])
1484 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1486 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1491 /* if vbox_play is done, the information are just used as they come */
1493 if (e_action->index == ACTION_VBOX_PLAY) {
1494 /* concat dialing string */
1495 SCAT(e_dialinginfo.id, param->information.id);
1500 /* keypad when disconnect but in connected mode */
1501 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1502 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1503 /* processing keypad function */
1504 if (param->information.id[0] == '0') {
1510 /* keypad when connected */
1511 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1512 if (e_enablekeypad) {
1513 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1514 memcpy(&message->param, param, sizeof(union parameter));
1515 message_put(message);
1519 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1520 /* processing keypad function */
1521 if (param->information.id[0] == '0') {
1524 if (param->information.id[0])
1525 keypad_function(param->information.id[0]);
1527 if (e_ext.number[0])
1528 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1530 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1535 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1536 if (e_ext.number[0])
1537 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1539 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1543 if (!param->information.id[0])
1545 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1546 set_tone(portlist, "dialing");
1549 if (e_action->index==ACTION_OUTDIAL
1550 || e_action->index==ACTION_EXTERNAL
1551 || e_action->index==ACTION_REMOTE) {
1553 set_tone(portlist, "dialing");
1554 else if (!e_extdialing[0])
1555 set_tone(portlist, "dialing");
1557 /* concat dialing string */
1558 SCAT(e_dialinginfo.id, param->information.id);
1562 /* port MESSAGE_DTMF */
1563 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1566 struct lcr_msg *message;
1570 /* only if dtmf detection is enabled */
1572 trace_header("DTMF (disabled)", DIRECTION_IN);
1576 trace_header("DTMF", DIRECTION_IN);
1577 add_trace("digit", NULL, "%c", param->dtmf);
1581 NOTE: vbox is now handled due to overlap state
1582 /* if vbox_play is done, the dtmf digits are just used as they come */
1584 if (e_action->index == ACTION_VBOX_PLAY) {
1585 /* concat dialing string */
1586 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1587 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1588 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1591 /* continue to process *X# sequences */
1595 /* check for *X# sequence */
1596 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1597 if (e_enablekeypad) {
1598 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1599 memcpy(&message->param, param, sizeof(union parameter));
1600 message_put(message);
1603 if (e_dtmf_time+3 < now) {
1604 /* the last digit was too far in the past to be a sequence */
1605 if (param->dtmf == '*')
1606 /* only start is allowed in the sequence */
1611 /* we have a sequence of digits, see what we got */
1612 if (param->dtmf == '*')
1614 else if (param->dtmf>='0' && param->dtmf<='9') {
1615 /* we need to have a star before we receive the digit of the sequence */
1616 if (e_dtmf_last == '*')
1617 e_dtmf_last = param->dtmf;
1618 } else if (param->dtmf == '#') {
1620 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1621 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1622 if (e_dtmf_last == '0') {
1626 /* processing keypad function */
1628 keypad_function(e_dtmf_last);
1634 /* set last time of dtmf */
1639 /* check for ## hookflash during dialing */
1641 if (e_action->index==ACTION_PASSWORD
1642 || e_action->index==ACTION_PASSWORD_WRITE)
1644 if (param->dtmf=='#') { /* current digit is '#' */
1645 if (e_state==EPOINT_STATE_IN_DISCONNECT
1646 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1660 /* dialing using dtmf digit */
1661 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1662 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1663 set_tone(portlist, "dialing");
1665 /* concat dialing string */
1666 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1667 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1668 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1674 /* port MESSAGE_CRYPT */
1675 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1678 /* send crypt response to cryptman */
1679 if (param->crypt.type == CR_MESSAGE_IND)
1680 cryptman_msg2man(param->crypt.data, param->crypt.len);
1682 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1686 /* port MESSAGE_OVERLAP */
1687 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1689 struct lcr_msg *message;
1691 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1693 /* signal to call tool */
1694 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1696 if (e_dialing_queue[0] && portlist) {
1697 /* send what we have not dialed yet, because we had no setup complete */
1698 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1699 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1700 SCPY(message->param.information.id, e_dialing_queue);
1701 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1702 message_put(message);
1703 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1704 e_dialing_queue[0] = '\0';
1706 /* check if pattern is available */
1707 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1708 /* indicate patterns */
1709 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1710 message_put(message);
1712 /* connect audio, if not already */
1713 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1714 message->param.audiopath = 1;
1715 message_put(message);
1717 /* indicate no patterns */
1718 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1719 message_put(message);
1721 /* disconnect audio, if not already */
1722 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1723 message->param.audiopath = 0;
1724 message_put(message);
1726 new_state(EPOINT_STATE_OUT_OVERLAP);
1727 /* if we are in a join */
1728 if (ea_endpoint->ep_join_id) {
1729 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1730 memcpy(&message->param, param, sizeof(union parameter));
1731 message_put(message);
1735 /* port MESSAGE_PROCEEDING */
1736 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1738 struct lcr_msg *message;
1740 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1742 /* signal to call tool */
1743 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1745 e_state = EPOINT_STATE_OUT_PROCEEDING;
1746 /* check if pattern is availatle */
1747 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1748 /* indicate patterns */
1749 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1750 message_put(message);
1752 /* connect audio, if not already */
1753 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1754 message->param.audiopath = 1;
1755 message_put(message);
1757 /* indicate no patterns */
1758 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1759 message_put(message);
1761 /* disconnect audio, if not already */
1762 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1763 message->param.audiopath = 0;
1764 message_put(message);
1766 /* if we are in a call */
1767 if (ea_endpoint->ep_join_id) {
1768 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1769 memcpy(&message->param, param, sizeof(union parameter));
1770 message_put(message);
1774 /* port MESSAGE_ALERTING */
1775 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1777 struct lcr_msg *message;
1779 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1781 /* signal to call tool */
1782 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1785 // set_tone(portlist, "hold");
1787 new_state(EPOINT_STATE_OUT_ALERTING);
1788 /* check if pattern is available */
1789 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1790 /* indicate patterns */
1791 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1792 message_put(message);
1794 /* connect audio, if not already */
1795 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1796 message->param.audiopath = 1;
1797 message_put(message);
1799 /* indicate no patterns */
1800 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1801 message_put(message);
1803 /* disconnect audio, if not already */
1804 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1805 message->param.audiopath = 0;
1806 message_put(message);
1808 /* if we are in a call */
1809 if (ea_endpoint->ep_join_id) {
1810 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1811 memcpy(&message->param, param, sizeof(union parameter));
1812 message_put(message);
1816 /* port MESSAGE_CONNECT */
1817 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1819 struct lcr_msg *message;
1821 unsigned int port_id = portlist->port_id;
1822 struct port_list *tportlist;
1826 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1828 /* signal to call tool */
1829 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1831 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1832 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1833 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1834 tportlist = ea_endpoint->ep_portlist;
1835 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1836 tportlist = tportlist->next;
1837 if (tportlist->port_id == port_id)
1838 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1839 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1840 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1841 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1842 message_put(message);
1843 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1844 ea_endpoint->free_portlist(tportlist);
1846 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1851 if (e_callerinfo.interface[0])
1852 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, e_connectinfo.interface);
1854 /* screen connected name */
1856 SCPY(e_connectinfo.name, e_ext.name);
1858 /* add internal id to colp */
1859 SCPY(e_connectinfo.extension, e_ext.number);
1861 /* we store the connected port number */
1862 SCPY(e_extension_interface, e_connectinfo.interface);
1864 /* for internal and am calls, we get the extension's id */
1865 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
1866 SCPY(e_connectinfo.id, e_ext.callerid);
1867 SCPY(e_connectinfo.extension, e_ext.number);
1868 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1869 e_connectinfo.ntype = e_ext.callerid_type;
1870 e_connectinfo.present = e_ext.callerid_present;
1872 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
1873 e_connectinfo.itype = INFO_ITYPE_VBOX;
1874 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
1877 new_state(EPOINT_STATE_CONNECT);
1879 /* set volume of rx and tx */
1880 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1881 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1882 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1883 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1884 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1885 message_put(message);
1888 unsched_timer(&e_cfnr_timeout);
1889 unsched_timer(&e_cfnr_call_timeout);
1890 if (e_ext.number[0])
1891 e_dtmf = 1; /* allow dtmf */
1894 /* other calls with no caller id (or not available for the extension) and force colp */
1895 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
1896 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
1897 if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT) {
1898 /* external extension answered */
1899 port = find_port_id(portlist->port_id);
1901 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
1902 e_connectinfo.present = INFO_PRESENT_ALLOWED;
1907 /* send connect to join */
1908 if (ea_endpoint->ep_join_id) {
1909 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1910 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
1911 message_put(message);
1913 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1914 message->param.audiopath = 1;
1915 message_put(message);
1916 } else if (!e_adminid) {
1918 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
1919 SCPY(e_ext.number, e_cbcaller);
1920 new_state(EPOINT_STATE_IN_OVERLAP);
1921 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1923 /* get extension's info about terminal */
1924 if (!read_extension(&e_ext, e_ext.number)) {
1925 /* extension doesn't exist */
1926 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1927 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1928 new_state(EPOINT_STATE_OUT_DISCONNECT);
1929 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1933 /* put prefix in front of e_cbdialing */
1934 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
1935 SCPY(e_dialinginfo.id, buffer);
1936 e_dialinginfo.itype = INFO_ITYPE_ISDN;
1937 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1939 /* use caller id (or if exist: id_next_call) for this call */
1940 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1941 SCPY(e_callerinfo.extension, e_ext.number);
1942 if (e_ext.id_next_call_present >= 0) {
1943 SCPY(e_callerinfo.id, e_ext.id_next_call);
1944 e_callerinfo.present = e_ext.id_next_call_present;
1945 e_callerinfo.ntype = e_ext.id_next_call_type;
1946 e_ext.id_next_call_present = -1;
1947 /* extension is written */
1948 write_extension(&e_ext, e_ext.number);
1950 SCPY(e_callerinfo.id, e_ext.callerid);
1951 e_callerinfo.present = e_ext.callerid_present;
1952 e_callerinfo.ntype = e_ext.callerid_type;
1954 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1956 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
1959 /* check if caller id is NOT authenticated */
1960 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
1961 /* make call state to enter password */
1962 new_state(EPOINT_STATE_IN_OVERLAP);
1963 e_action = &action_password_write;
1964 unsched_timer(&e_match_timeout);
1965 e_match_to_action = NULL;
1966 e_dialinginfo.id[0] = '\0';
1967 e_extdialing = strchr(e_dialinginfo.id, '\0');
1968 schedule_timer(&e_password_timeout, 20, 0);
1971 /* incoming call (callback) */
1972 e_ruleset = ruleset_main;
1974 e_rule = e_ruleset->rule_first;
1976 e_extdialing = e_dialinginfo.id;
1977 if (e_dialinginfo.id[0]) {
1978 set_tone(portlist, "dialing");
1981 set_tone(portlist, "dialpbx");
1984 } else { /* testcall */
1985 set_tone(portlist, "hold");
1988 /* start recording if enabled, not when answering machine answers */
1989 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)) {
1990 /* check if we are a terminal */
1991 if (e_ext.number[0] == '\0')
1992 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1994 port = find_port_id(portlist->port_id);
1996 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2001 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2002 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2004 struct lcr_msg *message;
2006 unsigned int port_id = portlist->port_id;
2010 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2012 /* signal to call tool */
2013 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2015 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2016 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2017 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2022 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);
2023 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2024 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2026 /* check if we have more than one portlist relation and we just ignore the disconnect */
2027 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2028 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2029 portlist = ea_endpoint->ep_portlist;
2031 if (portlist->port_id == port_id)
2033 portlist = portlist->next;
2036 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2037 if (message_type != MESSAGE_RELEASE) {
2038 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2039 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2040 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2041 message_put(message);
2042 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2044 ea_endpoint->free_portlist(portlist);
2045 return; /* one relation removed */
2047 if (e_state == EPOINT_STATE_CONNECT) {
2048 /* use cause from port after connect */
2049 cause = param->disconnectinfo.cause;
2050 location = param->disconnectinfo.location;
2052 /* use multipoint cause if no connect yet */
2053 if (e_multipoint_cause) {
2054 cause = e_multipoint_cause;
2055 location = e_multipoint_location;
2057 cause = CAUSE_NOUSER;
2058 location = LOCATION_PRIVATE_LOCAL;
2062 unsched_timer(&e_cfnr_timeout);
2063 unsched_timer(&e_cfnr_call_timeout);
2065 /* process hangup */
2066 process_hangup(e_join_cause, e_join_location);
2067 e_multipoint_cause = 0;
2068 e_multipoint_location = 0;
2070 if (message_type == MESSAGE_DISCONNECT) {
2071 /* tone to disconnected end */
2072 SPRINT(buffer, "cause_%02x", cause);
2073 if (ea_endpoint->ep_portlist)
2074 set_tone(ea_endpoint->ep_portlist, buffer);
2076 new_state(EPOINT_STATE_IN_DISCONNECT);
2079 if (ea_endpoint->ep_join_id) {
2080 int haspatterns = 0;
2081 /* check if pattern is available */
2082 if (ea_endpoint->ep_portlist)
2083 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2084 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
2085 && message_type != MESSAGE_RELEASE) // if we release, we are done
2088 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2089 /* indicate patterns */
2090 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2091 message_put(message);
2092 /* connect audio, if not already */
2093 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2094 message->param.audiopath = 1;
2095 message_put(message);
2096 /* send disconnect */
2097 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2098 memcpy(&message->param, param, sizeof(union parameter));
2099 message_put(message);
2100 /* disable encryption if disconnected */
2101 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2104 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2108 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2111 if (message_type == MESSAGE_RELEASE)
2112 ea_endpoint->free_portlist(portlist);
2113 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
2114 return; /* must exit here */
2117 /* port MESSAGE_TIMEOUT */
2118 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2122 trace_header("TIMEOUT", DIRECTION_IN);
2123 message_type = MESSAGE_DISCONNECT;
2124 switch (param->state) {
2125 case PORT_STATE_OUT_SETUP:
2126 case PORT_STATE_OUT_OVERLAP:
2127 add_trace("state", NULL, "outgoing setup/dialing");
2129 /* no user responding */
2130 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2131 return; /* must exit here */
2133 case PORT_STATE_IN_SETUP:
2134 case PORT_STATE_IN_OVERLAP:
2135 add_trace("state", NULL, "incoming setup/dialing");
2136 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2137 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2140 case PORT_STATE_OUT_PROCEEDING:
2141 add_trace("state", NULL, "outgoing proceeding");
2143 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2144 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2145 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2146 return; /* must exit here */
2148 case PORT_STATE_IN_PROCEEDING:
2149 add_trace("state", NULL, "incoming proceeding");
2150 param->disconnectinfo.cause = CAUSE_NOUSER;
2151 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2154 case PORT_STATE_OUT_ALERTING:
2155 add_trace("state", NULL, "outgoing alerting");
2157 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2158 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2159 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2160 return; /* must exit here */
2162 case PORT_STATE_CONNECT:
2163 add_trace("state", NULL, "connect");
2165 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2166 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2167 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2168 return; /* must exit here */
2170 case PORT_STATE_IN_ALERTING:
2171 add_trace("state", NULL, "incoming alerting");
2172 param->disconnectinfo.cause = CAUSE_NOANSWER;
2173 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2176 case PORT_STATE_IN_DISCONNECT:
2177 case PORT_STATE_OUT_DISCONNECT:
2178 add_trace("state", NULL, "disconnect");
2180 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2181 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2182 return; /* must exit here */
2185 param->disconnectinfo.cause = 31; /* normal unspecified */
2186 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2189 /* release call, disconnect isdn */
2191 new_state(EPOINT_STATE_OUT_DISCONNECT);
2192 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2193 SCPY(e_tone, cause);
2195 set_tone(portlist, cause);
2196 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2197 portlist = portlist->next;
2199 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2202 /* port MESSAGE_NOTIFY */
2203 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2205 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2207 struct lcr_msg *message;
2208 const char *logtext = "";
2211 /* signal to call tool */
2212 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);
2213 if (param->notifyinfo.notify) {
2214 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2217 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2218 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2219 case INFO_NOTIFY_REMOTE_HOLD:
2220 case INFO_NOTIFY_USER_SUSPENDED:
2221 /* tell call about it */
2222 if (ea_endpoint->ep_join_id) {
2223 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2224 message->param.audiopath = 0;
2225 message_put(message);
2229 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2230 case INFO_NOTIFY_USER_RESUMED:
2231 /* set volume of rx and tx */
2232 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2233 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2235 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2236 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2237 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2238 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2239 message_put(message);
2241 /* set current tone */
2243 set_tone(portlist, e_tone);
2244 /* tell call about it */
2245 if (ea_endpoint->ep_join_id) {
2246 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2247 message->param.audiopath = 1;
2248 message_put(message);
2253 /* get name of notify */
2254 switch(param->notifyinfo.notify) {
2259 logtext = "USER_SUSPENDED";
2262 logtext = "BEARER_SERVICE_CHANGED";
2265 logtext = "USER_RESUMED";
2268 logtext = "CONFERENCE_ESTABLISHED";
2271 logtext = "CONFERENCE_DISCONNECTED";
2274 logtext = "OTHER_PARTY_ADDED";
2277 logtext = "ISOLATED";
2280 logtext = "REATTACHED";
2283 logtext = "OTHER_PARTY_ISOLATED";
2286 logtext = "OTHER_PARTY_REATTACHED";
2289 logtext = "OTHER_PARTY_SPLIT";
2292 logtext = "OTHER_PARTY_DISCONNECTED";
2295 logtext = "CONFERENCE_FLOATING";
2298 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2301 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2304 logtext = "CALL_IS_A_WAITING_CALL";
2307 logtext = "DIVERSION_ACTIVATED";
2310 logtext = "RESERVED_CT_1";
2313 logtext = "RESERVED_CT_2";
2316 logtext = "REVERSE_CHARGING";
2319 logtext = "REMOTE_HOLD";
2322 logtext = "REMOTE_RETRIEVAL";
2325 logtext = "CALL_IS_DIVERTING";
2328 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2333 /* notify call if available */
2334 if (ea_endpoint->ep_join_id) {
2335 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2336 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2337 message_put(message);
2342 /* port MESSAGE_PROGRESS */
2343 void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
2345 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2347 struct lcr_msg *message;
2349 /* signal to call tool */
2350 admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
2352 /* send progress to call if available */
2353 if (ea_endpoint->ep_join_id) {
2354 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
2355 memcpy(&message->param.progressinfo, ¶m->progressinfo, sizeof(struct progress_info));
2356 message_put(message);
2361 /* port MESSAGE_FACILITY */
2362 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2364 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2366 struct lcr_msg *message;
2368 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2369 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2370 message_put(message);
2373 /* port MESSAGE_SUSPEND */
2374 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2375 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2377 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2379 /* epoint is now parked */
2380 ea_endpoint->ep_park = 1;
2381 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2382 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2384 /* remove port relation */
2385 ea_endpoint->free_portlist(portlist);
2388 /* port MESSAGE_RESUME */
2389 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2390 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2392 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2394 /* epoint is now resumed */
2395 ea_endpoint->ep_park = 0;
2399 /* port MESSAGE_ENABLEKEYPAD */
2400 void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
2402 struct lcr_msg *message;
2404 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2406 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
2407 memcpy(&message->param, param, sizeof(union parameter));
2408 message_put(message);
2412 /* port sends message to the endpoint
2414 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2416 struct port_list *portlist;
2418 portlist = ea_endpoint->ep_portlist;
2420 if (port_id == portlist->port_id)
2422 portlist = portlist->next;
2425 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);
2429 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2430 switch(message_type) {
2431 case MESSAGE_TONE_EOF: /* tone is end of file */
2432 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2434 if (e_action->index == ACTION_VBOX_PLAY) {
2437 if (e_action->index == ACTION_EFI) {
2443 case MESSAGE_TONE_COUNTER: /* counter info received */
2444 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);
2446 if (e_action->index == ACTION_VBOX_PLAY) {
2447 e_vbox_counter = param->counter.current;
2448 if (param->counter.max >= 0)
2449 e_vbox_counter_max = param->counter.max;
2453 /* PORT sends SETUP message */
2455 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);
2456 if (e_state!=EPOINT_STATE_IDLE) {
2457 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2460 port_setup(portlist, message_type, param);
2463 /* PORT sends INFORMATION message */
2464 case MESSAGE_INFORMATION: /* additional digits received */
2465 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);
2466 port_information(portlist, message_type, param);
2469 /* PORT sends FACILITY message */
2470 case MESSAGE_FACILITY:
2471 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2472 port_facility(portlist, message_type, param);
2475 /* PORT sends DTMF message */
2476 case MESSAGE_DTMF: /* dtmf digits received */
2477 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);
2478 port_dtmf(portlist, message_type, param);
2481 /* PORT sends CRYPT message */
2482 case MESSAGE_CRYPT: /* crypt response received */
2483 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2484 port_crypt(portlist, message_type, param);
2487 /* PORT sends MORE message */
2488 case MESSAGE_OVERLAP:
2489 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);
2490 if (e_state != EPOINT_STATE_OUT_SETUP) {
2491 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);
2494 port_overlap(portlist, message_type, param);
2497 /* PORT sends PROCEEDING message */
2498 case MESSAGE_PROCEEDING: /* port is proceeding */
2499 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);
2500 if (e_state!=EPOINT_STATE_OUT_SETUP
2501 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2502 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);
2505 port_proceeding(portlist, message_type, param);
2508 /* PORT sends ALERTING message */
2509 case MESSAGE_ALERTING:
2510 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);
2511 if (e_state!=EPOINT_STATE_OUT_SETUP
2512 && e_state!=EPOINT_STATE_OUT_OVERLAP
2513 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2514 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);
2517 port_alerting(portlist, message_type, param);
2520 /* PORT sends CONNECT message */
2521 case MESSAGE_CONNECT:
2522 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);
2523 if (e_state!=EPOINT_STATE_OUT_SETUP
2524 && e_state!=EPOINT_STATE_OUT_OVERLAP
2525 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2526 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2530 port_connect(portlist, message_type, param);
2533 /* PORT sends DISCONNECT message */
2534 case MESSAGE_DISCONNECT: /* port is disconnected */
2535 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);
2536 port_disconnect_release(portlist, message_type, param);
2539 /* PORT sends a RELEASE message */
2540 case MESSAGE_RELEASE: /* port releases */
2541 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);
2542 /* portlist is release at port_disconnect_release, thanx Paul */
2543 port_disconnect_release(portlist, message_type, param);
2546 /* PORT sends a TIMEOUT message */
2547 case MESSAGE_TIMEOUT:
2548 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);
2549 port_timeout(portlist, message_type, param);
2550 break; /* release */
2552 /* PORT sends a NOTIFY message */
2553 case MESSAGE_NOTIFY:
2554 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);
2555 port_notify(portlist, message_type, param);
2558 /* PORT sends a PROGRESS message */
2559 case MESSAGE_PROGRESS:
2560 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received progress.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2561 port_progress(portlist, message_type, param);
2564 /* PORT sends a SUSPEND message */
2565 case MESSAGE_SUSPEND:
2566 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);
2567 port_suspend(portlist, message_type, param);
2568 break; /* suspend */
2570 /* PORT sends a RESUME message */
2571 case MESSAGE_RESUME:
2572 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);
2573 port_resume(portlist, message_type, param);
2577 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2578 /* port assigns bchannel */
2579 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2580 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);
2581 /* only one port is expected to be connected to bchannel */
2582 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2583 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2587 /* PORT requests DTMF */
2588 case MESSAGE_ENABLEKEYPAD:
2589 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') requests DTMF/KEYPAD.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2590 port_enablekeypad(portlist, message_type, param);
2595 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);
2598 /* Note: this endpoint may be destroyed, so we MUST return */
2602 /* messages from join
2604 /* join MESSAGE_CRYPT */
2605 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2608 switch(param->crypt.type) {
2609 /* message from remote port to "crypt manager" */
2610 case CU_ACTK_REQ: /* activate key-exchange */
2611 case CU_ACTS_REQ: /* activate shared key */
2612 case CU_DACT_REQ: /* deactivate */
2613 case CU_INFO_REQ: /* request last info message */
2614 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2617 /* message from "crypt manager" to user */
2618 case CU_ACTK_CONF: /* key-echange done */
2619 case CU_ACTS_CONF: /* shared key done */
2620 case CU_DACT_CONF: /* deactivated */
2621 case CU_DACT_IND: /* deactivated */
2622 case CU_ERROR_IND: /* receive error message */
2623 case CU_INFO_IND: /* receive info message */
2624 case CU_INFO_CONF: /* receive info message */
2625 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2629 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);
2634 /* join MESSAGE_INFORMATION */
2635 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2637 struct lcr_msg *message;
2642 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2643 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2644 message_put(message);
2645 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2646 portlist = portlist->next;
2650 /* join MESSAGE_FACILITY */
2651 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2653 struct lcr_msg *message;
2655 if (!e_ext.facility && e_ext.number[0]) {
2660 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2661 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2662 message_put(message);
2663 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2664 portlist = portlist->next;
2668 /* join MESSAGE_MORE */
2669 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2671 struct lcr_msg *message;
2673 new_state(EPOINT_STATE_IN_OVERLAP);
2676 if (e_join_pattern && e_ext.own_setup) {
2677 /* disconnect audio */
2678 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2679 message->param.audiopath = 0;
2680 message_put(message);
2682 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2683 if (e_dialinginfo.id[0])
2684 set_tone(portlist, "dialing");
2686 set_tone(portlist, "dialtone");
2689 if (e_dialinginfo.id[0]) {
2690 set_tone(portlist, "dialing");
2692 if (e_ext.number[0])
2693 set_tone(portlist, "dialpbx");
2695 set_tone(portlist, "dialtone");
2699 /* join MESSAGE_PROCEEDING */
2700 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2702 struct lcr_msg *message;
2704 new_state(EPOINT_STATE_IN_PROCEEDING);
2706 /* own proceeding tone */
2707 if (e_join_pattern) {
2708 /* connect / disconnect audio */
2709 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2710 if (e_ext.own_proceeding)
2711 message->param.audiopath = 0;
2713 message->param.audiopath = 1;
2714 message_put(message);
2716 // UCPY(e_join_tone, "proceeding");
2718 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2719 message_put(message);
2720 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2722 set_tone(portlist, "proceeding");
2725 /* join MESSAGE_ALERTING */
2726 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2728 struct lcr_msg *message;
2730 new_state(EPOINT_STATE_IN_ALERTING);
2732 /* own alerting tone */
2733 if (e_join_pattern) {
2734 /* connect / disconnect audio */
2735 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2736 if (e_ext.own_alerting)
2737 message->param.audiopath = 0;
2739 message->param.audiopath = 1;
2740 message_put(message);
2743 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2744 message_put(message);
2745 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2747 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2748 set_tone(portlist, "ringing");
2751 if (e_ext.number[0])
2752 set_tone(portlist, "ringpbx");
2754 set_tone(portlist, "ringing");
2756 if (e_ext.number[0])
2757 e_dtmf = 1; /* allow dtmf */
2760 /* join MESSAGE_CONNECT */
2761 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2763 struct lcr_msg *message;
2766 new_state(EPOINT_STATE_CONNECT);
2767 // UCPY(e_join_tone, "");
2769 if (e_ext.number[0])
2770 e_dtmf = 1; /* allow dtmf */
2773 unsched_timer(&e_powerdial_timeout);
2774 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2776 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2777 memcpy(&message->param, param, sizeof(union parameter));
2779 /* screen clip if prefix is required */
2780 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2781 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2782 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2783 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2786 /* use internal caller id */
2787 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2788 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2789 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2792 /* handle restricted caller ids */
2793 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);
2794 /* display callerid if desired for extension */
2795 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));
2797 /* use conp, if enabld */
2798 // if (!e_ext.centrex)
2799 // message->param.connectinfo.name[0] = '\0';
2802 message_put(message);
2803 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2805 set_tone(portlist, NULL);
2807 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2808 message->param.audiopath = 1;
2809 message_put(message);
2814 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2815 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2818 struct lcr_msg *message;
2819 struct port_list *portlist = NULL;
2823 /* be sure that we are active */
2825 e_tx_state = NOTIFY_STATE_ACTIVE;
2827 /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
2828 if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2829 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
2831 /* set time for power dialing */
2832 schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
2835 /* set redial tone */
2836 if (ea_endpoint->ep_portlist) {
2839 set_tone(ea_endpoint->ep_portlist, "redial");
2840 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);
2841 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2842 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2843 new_state(EPOINT_STATE_IN_PROCEEDING);
2844 if (ea_endpoint->ep_portlist) {
2845 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2846 message_put(message);
2847 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2849 /* caused the error, that the first knock sound was not there */
2850 /* set_tone(portlist, "proceeding"); */
2852 /* send display of powerdialing */
2853 if (e_ext.display_dialing) {
2854 portlist = ea_endpoint->ep_portlist;
2856 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2858 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2860 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2861 message_put(message);
2862 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2863 portlist = portlist->next;
2873 if ((e_state!=EPOINT_STATE_CONNECT
2874 && e_state!=EPOINT_STATE_OUT_DISCONNECT
2875 && e_state!=EPOINT_STATE_IN_OVERLAP
2876 && e_state!=EPOINT_STATE_IN_PROCEEDING
2877 && e_state!=EPOINT_STATE_IN_ALERTING)
2878 || !ea_endpoint->ep_portlist) { /* or no port */
2879 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
2880 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
2881 return; /* must exit here */
2884 if (!e_join_cause) {
2885 e_join_cause = param->disconnectinfo.cause;
2886 e_join_location = param->disconnectinfo.location;
2889 /* on release we need the audio again! */
2890 if (message_type == MESSAGE_RELEASE) {
2892 ea_endpoint->ep_join_id = 0;
2894 /* disconnect and select tone */
2895 new_state(EPOINT_STATE_OUT_DISCONNECT);
2896 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2897 /* if own_cause, we must release the join */
2898 if (e_ext.own_cause /* own cause */
2899 || !e_join_pattern) { /* no patterns */
2900 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);
2901 if (message_type != MESSAGE_RELEASE)
2902 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2904 } else { /* else we enable audio */
2905 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2906 message->param.audiopath = 1;
2907 message_put(message);
2909 /* send disconnect message */
2910 SCPY(e_tone, cause);
2911 portlist = ea_endpoint->ep_portlist;
2913 set_tone(portlist, cause);
2914 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2915 portlist = portlist->next;
2919 /* join MESSAGE_SETUP */
2920 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
2922 struct lcr_msg *message;
2923 // struct interface *interface;
2925 /* if we already in setup state, we just update the dialing with new digits */
2926 if (e_state == EPOINT_STATE_OUT_SETUP
2927 || e_state == EPOINT_STATE_OUT_OVERLAP) {
2928 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
2929 /* if digits changed, what we have already dialed */
2930 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
2931 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);
2932 /* release all ports */
2933 while((portlist = ea_endpoint->ep_portlist)) {
2934 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2935 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2936 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2937 message_put(message);
2938 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2939 ea_endpoint->free_portlist(portlist);
2942 /* disconnect audio */
2943 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2944 message->param.audiopath = 0;
2945 message_put(message);
2947 /* get dialing info */
2948 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
2949 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
2950 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
2951 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
2952 new_state(EPOINT_STATE_OUT_OVERLAP);
2955 schedule_timer(&e_redial_timeout, 1, 0);
2958 /* if we have a pending redial, so we just adjust the dialing number */
2959 if (e_redial_timeout.active) {
2960 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);
2961 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
2964 if (!ea_endpoint->ep_portlist) {
2965 PERROR("ERROR: overlap dialing to a NULL port relation\n");
2967 if (ea_endpoint->ep_portlist->next) {
2968 PERROR("ERROR: overlap dialing to a port_list port relation\n");
2970 if (e_state == EPOINT_STATE_OUT_SETUP) {
2972 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);
2973 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
2976 /* get what we have not dialed yet */
2977 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));
2978 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2979 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
2980 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
2981 message_put(message);
2982 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2984 /* always store what we have dialed or queued */
2985 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
2989 if (e_state != EPOINT_STATE_IDLE) {
2990 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2993 /* if an internal extension is dialed, copy that number */
2994 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
2995 SCPY(e_ext.number, param->setup.dialinginfo.id);
2996 /* if an internal extension is dialed, get extension's info about caller */
2997 if (e_ext.number[0]) {
2998 if (!read_extension(&e_ext, e_ext.number)) {
2999 e_ext.number[0] = '\0';
3000 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3004 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3005 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3006 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3007 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3008 memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
3010 /* process (voice over) data calls */
3011 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3012 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3013 memset(&e_capainfo, 0, sizeof(e_capainfo));
3014 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3015 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3016 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3019 new_state(EPOINT_STATE_OUT_SETUP);
3020 /* call special setup routine */
3024 /* join MESSAGE_mISDNSIGNAL */
3025 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3027 struct lcr_msg *message;
3030 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3031 memcpy(&message->param, param, sizeof(union parameter));
3032 message_put(message);
3033 portlist = portlist->next;
3037 /* join MESSAGE_BRIDE */
3038 void EndpointAppPBX::join_bridge(struct port_list *portlist, int message_type, union parameter *param)
3040 struct lcr_msg *message;
3043 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
3044 memcpy(&message->param, param, sizeof(union parameter));
3045 message_put(message);
3046 portlist = portlist->next;
3050 /* join MESSAGE_NOTIFY */
3051 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3053 struct lcr_msg *message;
3056 if (param->notifyinfo.notify) {
3057 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3058 // /* if notification was generated locally, we turn hold music on/off */
3059 // if (param->notifyinfo.local)
3060 // 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)
3064 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3065 if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3067 set_tone(portlist, "");
3068 portlist = portlist->next;
3071 portlist = ea_endpoint->ep_portlist;
3076 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3078 set_tone(portlist, "hold");
3079 portlist = portlist->next;
3081 portlist = ea_endpoint->ep_portlist;
3086 /* save new state */
3087 e_tx_state = new_state;
3090 /* notify port(s) about it */
3092 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3093 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3094 /* handle restricted caller ids */
3095 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3096 /* display callerid if desired for extension */
3097 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));
3098 message_put(message);
3099 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3100 portlist = portlist->next;
3104 /* join MESSAGE_DTMF */
3105 void EndpointAppPBX::join_dtmf(struct port_list *portlist, int message_type, union parameter *param)
3107 struct lcr_msg *message;
3110 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DTMF);
3111 memcpy(&message->param, param, sizeof(union parameter));
3112 message_put(message);
3113 portlist = portlist->next;
3117 /* JOIN sends messages to the endpoint
3119 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3121 struct port_list *portlist;
3122 struct lcr_msg *message;
3125 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3129 portlist = ea_endpoint->ep_portlist;
3131 // 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);
3132 switch(message_type) {
3133 /* JOIN SENDS TONE message */
3135 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);
3136 set_tone(portlist, param->tone.name);
3139 /* JOIN SENDS CRYPT message */
3141 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);
3142 join_crypt(portlist, message_type, param);
3145 /* JOIN sends INFORMATION message */
3146 case MESSAGE_INFORMATION:
3147 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);
3148 join_information(portlist, message_type, param);
3151 /* JOIN sends FACILITY message */
3152 case MESSAGE_FACILITY:
3153 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);
3154 join_facility(portlist, message_type, param);
3157 /* JOIN sends OVERLAP message */
3158 case MESSAGE_OVERLAP:
3159 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);
3160 if (e_state!=EPOINT_STATE_IN_SETUP
3161 && e_state!=EPOINT_STATE_IN_OVERLAP) {
3162 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3165 join_overlap(portlist, message_type, param);
3168 /* JOIN sends PROCEEDING message */
3169 case MESSAGE_PROCEEDING:
3170 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);
3171 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3172 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3175 join_proceeding(portlist, message_type, param);
3178 /* JOIN sends ALERTING message */
3179 case MESSAGE_ALERTING:
3180 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);
3181 if (e_state!=EPOINT_STATE_IN_OVERLAP
3182 && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3183 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3186 join_alerting(portlist, message_type, param);
3189 /* JOIN sends CONNECT message */
3190 case MESSAGE_CONNECT:
3191 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);
3192 if (e_state!=EPOINT_STATE_IN_OVERLAP
3193 && e_state!=EPOINT_STATE_IN_PROCEEDING
3194 && e_state!=EPOINT_STATE_IN_ALERTING) {
3195 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3198 join_connect(portlist, message_type, param);
3201 /* JOIN sends DISCONNECT/RELEASE message */
3202 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3203 case MESSAGE_RELEASE: /* JOIN releases */
3204 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);
3205 join_disconnect_release(message_type, param);
3208 /* JOIN sends SETUP message */
3210 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);
3211 join_setup(portlist, message_type, param);
3214 /* JOIN sends special mISDNSIGNAL message */
3215 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3216 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);
3217 join_mISDNsignal(portlist, message_type, param);
3220 /* JOIN sends bridge message */
3221 case MESSAGE_BRIDGE: /* bride message to port */
3222 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bridge message.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3223 join_bridge(portlist, message_type, param);
3226 /* JOIN has pattern available */
3227 case MESSAGE_PATTERN: /* indicating pattern available */
3228 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);
3229 if (!e_join_pattern) {
3230 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3234 set_tone(portlist, NULL);
3235 portlist = portlist->next;
3237 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3238 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3239 message->param.audiopath = 1;
3240 message_put(message);
3244 /* JOIN has no pattern available */
3245 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3246 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);
3247 if (e_join_pattern) {
3248 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3250 /* disconnect our audio tx and rx */
3251 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3252 message->param.audiopath = 0;
3253 message_put(message);
3258 /* JOIN (dunno at the moment) */
3259 case MESSAGE_REMOTE_AUDIO:
3260 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);
3261 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3262 message->param.audiopath = param->channel;
3263 message_put(message);
3267 /* JOIN sends a notify message */
3268 case MESSAGE_NOTIFY:
3269 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);
3270 join_notify(portlist, message_type, param);
3273 /* JOIN wants keypad / dtmf */
3274 case MESSAGE_ENABLEKEYPAD:
3275 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);
3278 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3282 /* JOIN sends a DTMF message */
3284 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received dtmf.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3285 join_dtmf(portlist, message_type, param);
3289 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);
3294 /* pick_join will connect the first incoming call found. the endpoint
3295 * will receivce a MESSAGE_CONNECT.
3297 int match_list(char *list, char *item)
3299 char *end, *next = NULL;
3301 /* no list make matching */
3306 /* eliminate white spaces */
3307 while (*list > '\0' && *list <= ' ')
3313 /* if end of list is reached, we return */
3314 if (list[0] == '\0')
3316 /* if we have more than one entry (left) */
3317 if ((end = strchr(list, ',')))
3320 next = end = strchr(list, '\0');
3321 while (*(end-1) <= ' ')
3323 /* if string part matches item */
3324 if (!strncmp(list, item, end-list))
3330 void EndpointAppPBX::pick_join(char *extensions)
3332 struct lcr_msg *message;
3333 struct port_list *portlist;
3335 class EndpointAppPBX *eapp, *found;
3337 class JoinPBX *joinpbx;
3338 struct join_relation *relation;
3341 /* find an endpoint that is ringing internally or vbox with higher priority */
3344 eapp = apppbx_first;
3346 if (eapp!=this && ea_endpoint->ep_portlist) {
3347 portlist = eapp->ea_endpoint->ep_portlist;
3349 if ((port = find_port_id(portlist->port_id))) {
3350 if (port->p_type == PORT_TYPE_VBOX_OUT) {
3351 if (match_list(extensions, eapp->e_ext.number)) {
3357 if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT
3358 && port->p_state==PORT_STATE_OUT_ALERTING)
3359 if (match_list(extensions, eapp->e_ext.number)) {
3363 portlist = portlist->next;
3371 /* if no endpoint found */
3373 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);
3375 set_tone(ea_endpoint->ep_portlist, "cause_10");
3376 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3377 new_state(EPOINT_STATE_OUT_DISCONNECT);
3382 if (ea_endpoint->ep_join_id) {
3383 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3386 if (!eapp->ea_endpoint->ep_join_id) {
3387 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3390 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3392 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3395 if (join->j_type != JOIN_TYPE_PBX) {
3396 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3399 joinpbx = (class JoinPBX *)join;
3400 relation = joinpbx->j_relation;
3402 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3405 while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
3406 relation = relation->next;
3408 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3413 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3415 if (options.deb & DEBUG_EPOINT) {
3416 class Join *debug_c = join_first;
3417 class Endpoint *debug_e = epoint_first;
3418 class Port *debug_p = port_first;
3420 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3422 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3424 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3425 debug_c = debug_c->next;
3427 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3429 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3430 debug_e = debug_e->next;
3432 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3434 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3435 debug_p = debug_p->next;
3440 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3441 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3442 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3444 /* connnecting our endpoint */
3445 new_state(EPOINT_STATE_CONNECT);
3446 if (e_ext.number[0])
3448 set_tone(ea_endpoint->ep_portlist, NULL);
3450 /* now we send a release to the ringing endpoint */
3451 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3452 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3453 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3454 message_put(message);
3456 /* we send a connect to the join with our caller id */
3457 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3458 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3459 message->param.connectinfo.present = e_callerinfo.present;
3460 message->param.connectinfo.screen = e_callerinfo.screen;
3461 message->param.connectinfo.itype = e_callerinfo.itype;
3462 message->param.connectinfo.ntype = e_callerinfo.ntype;
3463 message_put(message);
3465 /* we send a connect to our port with the remote callerid */
3466 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3467 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3468 message->param.connectinfo.present = eapp->e_callerinfo.present;
3469 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3470 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3471 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3472 /* handle restricted caller ids */
3473 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);
3474 /* display callerid if desired for extension */
3475 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));
3476 message_put(message);
3478 /* we send a connect to the audio path (not for vbox) */
3479 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3480 message->param.audiopath = 1;
3481 message_put(message);
3483 /* beeing paranoid, we make call update */
3484 trigger_work(&joinpbx->j_updatebridge);
3486 if (options.deb & DEBUG_EPOINT) {
3487 class Join *debug_c = join_first;
3488 class Endpoint *debug_e = epoint_first;
3489 class Port *debug_p = port_first;
3491 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3493 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3495 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3496 debug_c = debug_c->next;
3498 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3500 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3501 debug_e = debug_e->next;
3503 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3505 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3506 debug_p = debug_p->next;
3512 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3514 void EndpointAppPBX::join_join(void)
3517 struct lcr_msg *message;
3518 struct join_relation *our_relation, *other_relation;
3519 struct join_relation **our_relation_pointer, **other_relation_pointer;
3520 class Join *our_join, *other_join;
3521 class JoinPBX *our_joinpbx, *other_joinpbx;
3522 class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
3523 class Port *our_port, *other_port;
3524 class Pdss1 *our_pdss1, *other_pdss1;
3526 /* are we a candidate to join a join? */
3527 our_join = find_join_id(ea_endpoint->ep_join_id);
3529 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3532 if (our_join->j_type != JOIN_TYPE_PBX) {
3533 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3536 our_joinpbx = (class JoinPBX *)our_join;
3537 if (!ea_endpoint->ep_portlist) {
3538 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3541 if (!e_ext.number[0]) {
3542 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3545 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3547 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3550 if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
3551 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3554 our_pdss1 = (class Pdss1 *)our_port;
3556 /* find an endpoint that is on hold and has the same mISDNport that we are on */
3557 other_eapp = apppbx_first;
3559 if (other_eapp == this) {
3560 other_eapp = other_eapp->next;
3563 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);
3564 if (other_eapp->e_ext.number[0] /* has terminal */
3565 && other_eapp->ea_endpoint->ep_portlist /* has port */
3566 && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3567 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3568 if (other_port) { /* port still exists */
3569 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3570 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3571 other_pdss1 = (class Pdss1 *)other_port;
3572 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);
3573 if (other_pdss1->p_m_hold /* port is on hold */
3574 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3575 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3578 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3581 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3584 other_eapp = other_eapp->next;
3587 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3590 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3592 /* if we have the same join */
3593 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3594 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3597 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3599 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3602 if (other_join->j_type != JOIN_TYPE_PBX) {
3603 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3606 other_joinpbx = (class JoinPBX *)other_join;
3607 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3608 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3612 /* remove relation to endpoint for join on hold */
3613 other_relation = other_joinpbx->j_relation;
3614 other_relation_pointer = &other_joinpbx->j_relation;
3615 while(other_relation) {
3616 if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial) {
3617 /* detach other endpoint on hold */
3618 *other_relation_pointer = other_relation->next;
3619 FREE(other_relation, sizeof(struct join_relation));
3621 other_relation = *other_relation_pointer;
3622 other_eapp->ea_endpoint->ep_join_id = 0;
3626 /* change join/hold pointer of endpoint to the new join */
3627 temp_epoint = find_epoint_id(other_relation->epoint_id);
3629 if (temp_epoint->ep_join_id == other_join->j_serial)
3630 temp_epoint->ep_join_id = our_join->j_serial;
3633 other_relation_pointer = &other_relation->next;
3634 other_relation = other_relation->next;
3636 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
3638 /* join call relations */
3639 our_relation = our_joinpbx->j_relation;
3640 our_relation_pointer = &our_joinpbx->j_relation;
3641 while(our_relation) {
3642 our_relation_pointer = &our_relation->next;
3643 our_relation = our_relation->next;
3645 *our_relation_pointer = other_joinpbx->j_relation;
3646 other_joinpbx->j_relation = NULL;
3647 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3649 /* release endpoint on hold */
3650 message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3651 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3652 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3653 message_put(message);
3655 /* if we are not a partyline, we get partyline state from other join */
3656 our_joinpbx->j_partyline += other_joinpbx->j_partyline;
3658 /* remove empty join */
3660 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
3662 /* mixer must update */
3663 trigger_work(&our_joinpbx->j_updatebridge);
3665 /* we send a retrieve to that endpoint */
3666 // mixer will update the hold-state of the join and send it to the endpoints is changes
3668 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
3673 /* check if we have an external call
3674 * this is used to check for encryption ability
3676 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3678 struct join_relation *relation;
3680 class JoinPBX *joinpbx;
3681 class Endpoint *epoint;
3683 /* some paranoia check */
3684 if (!ea_endpoint->ep_portlist) {
3685 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3686 *errstr = "No Call";
3689 if (!e_ext.number[0]) {
3690 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3691 *errstr = "No Call";
3695 /* check if we have a join with 2 parties */
3696 join = find_join_id(ea_endpoint->ep_join_id);
3698 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3699 *errstr = "No Call";
3702 if (join->j_type != JOIN_TYPE_PBX) {
3703 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3704 *errstr = "No PBX Call";
3707 joinpbx = (class JoinPBX *)join;
3708 relation = joinpbx->j_relation;
3710 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
3711 *errstr = "No Call";
3714 if (!relation->next) {
3715 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
3716 *errstr = "No Call";
3719 if (relation->next->next) {
3720 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
3721 *errstr = "Err: Conference";
3724 if (relation->epoint_id == ea_endpoint->ep_serial) {
3725 relation = relation->next;
3726 if (relation->epoint_id == ea_endpoint->ep_serial) {
3727 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
3728 *errstr = "Software Error";
3733 /* check remote port for external call */
3734 epoint = find_epoint_id(relation->epoint_id);
3736 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
3737 *errstr = "No Call";
3740 if (!epoint->ep_portlist) {
3741 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
3742 *errstr = "No Call";
3745 *port = find_port_id(epoint->ep_portlist->port_id);
3747 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
3748 *errstr = "No Call";
3751 if (((*port)->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) { /* port is not external isdn */
3752 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
3753 *errstr = "No Ext Call";
3756 if ((*port)->p_state != PORT_STATE_CONNECT) {
3757 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
3758 *errstr = "No Ext Connect";
3764 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
3766 const char *logtext = "unknown";
3769 switch(message_type) {
3771 trace_header("SETUP", dir);
3772 if (dir == DIRECTION_OUT)
3773 add_trace("to", NULL, "CH(%lu)", port_id);
3774 if (dir == DIRECTION_IN)
3775 add_trace("from", NULL, "CH(%lu)", port_id);
3776 if (param->setup.callerinfo.extension[0])
3777 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
3778 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
3779 switch(param->setup.callerinfo.present) {
3780 case INFO_PRESENT_RESTRICTED:
3781 add_trace("caller id", "present", "restricted");
3783 case INFO_PRESENT_ALLOWED:
3784 add_trace("caller id", "present", "allowed");
3787 add_trace("caller id", "present", "not available");
3789 if (param->setup.callerinfo.ntype2) {
3790 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
3791 switch(param->setup.callerinfo.present) {
3792 case INFO_PRESENT_RESTRICTED:
3793 add_trace("caller id2", "present", "restricted");
3795 case INFO_PRESENT_ALLOWED:
3796 add_trace("caller id2", "present", "allowed");
3799 add_trace("caller id2", "present", "not available");
3802 if (param->setup.redirinfo.id[0]) {
3803 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
3804 switch(param->setup.redirinfo.present) {
3805 case INFO_PRESENT_RESTRICTED:
3806 add_trace("redir'ing", "present", "restricted");
3808 case INFO_PRESENT_ALLOWED:
3809 add_trace("redir'ing", "present", "allowed");
3812 add_trace("redir'ing", "present", "not available");
3815 if (param->setup.dialinginfo.id[0])
3816 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
3817 if (param->setup.dialinginfo.keypad[0])
3818 add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
3819 if (param->setup.dialinginfo.display[0])
3820 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
3821 if (param->setup.dialinginfo.sending_complete)
3822 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
3826 case MESSAGE_OVERLAP:
3827 trace_header("SETUP ACKNOWLEDGE", dir);
3828 if (dir == DIRECTION_OUT)
3829 add_trace("to", NULL, "CH(%lu)", port_id);
3830 if (dir == DIRECTION_IN)
3831 add_trace("from", NULL, "CH(%lu)", port_id);
3835 case MESSAGE_PROCEEDING:
3836 trace_header("PROCEEDING", dir);
3837 if (dir == DIRECTION_OUT)
3838 add_trace("to", NULL, "CH(%lu)", port_id);
3839 if (dir == DIRECTION_IN)
3840 add_trace("from", NULL, "CH(%lu)", port_id);
3844 case MESSAGE_ALERTING:
3845 trace_header("ALERTING", dir);
3846 if (dir == DIRECTION_OUT)
3847 add_trace("to", NULL, "CH(%lu)", port_id);
3848 if (dir == DIRECTION_IN)
3849 add_trace("from", NULL, "CH(%lu)", port_id);
3853 case MESSAGE_CONNECT:
3854 trace_header("CONNECT", dir);
3855 if (dir == DIRECTION_OUT)
3856 add_trace("to", NULL, "CH(%lu)", port_id);
3857 if (dir == DIRECTION_IN)
3858 add_trace("from", NULL, "CH(%lu)", port_id);
3859 if (param->connectinfo.extension[0])
3860 add_trace("extension", NULL, "%s", param->connectinfo.extension);
3861 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
3862 switch(param->connectinfo.present) {
3863 case INFO_PRESENT_RESTRICTED:
3864 add_trace("connect id", "present", "restricted");
3866 case INFO_PRESENT_ALLOWED:
3867 add_trace("connect id", "present", "allowed");
3870 add_trace("connect id", "present", "not available");
3872 if (param->connectinfo.display[0])
3873 add_trace("display", NULL, "%s", param->connectinfo.display);
3877 case MESSAGE_DISCONNECT:
3878 case MESSAGE_RELEASE:
3879 if (message_type == MESSAGE_DISCONNECT)
3880 trace_header("DISCONNECT", dir);
3882 trace_header("RELEASE", dir);
3883 if (dir == DIRECTION_OUT)
3884 add_trace("to", NULL, "CH(%lu)", port_id);
3885 if (dir == DIRECTION_IN)
3886 add_trace("from", NULL, "CH(%lu)", port_id);
3887 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
3888 switch(param->disconnectinfo.location) {
3890 add_trace("cause", "location", "0-User");
3892 case LOCATION_PRIVATE_LOCAL:
3893 add_trace("cause", "location", "1-Local-PBX");
3895 case LOCATION_PUBLIC_LOCAL:
3896 add_trace("cause", "location", "2-Local-Exchange");
3898 case LOCATION_TRANSIT:
3899 add_trace("cause", "location", "3-Transit");
3901 case LOCATION_PUBLIC_REMOTE:
3902 add_trace("cause", "location", "4-Remote-Exchange");
3904 case LOCATION_PRIVATE_REMOTE:
3905 add_trace("cause", "location", "5-Remote-PBX");
3907 case LOCATION_INTERNATIONAL:
3908 add_trace("cause", "location", "7-International-Exchange");
3910 case LOCATION_BEYOND:
3911 add_trace("cause", "location", "10-Beyond-Interworking");
3914 add_trace("cause", "location", "%d", param->disconnectinfo.location);
3916 if (param->disconnectinfo.display[0])
3917 add_trace("display", NULL, "%s", param->disconnectinfo.display);
3921 case MESSAGE_NOTIFY:
3922 switch(param->notifyinfo.notify) {
3927 logtext = "USER_SUSPENDED";
3930 logtext = "BEARER_SERVICE_CHANGED";
3933 logtext = "USER_RESUMED";
3936 logtext = "CONFERENCE_ESTABLISHED";
3939 logtext = "CONFERENCE_DISCONNECTED";
3942 logtext = "OTHER_PARTY_ADDED";
3945 logtext = "ISOLATED";
3948 logtext = "REATTACHED";
3951 logtext = "OTHER_PARTY_ISOLATED";
3954 logtext = "OTHER_PARTY_REATTACHED";
3957 logtext = "OTHER_PARTY_SPLIT";
3960 logtext = "OTHER_PARTY_DISCONNECTED";
3963 logtext = "CONFERENCE_FLOATING";
3966 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
3969 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
3972 logtext = "CALL_IS_A_WAITING_CALL";
3975 logtext = "DIVERSION_ACTIVATED";
3978 logtext = "RESERVED_CT_1";
3981 logtext = "RESERVED_CT_2";
3984 logtext = "REVERSE_CHARGING";
3987 logtext = "REMOTE_HOLD";
3990 logtext = "REMOTE_RETRIEVAL";
3993 logtext = "CALL_IS_DIVERTING";
3996 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4000 trace_header("NOTIFY", dir);
4001 if (dir == DIRECTION_OUT)
4002 add_trace("to", NULL, "CH(%lu)", port_id);
4003 if (dir == DIRECTION_IN)
4004 add_trace("from", NULL, "CH(%lu)", port_id);
4005 if (param->notifyinfo.notify)
4006 add_trace("indicator", NULL, "%s", logtext);
4007 if (param->notifyinfo.id[0]) {
4008 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4009 switch(param->notifyinfo.present) {
4010 case INFO_PRESENT_RESTRICTED:
4011 add_trace("redir'on", "present", "restricted");
4013 case INFO_PRESENT_ALLOWED:
4014 add_trace("redir'on", "present", "allowed");
4017 add_trace("redir'on", "present", "not available");
4020 if (param->notifyinfo.display[0])
4021 add_trace("display", NULL, "%s", param->notifyinfo.display);
4025 case MESSAGE_PROGRESS:
4026 switch(param->progressinfo.progress) {
4028 logtext = "Call is not end to end ISDN";
4031 logtext = "Destination address is non-ISDN";
4034 logtext = "Origination address is non-ISDN";
4037 logtext = "Call has returned to the ISDN";
4040 logtext = "In-band info or pattern available";
4043 SPRINT(buffer, "%d", param->progressinfo.progress);
4047 trace_header("PROGRESS", dir);
4048 if (dir == DIRECTION_OUT)
4049 add_trace("to", NULL, "CH(%lu)", port_id);
4050 if (dir == DIRECTION_IN)
4051 add_trace("from", NULL, "CH(%lu)", port_id);
4052 add_trace("indicator", NULL, "%s", logtext);
4053 switch(param->progressinfo.location) {
4055 add_trace("cause", "location", "0-User");
4057 case LOCATION_PRIVATE_LOCAL:
4058 add_trace("cause", "location", "1-Local-PBX");
4060 case LOCATION_PUBLIC_LOCAL:
4061 add_trace("cause", "location", "2-Local-Exchange");
4063 case LOCATION_TRANSIT:
4064 add_trace("cause", "location", "3-Transit");
4066 case LOCATION_PUBLIC_REMOTE:
4067 add_trace("cause", "location", "4-Remote-Exchange");
4069 case LOCATION_PRIVATE_REMOTE:
4070 add_trace("cause", "location", "5-Remote-PBX");
4072 case LOCATION_INTERNATIONAL:
4073 add_trace("cause", "location", "7-International-Exchange");
4075 case LOCATION_BEYOND:
4076 add_trace("cause", "location", "10-Beyond-Interworking");
4079 add_trace("cause", "location", "%d", param->progressinfo.location);
4084 case MESSAGE_INFORMATION:
4085 trace_header("INFORMATION", dir);
4086 if (dir == DIRECTION_OUT)
4087 add_trace("to", NULL, "CH(%lu)", port_id);
4088 if (dir == DIRECTION_IN)
4089 add_trace("from", NULL, "CH(%lu)", port_id);
4090 if (param->information.id[0])
4091 add_trace("dialing", NULL, "%s", param->information.id);
4092 if (param->information.display[0])
4093 add_trace("display", NULL, "%s", param->information.display);
4094 if (param->information.sending_complete)
4095 add_trace("complete", NULL, "true", param->information.sending_complete);
4099 case MESSAGE_FACILITY:
4100 trace_header("FACILITY", dir);
4101 if (dir == DIRECTION_OUT)
4102 add_trace("to", NULL, "CH(%lu)", port_id);
4103 if (dir == DIRECTION_IN)
4104 add_trace("from", NULL, "CH(%lu)", port_id);
4109 trace_header("TONE", dir);
4110 if (dir == DIRECTION_OUT)
4111 add_trace("to", NULL, "CH(%lu)", port_id);
4112 if (dir == DIRECTION_IN)
4113 add_trace("from", NULL, "CH(%lu)", port_id);
4114 if (param->tone.name[0]) {
4115 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4116 add_trace("name", NULL, "%s", param->tone.name);
4118 add_trace("off", NULL, NULL);
4122 case MESSAGE_SUSPEND:
4123 case MESSAGE_RESUME:
4124 if (message_type == MESSAGE_SUSPEND)
4125 trace_header("SUSPEND", dir);
4127 trace_header("RESUME", dir);
4128 if (dir == DIRECTION_OUT)
4129 add_trace("to", NULL, "CH(%lu)", port_id);
4130 if (dir == DIRECTION_IN)
4131 add_trace("from", NULL, "CH(%lu)", port_id);
4132 if (param->parkinfo.len)
4133 add_trace("length", NULL, "%d", param->parkinfo.len);
4138 case MESSAGE_BCHANNEL:
4139 trace_header("BCHANNEL", dir);
4140 switch(param->bchannel.type) {
4141 case BCHANNEL_REQUEST:
4142 add_trace("type", NULL, "request");
4144 case BCHANNEL_ASSIGN:
4145 add_trace("type", NULL, "assign");
4147 case BCHANNEL_ASSIGN_ACK:
4148 add_trace("type", NULL, "assign_ack");
4150 case BCHANNEL_REMOVE:
4151 add_trace("type", NULL, "remove");
4153 case BCHANNEL_REMOVE_ACK:
4154 add_trace("type", NULL, "remove_ack");
4157 if (param->bchannel.addr)
4158 add_trace("address", NULL, "%x", param->bchannel.addr);
4164 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4168 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4170 struct lcr_msg *message;
4174 if (!portlist->port_id)
4177 if (!e_connectedmode) {
4178 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4179 message->param.disconnectinfo.cause = cause;
4180 message->param.disconnectinfo.location = location;
4182 SCPY(message->param.disconnectinfo.display, display);
4184 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4186 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4188 SCPY(message->param.notifyinfo.display, display);
4190 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4192 message_put(message);
4193 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);