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)],
615 struct port_settings port_settings;
619 struct admin_list *admin;
621 int mode = B_MODE_TRANSPARENT;
623 /* set bchannel mode */
624 mode = e_capainfo.source_mode;
626 /* create settings for creating port */
627 memset(&port_settings, 0, sizeof(port_settings));
629 SCPY(port_settings.tones_dir, e_ext.tones_dir);
631 SCPY(port_settings.tones_dir, options.tones_dir);
632 port_settings.no_seconds = e_ext.no_seconds;
634 /* 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 */
636 /* check what dialinginfo.itype we got */
637 switch(e_dialinginfo.itype) {
638 /* *********************** call to extension or vbox */
639 case INFO_ITYPE_ISDN_EXTENSION:
640 /* check if we deny incoming calls when we use an extension */
641 if (e_ext.noknocking) {
642 atemp = apppbx_first;
645 if (!strcmp(atemp->e_ext.number, e_ext.number))
650 PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
651 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
652 return; /* must exit here */
655 /* FALL THROUGH !!!! */
656 case INFO_ITYPE_VBOX:
657 /* get dialed extension's info */
658 // SCPY(exten, e_dialinginfo.id);
659 // if (strchr(exten, ','))
660 // *strchr(exten, ',') = '\0';
661 // if (!read_extension(&e_ext, exten))
662 if (!read_extension(&e_ext, e_dialinginfo.id)) {
663 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
664 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
665 return; /* must exit here */
667 e_dialinginfo.sending_complete = 1;
669 if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
670 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
675 /* string from unconditional call forward (cfu) */
678 /* present to forwarded party */
679 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
680 e_callerinfo.present = INFO_PRESENT_ALLOWED;
682 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
686 /* string from busy call forward (cfb) */
689 class EndpointAppPBX *checkapp = apppbx_first;
691 if (checkapp != this) { /* any other endpoint except our own */
692 if (!strcmp(checkapp->e_ext.number, e_ext.number)) {
693 /* present to forwarded party */
694 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
695 e_callerinfo.present = INFO_PRESENT_ALLOWED;
697 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH))
701 checkapp = checkapp->next;
705 /* string from no-response call forward (cfnr) */
708 /* when cfnr is done, out_setup() will setup the call */
710 /* present to forwarded party */
711 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
712 e_callerinfo.present = INFO_PRESENT_ALLOWED;
716 if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
717 schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
718 schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* call one second after release */
719 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);
723 /* call to all internal interfaces */
724 p = e_ext.interfaces;
725 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
729 while(*p!=',' && *p!='\0')
734 /* search interface */
735 interface = hunt_interface(ifname);
737 trace_header("INTERFACE (not found)", DIRECTION_NONE);
738 add_trace("interface", NULL, "%s", ifname);
742 /* found interface */
743 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
744 if (interface->remote) {
747 if (admin->remote_name[0] && !strcmp(admin->remote_name, interface->remote_app))
752 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
753 add_trace("application", NULL, "%s", interface->remote_app);
757 SPRINT(portname, "%s-%d-out", interface->name, 0);
758 port = new Premote(PORT_TYPE_REMOTE_OUT, portname, &port_settings, interface, admin->sock);
759 earlyb = (interface->is_earlyb == IS_YES);
762 if (interface->gsm_bs) {
763 SPRINT(portname, "%s-%d-out", interface->name, 0);
764 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
765 earlyb = (interface->is_earlyb == IS_YES);
769 if (interface->gsm_ms) {
770 SPRINT(portname, "%s-%d-out", interface->name, 0);
771 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
772 earlyb = (interface->is_earlyb == IS_YES);
776 if (interface->sip) {
777 SPRINT(portname, "%s-%d-out", interface->name, 0);
778 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
779 earlyb = (interface->is_earlyb == IS_YES);
784 /* hunt for mISDNport and create Port */
785 mISDNport = hunt_port(ifname, &channel);
787 trace_header("INTERFACE (busy)", DIRECTION_NONE);
788 add_trace("interface", NULL, "%s", ifname);
793 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
796 port = ss5_hunt_line(mISDNport);
799 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, channel, mISDNport->ifport->channel_force, mode);
800 earlyb = mISDNport->earlyb;
802 trace_header("INTERFACE (has no function)", DIRECTION_NONE);
803 add_trace("interface", NULL, "%s", ifname);
809 FATAL("Failed to create Port instance\n");
810 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
811 memset(&dialinginfo, 0, sizeof(dialinginfo));
812 SCPY(dialinginfo.id, e_dialinginfo.id);
813 dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
814 dialinginfo.ntype = e_dialinginfo.ntype;
815 /* create port_list relation */
816 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
818 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
820 goto check_anycall_intern;
823 if (e_callerinfo.id[0] && e_ext.display_name) {
824 dirname = parse_directory(e_callerinfo.id, e_callerinfo.ntype);
826 SCPY(e_callerinfo.name, dirname);
828 // dss1 = (class Pdss1 *)port;
830 //printf("INTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
831 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
832 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
833 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
834 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
835 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
836 memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
837 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
838 //terminal if (e_dialinginfo.id)
839 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
840 /* handle restricted caller ids */
841 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);
842 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);
843 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);
844 /* display callerid if desired for extension */
845 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));
846 //printf("\n\ndisplay = %s\n\n\n",message->param.setup.callerinfo.display);
847 /* use cnip, if enabld */
848 // if (!e_ext.centrex)
849 // message->param.setup.callerinfo.name[0] = '\0';
850 /* screen clip if prefix is required */
851 if (message->param.setup.callerinfo.id[0] && e_ext.clip_prefix[0]) {
852 SCPY(message->param.setup.callerinfo.id, e_ext.clip_prefix);
853 SCAT(message->param.setup.callerinfo.id, numberrize_callerinfo(e_callerinfo.id,e_callerinfo.ntype, options.national, options.international));
854 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
856 if (message->param.setup.callerinfo.id2[0] && e_ext.clip_prefix[0]) {
857 SCPY(message->param.setup.callerinfo.id2, e_ext.clip_prefix);
858 SCAT(message->param.setup.callerinfo.id2, numberrize_callerinfo(e_callerinfo.id2,e_callerinfo.ntype2, options.national, options.international));
859 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_UNKNOWN;
861 /* use internal caller id */
862 if (e_callerinfo.extension[0] && (message->param.setup.callerinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
863 SCPY(message->param.setup.callerinfo.id, e_callerinfo.extension);
864 message->param.setup.callerinfo.ntype = INFO_NTYPE_UNKNOWN;
865 message->param.setup.callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
867 message_put(message);
868 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
872 /* string from parallel call forward (cfp) */
875 if (e_ext.anon_ignore && e_callerinfo.id[0]) {
876 e_callerinfo.present = INFO_PRESENT_ALLOWED;
877 e_callerinfo.present2 = INFO_PRESENT_ALLOWED;
881 vbox_only: /* entry point for answering machine only */
882 cfu_only: /* entry point for cfu */
883 cfb_only: /* entry point for cfb */
884 cfnr_only: /* entry point for cfnr */
885 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call extension %s for external destiantion(s) '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
889 /* only if vbox should be dialed, and terminal is given */
890 if (!strcmp(p, "vbox") && e_ext.number[0]) {
891 /* go to the end of p */
894 /* answering vbox call */
895 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) answering machine\n", ea_endpoint->ep_serial);
897 if (!(port = new VBoxPort(PORT_TYPE_VBOX_OUT, &port_settings)))
898 FATAL("No memory for VBOX Port instance\n");
899 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) allocated port %s\n", ea_endpoint->ep_serial, port->p_name);
900 UCPY(cfp, e_ext.number); /* cfp or any other direct forward/vbox */
903 while(*p!=',' && *p!='\0')
908 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
910 /* hunt for mISDNport and create Port */
911 mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
913 /* creating EXTERNAL port*/
914 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
917 port = ss5_hunt_line(mISDNport);
920 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, channel, mISDNport->ifport->channel_force, mode);
922 FATAL("No memory for Port instance\n");
923 earlyb = mISDNport->earlyb;
928 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
929 add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
934 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) no port found or created, which is idle.\n", ea_endpoint->ep_serial);
935 goto check_anycall_intern;
937 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found or created port %s\n", ea_endpoint->ep_serial, port->p_name);
938 memset(&dialinginfo, 0, sizeof(dialinginfo));
939 SCPY(dialinginfo.id, cfp);
940 dialinginfo.itype = INFO_ITYPE_ISDN;
941 dialinginfo.ntype = e_dialinginfo.ntype;
942 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
944 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
946 goto check_anycall_intern;
948 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
949 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
950 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
951 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
952 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
953 /* if clip is hidden */
954 if (e_ext.clip==CLIP_HIDE && port->p_type!=PORT_TYPE_VBOX_OUT) {
955 SCPY(message->param.setup.callerinfo.id, e_ext.callerid);
956 SCPY(message->param.setup.callerinfo.extension, e_ext.number);
957 message->param.setup.callerinfo.ntype = e_ext.callerid_type;
958 message->param.setup.callerinfo.present = e_ext.callerid_present;
959 message->param.setup.callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
961 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
962 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
963 //terminal if (e_dialinginfo.id)
964 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
965 /* handle restricted caller ids */
966 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);
967 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);
968 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);
969 /* display callerid if desired for extension */
970 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));
971 message_put(message);
972 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
976 check_anycall_intern:
977 /* now we have all ports created */
979 trace_header("INTERFACE (no extension's interface)", DIRECTION_NONE);
981 if (!ea_endpoint->ep_join_id)
983 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
984 return; /* must exit here */
988 /* *********************** external call */
990 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
991 /* call to extenal interfaces */
992 if (e_dialinginfo.keypad[0])
993 number_p = e_dialinginfo.keypad;
995 number_p = e_dialinginfo.id;
998 while(*number_p!=',' && *number_p!='\0')
999 SCCAT(number, *number_p++);
1000 if (*number_p == ',')
1004 ifname_p = e_dialinginfo.interfaces;
1005 if (*ifname_p == '+')
1010 while(*ifname_p!=',' && *ifname_p!='\0')
1011 SCCAT(ifname, *ifname_p++);
1012 if (*ifname_p == ',')
1014 /* found interface name */
1016 /* search interface */
1017 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, ifname[0]?ifname:"any interface");
1018 interface = hunt_interface(ifname[0]?ifname:NULL);
1020 trace_header("INTERFACE (not found)", DIRECTION_NONE);
1021 add_trace("interface", NULL, "%s", ifname);
1025 /* found interface */
1026 if (interface->remote) {
1027 admin = admin_first;
1029 if (admin->remote_name[0] && !strcmp(admin->remote_name, interface->remote_app))
1031 admin = admin->next;
1034 trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
1035 add_trace("application", NULL, "%s", interface->remote_app);
1039 SPRINT(portname, "%s-%d-out", interface->name, 0);
1040 port = new Premote(PORT_TYPE_REMOTE_OUT, portname, &port_settings, interface, admin->sock);
1041 earlyb = (interface->is_earlyb == IS_YES);
1044 if (interface->gsm_bs) {
1045 SPRINT(portname, "%s-%d-out", interface->name, 0);
1046 port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
1047 earlyb = (interface->is_earlyb == IS_YES);
1051 if (interface->gsm_ms) {
1052 SPRINT(portname, "%s-%d-out", interface->name, 0);
1053 port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
1054 earlyb = (interface->is_earlyb == IS_YES);
1058 if (interface->sip) {
1059 SPRINT(portname, "%s-%d-out", interface->name, 0);
1060 port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
1061 earlyb = (interface->is_earlyb == IS_YES);
1066 /* hunt for mISDNport and create Port */
1067 mISDNport = hunt_port(ifname[0]?ifname:NULL, &channel);
1069 trace_header("INTERFACE (too busy)", DIRECTION_NONE);
1070 add_trace("interface", NULL, "%s", ifname[0]?ifname:"any interface");
1074 /* creating EXTERNAL port*/
1075 SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
1079 port = ss5_hunt_line(mISDNport);
1082 port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, mISDNport->ifport->interface, channel, mISDNport->ifport->channel_force, mode);
1083 earlyb = mISDNport->earlyb;
1085 trace_header("INTERFACE (has no function)", DIRECTION_NONE);
1086 add_trace("interface", NULL, "%s", ifname);
1092 FATAL("No memory for Port instance\n");
1093 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
1094 memset(&dialinginfo, 0, sizeof(dialinginfo));
1095 if (e_dialinginfo.keypad[0])
1096 SCPY(dialinginfo.keypad, number);
1098 SCPY(dialinginfo.id, number);
1099 dialinginfo.itype = INFO_ITYPE_ISDN;
1100 dialinginfo.ntype = e_dialinginfo.ntype;
1101 dialinginfo.sending_complete = e_dialinginfo.sending_complete;
1102 portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
1104 PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
1108 //printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
1109 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
1110 memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
1111 memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
1112 memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
1113 memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
1114 memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
1115 //terminal SCPY(message->param.setup.from_terminal, e_ext.number);
1116 //terminal if (e_dialinginfo.id)
1117 //terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
1118 /* handle restricted caller ids */
1119 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);
1120 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);
1121 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);
1122 /* display callerid if desired for extension */
1123 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));
1124 message_put(message);
1125 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1128 /* found an interface
1129 * continue only if + is given, so every interface is calles parallel */
1130 if (e_dialinginfo.interfaces[0] != '+')
1132 } while (*ifname_p);
1135 /* now we have all ports created */
1137 trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
1139 if (!ea_endpoint->ep_join_id)
1141 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1142 return; /* must exit here */
1149 int action_timeout(struct lcr_timer *timer, void *instance, int index)
1151 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1153 if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
1156 unsched_timer(&ea->e_redial_timeout);
1157 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
1158 ea->e_multipoint_cause = 0;
1159 ea->e_multipoint_location = 0;
1160 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1161 ea->e_join_pattern = 0;
1162 ea->process_dialing(1);
1163 /* we must exit, because our endpoint might be gone */
1168 int match_timeout(struct lcr_timer *timer, void *instance, int index)
1170 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1172 if (!ea->e_action) {
1173 unsched_timer(&ea->e_redial_timeout);
1174 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
1175 ea->process_dialing(0);
1176 /* we must exit, because our endpoint might be gone */
1182 int redial_timeout(struct lcr_timer *timer, void *instance, int index)
1184 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1186 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
1188 ea->new_state(EPOINT_STATE_OUT_SETUP);
1189 /* call special setup routine */
1195 int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
1197 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1199 /* leave power dialing on */
1200 ea->e_powerdial_on = 1;
1201 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
1204 ea->e_ruleset = ruleset_main;
1206 ea->e_rule = ea->e_ruleset->rule_first;
1207 ea->e_action = NULL;
1208 ea->new_state(EPOINT_STATE_IN_OVERLAP);
1209 ea->process_dialing(0);
1214 int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
1216 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1217 struct port_list *portlist;
1218 struct lcr_msg *message;
1220 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
1222 /* release all ports */
1223 while((portlist = ea->ea_endpoint->ep_portlist)) {
1224 message = message_create(ea->ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1225 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
1226 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1227 message_put(message);
1228 ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1229 ea->ea_endpoint->free_portlist(portlist);
1232 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1233 message->param.audiopath = 0;
1234 message_put(message);
1235 /* indicate no patterns */
1236 message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1237 message_put(message);
1238 /* set setup state, since we have no response from the new join */
1239 ea->new_state(EPOINT_STATE_OUT_SETUP);
1244 int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
1246 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1248 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);
1254 int callback_timeout(struct lcr_timer *timer, void *instance, int index)
1256 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1258 if (ea->e_state == EPOINT_STATE_IDLE) {
1259 /* epoint is idle, check callback */
1260 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
1261 ea->new_state(EPOINT_STATE_OUT_SETUP);
1268 int password_timeout(struct lcr_timer *timer, void *instance, int index)
1270 class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
1272 if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
1273 struct port_list *portlist;
1275 ea->e_ruleset = ruleset_main;
1277 ea->e_rule = ea->e_ruleset->rule_first;
1278 ea->e_action = NULL;
1279 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
1280 ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
1282 ea->e_connectedmode = 0;
1284 ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
1285 portlist = ea->ea_endpoint->ep_portlist;
1287 ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
1288 ea->set_tone(portlist, "cause_10");
1295 /* doing a hookflash */
1296 void EndpointAppPBX::hookflash(void)
1301 /* be sure that we are active */
1303 e_tx_state = NOTIFY_STATE_ACTIVE;
1305 trace_header("HOOKFLASH DTMF", DIRECTION_NONE);
1307 if (ea_endpoint->ep_use > 1) {
1308 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot hooflash while child process is running.\n", ea_endpoint->ep_serial);
1311 /* dialtone after pressing the hash key */
1312 process_hangup(e_join_cause, e_join_location);
1313 e_multipoint_cause = 0;
1314 e_multipoint_location = 0;
1315 port = find_port_id(ea_endpoint->ep_portlist->port_id);
1317 port->set_echotest(0);
1319 if (ea_endpoint->ep_join_id) {
1320 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
1322 e_ruleset = ruleset_main;
1324 e_rule = e_ruleset->rule_first;
1326 new_state(EPOINT_STATE_IN_OVERLAP);
1327 e_connectedmode = 1;
1328 SCPY(e_dialinginfo.id, e_ext.prefix);
1329 e_extdialing = e_dialinginfo.id;
1331 if (e_dialinginfo.id[0]) {
1332 set_tone(ea_endpoint->ep_portlist, "dialing");
1335 set_tone(ea_endpoint->ep_portlist, "dialpbx");
1343 /* messages from port
1345 /* port MESSAGE_SETUP */
1346 void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, union parameter *param)
1348 struct lcr_msg *message;
1350 int writeext; /* flags need to write extension after modification */
1353 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1355 portlist->port_type = param->setup.port_type;
1356 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
1357 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
1358 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
1359 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
1360 memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
1362 /* convert (inter-)national number type */
1363 SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
1364 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1366 // e_dtmf = param->setup.dtmf;
1367 /* screen incoming caller id */
1368 if (e_callerinfo.interface[0]) {
1369 do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, e_callerinfo.interface);
1370 do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, e_callerinfo.interface);
1371 do_screen(0, e_redirinfo.id, sizeof(e_redirinfo.id), &e_redirinfo.ntype, &e_redirinfo.present, e_callerinfo.interface);
1374 /* process extension */
1375 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1376 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is extension\n", ea_endpoint->ep_serial);
1377 /* port makes call from extension */
1378 SCPY(e_callerinfo.extension, e_callerinfo.id);
1379 SCPY(e_ext.number, e_callerinfo.extension);
1380 SCPY(e_extension_interface, e_callerinfo.interface);
1382 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming call is external or voip\n", ea_endpoint->ep_serial);
1385 if (e_callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION) {
1386 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1388 /* get extension's info about caller */
1389 if (!read_extension(&e_ext, e_ext.number)) {
1390 /* extension doesn't exist */
1391 trace_header("EXTENSION (not created)", DIRECTION_IN);
1392 add_trace("extension", NULL, "%s", e_ext.number);
1394 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1395 new_state(EPOINT_STATE_OUT_DISCONNECT);
1396 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1397 e_ext.number[0] = '\0'; /* no terminal */
1402 /* put prefix (next) in front of e_dialinginfo.id */
1403 if (e_ext.next[0]) {
1404 SPRINT(buffer, "%s%s", e_ext.next, e_dialinginfo.id);
1405 SCPY(e_dialinginfo.id, buffer);
1406 e_ext.next[0] = '\0';
1408 } else if (e_ext.prefix[0]) {
1409 SPRINT(buffer, "%s%s", e_ext.prefix, e_dialinginfo.id);
1410 SCPY(e_dialinginfo.id, buffer);
1413 /* screen caller id by extension's config */
1414 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1416 SCPY(e_callerinfo.name, e_ext.name);
1417 /* use caller id (or if exist: id_next_call) for this call */
1418 if (e_ext.id_next_call_present >= 0) {
1419 SCPY(e_callerinfo.id, e_ext.id_next_call);
1420 /* if we restrict the pesentation */
1421 if (e_ext.id_next_call_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1422 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1423 else e_callerinfo.present = e_ext.id_next_call_present;
1424 e_callerinfo.ntype = e_ext.id_next_call_type;
1425 e_ext.id_next_call_present = -1;
1428 SCPY(e_callerinfo.id, e_ext.callerid);
1429 /* if we restrict the pesentation */
1430 if (e_ext.callerid_present==INFO_PRESENT_ALLOWED && e_callerinfo.present==INFO_PRESENT_RESTRICTED)
1431 e_callerinfo.present = INFO_PRESENT_RESTRICTED;
1432 else e_callerinfo.present = e_ext.callerid_present;
1433 e_callerinfo.ntype = e_ext.callerid_type;
1435 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1437 /* extension is written */
1439 write_extension(&e_ext, e_ext.number);
1441 /* set volume of rx and tx */
1442 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
1443 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1444 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1445 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1446 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1447 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1448 message_put(message);
1451 /* start recording if enabled */
1452 if (e_ext.record!=CODEC_OFF && (e_capainfo.bearer_capa==INFO_BC_SPEECH || e_capainfo.bearer_capa==INFO_BC_AUDIO)) {
1453 /* check if we are a terminal */
1454 if (e_ext.number[0] == '\0')
1455 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
1457 port = find_port_id(portlist->port_id);
1459 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
1463 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call from external port\n", ea_endpoint->ep_serial);
1464 /* no terminal identification */
1465 e_ext.number[0] = '\0';
1466 e_extension_interface[0] = '\0';
1467 memset(&e_ext, 0, sizeof(e_ext));
1468 e_ext.rights = 4; /* right to dial internat */
1472 e_ruleset = ruleset_main;
1474 e_rule = e_ruleset->rule_first;
1476 e_extdialing = e_dialinginfo.id;
1477 new_state(EPOINT_STATE_IN_SETUP);
1478 if (e_dialinginfo.id[0]) {
1479 set_tone(portlist, "dialing");
1481 if (e_ext.number[0])
1482 set_tone(portlist, "dialpbx");
1484 set_tone(portlist, "dialtone");
1487 if (e_state == EPOINT_STATE_IN_SETUP) {
1488 /* request MORE info, if not already at higher state */
1489 new_state(EPOINT_STATE_IN_OVERLAP);
1490 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_OVERLAP);
1491 message_put(message);
1492 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
1496 /* port MESSAGE_INFORMATION */
1497 void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
1499 struct lcr_msg *message;
1501 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1503 /* ignore information message without digit information */
1504 if (!param->information.id[0])
1509 /* turn off dtmf detection, in case dtmf is sent with keypad information */
1511 trace_header("DTMF (disabling due to keypad)", DIRECTION_IN);
1516 /* if vbox_play is done, the information are just used as they come */
1518 if (e_action->index == ACTION_VBOX_PLAY) {
1519 /* concat dialing string */
1520 SCAT(e_dialinginfo.id, param->information.id);
1525 /* keypad when disconnect but in connected mode */
1526 if (e_state==EPOINT_STATE_OUT_DISCONNECT && e_connectedmode) {
1527 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received after disconnect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1528 /* processing keypad function */
1529 if (param->information.id[0] == '0') {
1535 /* keypad when connected */
1536 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1537 if (e_enablekeypad) {
1538 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1539 memcpy(&message->param, param, sizeof(union parameter));
1540 message_put(message);
1544 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
1545 /* processing keypad function */
1546 if (param->information.id[0] == '0') {
1549 if (param->information.id[0])
1550 keypad_function(param->information.id[0]);
1552 if (e_ext.number[0])
1553 trace_header("KEYPAD (not enabled by extension's settings)", DIRECTION_IN);
1555 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1560 if (e_state != EPOINT_STATE_IN_OVERLAP) {
1561 if (e_ext.number[0])
1562 trace_header("KEYPAD (ignored, not connected and not dialing)", DIRECTION_IN);
1564 trace_header("KEYPAD (not enabled for external interfaces)", DIRECTION_IN);
1568 if (!param->information.id[0])
1570 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1571 set_tone(portlist, "dialing");
1574 if (e_action->index==ACTION_OUTDIAL
1575 || e_action->index==ACTION_EXTERNAL) {
1577 set_tone(portlist, "dialing");
1578 else if (!e_extdialing[0])
1579 set_tone(portlist, "dialing");
1581 /* concat dialing string */
1582 SCAT(e_dialinginfo.id, param->information.id);
1586 /* port MESSAGE_DTMF */
1587 void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
1590 struct lcr_msg *message;
1594 /* only if dtmf detection is enabled */
1596 trace_header("DTMF (disabled)", DIRECTION_IN);
1600 trace_header("DTMF", DIRECTION_IN);
1601 add_trace("digit", NULL, "%c", param->dtmf);
1605 NOTE: vbox is now handled due to overlap state
1606 /* if vbox_play is done, the dtmf digits are just used as they come */
1608 if (e_action->index == ACTION_VBOX_PLAY) {
1609 /* concat dialing string */
1610 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1611 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1612 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1615 /* continue to process *X# sequences */
1619 /* check for *X# sequence */
1620 if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
1621 if (e_enablekeypad) {
1622 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1623 memcpy(&message->param, param, sizeof(union parameter));
1624 message_put(message);
1627 if (e_dtmf_time+3 < now) {
1628 /* the last digit was too far in the past to be a sequence */
1629 if (param->dtmf == '*')
1630 /* only start is allowed in the sequence */
1635 /* we have a sequence of digits, see what we got */
1636 if (param->dtmf == '*')
1638 else if (param->dtmf>='0' && param->dtmf<='9') {
1639 /* we need to have a star before we receive the digit of the sequence */
1640 if (e_dtmf_last == '*')
1641 e_dtmf_last = param->dtmf;
1642 } else if (param->dtmf == '#') {
1644 if (e_dtmf_last>='0' && e_dtmf_last<='9') {
1645 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf sequence *%c# detected.\n", ea_endpoint->ep_serial, e_dtmf_last);
1646 if (e_dtmf_last == '0') {
1650 /* processing keypad function */
1652 keypad_function(e_dtmf_last);
1658 /* set last time of dtmf */
1663 /* check for ## hookflash during dialing */
1665 if (e_action->index==ACTION_PASSWORD
1666 || e_action->index==ACTION_PASSWORD_WRITE)
1668 if (param->dtmf=='#') { /* current digit is '#' */
1669 if (e_state==EPOINT_STATE_IN_DISCONNECT
1670 || (e_state!=EPOINT_STATE_CONNECT && e_dtmf_time+3>=now && e_dtmf_last=='#')) { /* when disconnected, just #. when dialing, ##. */
1684 /* dialing using dtmf digit */
1685 if (e_state==EPOINT_STATE_IN_OVERLAP){ // && e_state==e_connectedmode)
1686 if (e_dialinginfo.id[0]=='\0' && !e_action) {
1687 set_tone(portlist, "dialing");
1689 /* concat dialing string */
1690 if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
1691 e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
1692 e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
1698 /* port MESSAGE_CRYPT */
1699 void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
1702 /* send crypt response to cryptman */
1703 if (param->crypt.type == CR_MESSAGE_IND)
1704 cryptman_msg2man(param->crypt.data, param->crypt.len);
1706 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
1710 /* port MESSAGE_OVERLAP */
1711 void EndpointAppPBX::port_overlap(struct port_list *portlist, int message_type, union parameter *param)
1713 struct lcr_msg *message;
1715 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1717 /* signal to call tool */
1718 admin_call_response(e_adminid, ADMIN_CALL_SETUP_ACK, "", 0, 0, 0);
1720 if (e_dialing_queue[0] && portlist) {
1721 /* send what we have not dialed yet, because we had no setup complete */
1722 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing pending digits: '%s'\n", ea_endpoint->ep_serial, e_dialing_queue);
1723 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
1724 SCPY(message->param.information.id, e_dialing_queue);
1725 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
1726 message_put(message);
1727 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
1728 e_dialing_queue[0] = '\0';
1730 /* check if pattern is available */
1731 if (!ea_endpoint->ep_portlist->next && portlist->early_b) { /* one port_list relation and tones available */
1732 /* indicate patterns */
1733 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1734 message_put(message);
1736 /* connect audio, if not already */
1737 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1738 message->param.audiopath = 1;
1739 message_put(message);
1741 /* indicate no patterns */
1742 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1743 message_put(message);
1745 /* disconnect audio, if not already */
1746 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1747 message->param.audiopath = 0;
1748 message_put(message);
1750 new_state(EPOINT_STATE_OUT_OVERLAP);
1751 /* if we are in a join */
1752 if (ea_endpoint->ep_join_id) {
1753 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1754 memcpy(&message->param, param, sizeof(union parameter));
1755 message_put(message);
1759 /* port MESSAGE_PROCEEDING */
1760 void EndpointAppPBX::port_proceeding(struct port_list *portlist, int message_type, union parameter *param)
1762 struct lcr_msg *message;
1764 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1766 /* signal to call tool */
1767 admin_call_response(e_adminid, ADMIN_CALL_PROCEEDING, "", 0, 0, 0);
1769 e_state = EPOINT_STATE_OUT_PROCEEDING;
1770 /* check if pattern is availatle */
1771 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1772 /* indicate patterns */
1773 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1774 message_put(message);
1776 /* connect audio, if not already */
1777 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1778 message->param.audiopath = 1;
1779 message_put(message);
1781 /* indicate no patterns */
1782 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1783 message_put(message);
1785 /* disconnect audio, if not already */
1786 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1787 message->param.audiopath = 0;
1788 message_put(message);
1790 /* if we are in a call */
1791 if (ea_endpoint->ep_join_id) {
1792 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1793 memcpy(&message->param, param, sizeof(union parameter));
1794 message_put(message);
1798 /* port MESSAGE_ALERTING */
1799 void EndpointAppPBX::port_alerting(struct port_list *portlist, int message_type, union parameter *param)
1801 struct lcr_msg *message;
1803 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1805 /* signal to call tool */
1806 admin_call_response(e_adminid, ADMIN_CALL_ALERTING, "", 0, 0, 0);
1809 // set_tone(portlist, "hold");
1811 new_state(EPOINT_STATE_OUT_ALERTING);
1812 /* check if pattern is available */
1813 if (!ea_endpoint->ep_portlist->next && (portlist->early_b || portlist->port_type==PORT_TYPE_VBOX_OUT)) { /* one port_list relation and tones available */
1814 /* indicate patterns */
1815 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
1816 message_put(message);
1818 /* connect audio, if not already */
1819 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1820 message->param.audiopath = 1;
1821 message_put(message);
1823 /* indicate no patterns */
1824 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
1825 message_put(message);
1827 /* disconnect audio, if not already */
1828 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1829 message->param.audiopath = 0;
1830 message_put(message);
1832 /* if we are in a call */
1833 if (ea_endpoint->ep_join_id) {
1834 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1835 memcpy(&message->param, param, sizeof(union parameter));
1836 message_put(message);
1840 /* port MESSAGE_CONNECT */
1841 void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type, union parameter *param)
1843 struct lcr_msg *message;
1845 unsigned int port_id = portlist->port_id;
1846 struct port_list *tportlist;
1850 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
1852 /* signal to call tool */
1853 admin_call_response(e_adminid, ADMIN_CALL_CONNECT, numberrize_callerinfo(param->connectinfo.id,param->connectinfo.ntype, options.national, options.international), 0, 0, 0);
1855 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_connectinfo));
1856 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (start)\n", ea_endpoint->ep_serial);
1857 while(ea_endpoint->ep_portlist->next) { /* as long as we have at least two ports */
1858 tportlist = ea_endpoint->ep_portlist;
1859 if (tportlist->port_id == port_id) /* if the first portlist is the calling one, the second must be a different one */
1860 tportlist = tportlist->next;
1861 if (tportlist->port_id == port_id)
1862 FATAL("EPOINT(%d) this should not happen since the portlist list must not have two links to the same port - exitting.\n");
1863 message = message_create(ea_endpoint->ep_serial, tportlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
1864 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
1865 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
1866 message_put(message);
1867 logmessage(message->type, &message->param, tportlist->port_id, DIRECTION_OUT);
1868 ea_endpoint->free_portlist(tportlist);
1870 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
1875 if (e_callerinfo.interface[0])
1876 do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, e_connectinfo.interface);
1878 /* screen connected name */
1880 SCPY(e_connectinfo.name, e_ext.name);
1882 /* add internal id to colp */
1883 SCPY(e_connectinfo.extension, e_ext.number);
1885 /* we store the connected port number */
1886 SCPY(e_extension_interface, e_connectinfo.interface);
1888 /* for internal and am calls, we get the extension's id */
1889 if (portlist->port_type==PORT_TYPE_VBOX_OUT || e_ext.colp==COLP_HIDE) {
1890 SCPY(e_connectinfo.id, e_ext.callerid);
1891 SCPY(e_connectinfo.extension, e_ext.number);
1892 e_connectinfo.itype = INFO_ITYPE_ISDN_EXTENSION;
1893 e_connectinfo.ntype = e_ext.callerid_type;
1894 e_connectinfo.present = e_ext.callerid_present;
1896 if (portlist->port_type==PORT_TYPE_VBOX_OUT) {
1897 e_connectinfo.itype = INFO_ITYPE_VBOX;
1898 e_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
1901 new_state(EPOINT_STATE_CONNECT);
1903 /* set volume of rx and tx */
1904 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0) {
1905 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
1906 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
1907 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
1908 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
1909 message_put(message);
1912 unsched_timer(&e_cfnr_timeout);
1913 unsched_timer(&e_cfnr_call_timeout);
1914 if (e_ext.number[0])
1915 e_dtmf = 1; /* allow dtmf */
1918 /* other calls with no caller id (or not available for the extension) and force colp */
1919 if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
1920 e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
1921 if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT) {
1922 /* external extension answered */
1923 port = find_port_id(portlist->port_id);
1925 SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
1926 e_connectinfo.present = INFO_PRESENT_ALLOWED;
1931 /* send connect to join */
1932 if (ea_endpoint->ep_join_id) {
1933 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
1934 memcpy(&message->param.connectinfo, &e_connectinfo, sizeof(struct connect_info));
1935 message_put(message);
1937 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
1938 message->param.audiopath = 1;
1939 message_put(message);
1940 } else if (!e_adminid) {
1942 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have a callback, so we create a call with cbcaller: \"%s\".\n", ea_endpoint->ep_serial, e_cbcaller);
1943 SCPY(e_ext.number, e_cbcaller);
1944 new_state(EPOINT_STATE_IN_OVERLAP);
1945 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) callback from extension '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1947 /* get extension's info about terminal */
1948 if (!read_extension(&e_ext, e_ext.number)) {
1949 /* extension doesn't exist */
1950 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) rejecting callback from not existing extension: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
1951 message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
1952 new_state(EPOINT_STATE_OUT_DISCONNECT);
1953 set_tone(portlist, "cause_80"); /* pbx cause: extension not authorized */
1957 /* put prefix in front of e_cbdialing */
1958 SPRINT(buffer, "%s%s", e_ext.prefix, e_cbdialing);
1959 SCPY(e_dialinginfo.id, buffer);
1960 e_dialinginfo.itype = INFO_ITYPE_ISDN;
1961 e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
1963 /* use caller id (or if exist: id_next_call) for this call */
1964 e_callerinfo.screen = INFO_SCREEN_NETWORK;
1965 SCPY(e_callerinfo.extension, e_ext.number);
1966 if (e_ext.id_next_call_present >= 0) {
1967 SCPY(e_callerinfo.id, e_ext.id_next_call);
1968 e_callerinfo.present = e_ext.id_next_call_present;
1969 e_callerinfo.ntype = e_ext.id_next_call_type;
1970 e_ext.id_next_call_present = -1;
1971 /* extension is written */
1972 write_extension(&e_ext, e_ext.number);
1974 SCPY(e_callerinfo.id, e_ext.callerid);
1975 e_callerinfo.present = e_ext.callerid_present;
1976 e_callerinfo.ntype = e_ext.callerid_type;
1978 e_callerinfo.ntype2 = INFO_NTYPE_NOTPRESENT;
1980 e_connectedmode = 1; /* dtmf-hangup & disconnect prevention */
1983 /* check if caller id is NOT authenticated */
1984 if (!parse_callbackauth(e_ext.number, &e_callbackinfo)) {
1985 /* make call state to enter password */
1986 new_state(EPOINT_STATE_IN_OVERLAP);
1987 e_action = &action_password_write;
1988 unsched_timer(&e_match_timeout);
1989 e_match_to_action = NULL;
1990 e_dialinginfo.id[0] = '\0';
1991 e_extdialing = strchr(e_dialinginfo.id, '\0');
1992 schedule_timer(&e_password_timeout, 20, 0);
1995 /* incoming call (callback) */
1996 e_ruleset = ruleset_main;
1998 e_rule = e_ruleset->rule_first;
2000 e_extdialing = e_dialinginfo.id;
2001 if (e_dialinginfo.id[0]) {
2002 set_tone(portlist, "dialing");
2005 set_tone(portlist, "dialpbx");
2008 } else { /* testcall */
2009 set_tone(portlist, "hold");
2012 /* start recording if enabled, not when answering machine answers */
2013 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)) {
2014 /* check if we are a terminal */
2015 if (e_ext.number[0] == '\0')
2016 PERROR("Port(%d) cannot record because we are not a terminal\n", ea_endpoint->ep_serial);
2018 port = find_port_id(portlist->port_id);
2020 port->open_record(e_ext.record, 0, 0, e_ext.number, e_ext.anon_ignore, "", 0);
2025 /* port MESSAGE_DISCONNECT MESSAGE_RELEASE */
2026 void EndpointAppPBX::port_disconnect_release(struct port_list *portlist, int message_type, union parameter *param)
2028 struct lcr_msg *message;
2030 unsigned int port_id = portlist->port_id;
2034 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2036 /* signal to call tool */
2037 admin_call_response(e_adminid, (message_type==MESSAGE_DISCONNECT)?ADMIN_CALL_DISCONNECT:ADMIN_CALL_RELEASE, "", param->disconnectinfo.cause, param->disconnectinfo.location, 0);
2039 //#warning does this work? only disconnect when incoming port hat not already disconnected yet?
2040 if (e_state==EPOINT_STATE_IN_DISCONNECT && message_type!=MESSAGE_RELEASE){ // || e_state==EPOINT_STATE_OUT_DISCONNECT || e_state==EPOINT_STATE_IDLE)
2041 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are already disconnected.\n", ea_endpoint->ep_serial);
2046 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);
2047 collect_cause(&e_multipoint_cause, &e_multipoint_location, param->disconnectinfo.cause, param->disconnectinfo.location);
2048 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) new multipoint cause %d location %d.\n", ea_endpoint->ep_serial, e_multipoint_cause, e_multipoint_location);
2050 /* check if we have more than one portlist relation and we just ignore the disconnect */
2051 if (ea_endpoint->ep_portlist) if (ea_endpoint->ep_portlist->next) {
2052 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the disconnect was from a multipoint call. we just release that relation.\n", ea_endpoint->ep_serial);
2053 portlist = ea_endpoint->ep_portlist;
2055 if (portlist->port_id == port_id)
2057 portlist = portlist->next;
2060 FATAL("EPOINT(%d) no portlist related to the calling port.\n", ea_endpoint->ep_serial);
2061 if (message_type != MESSAGE_RELEASE) {
2062 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
2063 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
2064 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2065 message_put(message);
2066 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2068 ea_endpoint->free_portlist(portlist);
2069 return; /* one relation removed */
2071 if (e_state == EPOINT_STATE_CONNECT) {
2072 /* use cause from port after connect */
2073 cause = param->disconnectinfo.cause;
2074 location = param->disconnectinfo.location;
2076 /* use multipoint cause if no connect yet */
2077 if (e_multipoint_cause) {
2078 cause = e_multipoint_cause;
2079 location = e_multipoint_location;
2081 cause = CAUSE_NOUSER;
2082 location = LOCATION_PRIVATE_LOCAL;
2086 unsched_timer(&e_cfnr_timeout);
2087 unsched_timer(&e_cfnr_call_timeout);
2089 /* process hangup */
2090 process_hangup(e_join_cause, e_join_location);
2091 e_multipoint_cause = 0;
2092 e_multipoint_location = 0;
2094 if (message_type == MESSAGE_DISCONNECT) {
2095 /* tone to disconnected end */
2096 SPRINT(buffer, "cause_%02x", cause);
2097 if (ea_endpoint->ep_portlist)
2098 set_tone(ea_endpoint->ep_portlist, buffer);
2100 new_state(EPOINT_STATE_IN_DISCONNECT);
2103 if (ea_endpoint->ep_join_id) {
2104 int haspatterns = 0;
2105 /* check if pattern is available */
2106 if (ea_endpoint->ep_portlist)
2107 if (!ea_endpoint->ep_portlist->next && ea_endpoint->ep_portlist->early_b)
2108 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
2109 && message_type != MESSAGE_RELEASE) // if we release, we are done
2112 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has patterns.\n", ea_endpoint->ep_serial);
2113 /* indicate patterns */
2114 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PATTERN);
2115 message_put(message);
2116 /* connect audio, if not already */
2117 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2118 message->param.audiopath = 1;
2119 message_put(message);
2120 /* send disconnect */
2121 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
2122 memcpy(&message->param, param, sizeof(union parameter));
2123 message_put(message);
2124 /* disable encryption if disconnected */
2125 //PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
2128 cryptman_message(CI_DISCONNECT_IND, NULL, 0);
2132 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
2135 if (message_type == MESSAGE_RELEASE)
2136 ea_endpoint->free_portlist(portlist);
2137 release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
2138 return; /* must exit here */
2141 /* port MESSAGE_TIMEOUT */
2142 void EndpointAppPBX::port_timeout(struct port_list *portlist, int message_type, union parameter *param)
2146 trace_header("TIMEOUT", DIRECTION_IN);
2147 message_type = MESSAGE_DISCONNECT;
2148 switch (param->state) {
2149 case PORT_STATE_OUT_SETUP:
2150 case PORT_STATE_OUT_OVERLAP:
2151 add_trace("state", NULL, "outgoing setup/dialing");
2153 /* no user responding */
2154 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2155 return; /* must exit here */
2157 case PORT_STATE_IN_SETUP:
2158 case PORT_STATE_IN_OVERLAP:
2159 add_trace("state", NULL, "incoming setup/dialing");
2160 param->disconnectinfo.cause = CAUSE_INVALID; /* number incomplete */
2161 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2164 case PORT_STATE_OUT_PROCEEDING:
2165 add_trace("state", NULL, "outgoing proceeding");
2167 param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
2168 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2169 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2170 return; /* must exit here */
2172 case PORT_STATE_IN_PROCEEDING:
2173 add_trace("state", NULL, "incoming proceeding");
2174 param->disconnectinfo.cause = CAUSE_NOUSER;
2175 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL; /* no user responding */
2178 case PORT_STATE_OUT_ALERTING:
2179 add_trace("state", NULL, "outgoing alerting");
2181 param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
2182 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2183 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2184 return; /* must exit here */
2186 case PORT_STATE_CONNECT:
2187 add_trace("state", NULL, "connect");
2189 param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
2190 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2191 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2192 return; /* must exit here */
2194 case PORT_STATE_IN_ALERTING:
2195 add_trace("state", NULL, "incoming alerting");
2196 param->disconnectinfo.cause = CAUSE_NOANSWER;
2197 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2200 case PORT_STATE_IN_DISCONNECT:
2201 case PORT_STATE_OUT_DISCONNECT:
2202 add_trace("state", NULL, "disconnect");
2204 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
2205 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
2206 return; /* must exit here */
2209 param->disconnectinfo.cause = 31; /* normal unspecified */
2210 param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
2213 /* release call, disconnect isdn */
2215 new_state(EPOINT_STATE_OUT_DISCONNECT);
2216 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2217 SCPY(e_tone, cause);
2219 set_tone(portlist, cause);
2220 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
2221 portlist = portlist->next;
2223 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2226 /* port MESSAGE_NOTIFY */
2227 void EndpointAppPBX::port_notify(struct port_list *portlist, int message_type, union parameter *param)
2229 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2231 struct lcr_msg *message;
2232 const char *logtext = "";
2235 /* signal to call tool */
2236 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);
2237 if (param->notifyinfo.notify) {
2238 e_rx_state = track_notify(e_rx_state, param->notifyinfo.notify);
2241 /* if we get notification from stack, local shows if we disabled/enabled audio stream */
2242 if (param->notifyinfo.local) switch(param->notifyinfo.notify) {
2243 case INFO_NOTIFY_REMOTE_HOLD:
2244 case INFO_NOTIFY_USER_SUSPENDED:
2245 /* tell call about it */
2246 if (ea_endpoint->ep_join_id) {
2247 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2248 message->param.audiopath = 0;
2249 message_put(message);
2253 case INFO_NOTIFY_REMOTE_RETRIEVAL:
2254 case INFO_NOTIFY_USER_RESUMED:
2255 /* set volume of rx and tx */
2256 if (param->setup.callerinfo.itype == INFO_ITYPE_ISDN_EXTENSION)
2257 if (e_ext.tx_gain!=0 || e_ext.rx_gain!=0)
2259 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
2260 message->param.mISDNsignal.message = mISDNSIGNAL_VOLUME;
2261 message->param.mISDNsignal.rx_gain = e_ext.tx_gain;
2262 message->param.mISDNsignal.tx_gain = e_ext.rx_gain;
2263 message_put(message);
2265 /* set current tone */
2267 set_tone(portlist, e_tone);
2268 /* tell call about it */
2269 if (ea_endpoint->ep_join_id) {
2270 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2271 message->param.audiopath = 1;
2272 message_put(message);
2277 /* get name of notify */
2278 switch(param->notifyinfo.notify) {
2283 logtext = "USER_SUSPENDED";
2286 logtext = "BEARER_SERVICE_CHANGED";
2289 logtext = "USER_RESUMED";
2292 logtext = "CONFERENCE_ESTABLISHED";
2295 logtext = "CONFERENCE_DISCONNECTED";
2298 logtext = "OTHER_PARTY_ADDED";
2301 logtext = "ISOLATED";
2304 logtext = "REATTACHED";
2307 logtext = "OTHER_PARTY_ISOLATED";
2310 logtext = "OTHER_PARTY_REATTACHED";
2313 logtext = "OTHER_PARTY_SPLIT";
2316 logtext = "OTHER_PARTY_DISCONNECTED";
2319 logtext = "CONFERENCE_FLOATING";
2322 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
2325 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
2328 logtext = "CALL_IS_A_WAITING_CALL";
2331 logtext = "DIVERSION_ACTIVATED";
2334 logtext = "RESERVED_CT_1";
2337 logtext = "RESERVED_CT_2";
2340 logtext = "REVERSE_CHARGING";
2343 logtext = "REMOTE_HOLD";
2346 logtext = "REMOTE_RETRIEVAL";
2349 logtext = "CALL_IS_DIVERTING";
2352 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
2357 /* notify call if available */
2358 if (ea_endpoint->ep_join_id) {
2359 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOTIFY);
2360 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
2361 message_put(message);
2366 /* port MESSAGE_PROGRESS */
2367 void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
2369 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2371 struct lcr_msg *message;
2373 /* signal to call tool */
2374 admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
2376 /* send progress to call if available */
2377 if (ea_endpoint->ep_join_id) {
2378 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
2379 memcpy(&message->param.progressinfo, ¶m->progressinfo, sizeof(struct progress_info));
2380 message_put(message);
2385 /* port MESSAGE_FACILITY */
2386 void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
2388 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2390 struct lcr_msg *message;
2392 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_FACILITY);
2393 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2394 message_put(message);
2397 /* port MESSAGE_3PTY */
2398 void EndpointAppPBX::port_3pty(struct port_list *portlist, int message_type, union parameter *param)
2400 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2402 struct lcr_msg *message;
2406 /* bridge for real */
2407 if (param->threepty.begin)
2409 else if (param->threepty.end)
2415 if (param->threepty.begin)
2417 else if (param->threepty.end)
2423 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_3PTY);
2424 message->param.threepty.begin = param->threepty.begin;
2425 message->param.threepty.end = param->threepty.end;
2427 message->param.threepty.error = 1;
2429 message->param.threepty.result = 1;
2430 message->param.threepty.invoke_id = param->threepty.invoke_id;
2431 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2432 message_put(message);
2435 /* port MESSAGE_SUSPEND */
2436 /* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
2437 void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
2439 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2441 /* epoint is now parked */
2442 ea_endpoint->ep_park = 1;
2443 memcpy(ea_endpoint->ep_park_callid, param->parkinfo.callid, sizeof(ea_endpoint->ep_park_callid));
2444 ea_endpoint->ep_park_len = (param->parkinfo.len>8)?8:param->parkinfo.len;
2446 /* remove port relation */
2447 ea_endpoint->free_portlist(portlist);
2450 /* port MESSAGE_RESUME */
2451 /* NOTE: before resume, the active-notification must be done in order to set call mixer */
2452 void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
2454 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2456 /* epoint is now resumed */
2457 ea_endpoint->ep_park = 0;
2461 /* port MESSAGE_ENABLEKEYPAD */
2462 void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
2464 struct lcr_msg *message;
2466 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2468 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
2469 memcpy(&message->param, param, sizeof(union parameter));
2470 message_put(message);
2474 /* port MESSAGE_DISABLE_DEJITTER */
2475 void EndpointAppPBX::port_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param)
2477 struct lcr_msg *message;
2479 logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
2481 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_DISABLE_DEJITTER);
2482 memcpy(&message->param, param, sizeof(union parameter));
2483 message_put(message);
2487 /* port sends message to the endpoint
2489 void EndpointAppPBX::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
2491 struct port_list *portlist;
2493 portlist = ea_endpoint->ep_portlist;
2495 if (port_id == portlist->port_id)
2497 portlist = portlist->next;
2500 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);
2504 // PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
2505 switch(message_type) {
2506 case MESSAGE_TONE_EOF: /* tone is end of file */
2507 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
2509 if (e_action->index == ACTION_VBOX_PLAY) {
2512 if (e_action->index == ACTION_EFI) {
2518 case MESSAGE_TONE_COUNTER: /* counter info received */
2519 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);
2521 if (e_action->index == ACTION_VBOX_PLAY) {
2522 e_vbox_counter = param->counter.current;
2523 if (param->counter.max >= 0)
2524 e_vbox_counter_max = param->counter.max;
2528 /* PORT sends SETUP message */
2530 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);
2531 if (e_state!=EPOINT_STATE_IDLE) {
2532 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
2535 port_setup(portlist, message_type, param);
2538 /* PORT sends INFORMATION message */
2539 case MESSAGE_INFORMATION: /* additional digits received */
2540 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);
2541 port_information(portlist, message_type, param);
2544 /* PORT sends FACILITY message */
2545 case MESSAGE_FACILITY:
2546 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2547 port_facility(portlist, message_type, param);
2551 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming 3PTY facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2552 port_3pty(portlist, message_type, param);
2555 /* PORT sends DTMF message */
2556 case MESSAGE_DTMF: /* dtmf digits received */
2557 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);
2558 port_dtmf(portlist, message_type, param);
2561 /* PORT sends CRYPT message */
2562 case MESSAGE_CRYPT: /* crypt response received */
2563 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) crypt response=%d\n", ea_endpoint->ep_serial, param->crypt.type);
2564 port_crypt(portlist, message_type, param);
2567 /* PORT sends MORE message */
2568 case MESSAGE_OVERLAP:
2569 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);
2570 if (e_state != EPOINT_STATE_OUT_SETUP) {
2571 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);
2574 port_overlap(portlist, message_type, param);
2577 /* PORT sends PROCEEDING message */
2578 case MESSAGE_PROCEEDING: /* port is proceeding */
2579 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);
2580 if (e_state!=EPOINT_STATE_OUT_SETUP
2581 && e_state!=EPOINT_STATE_OUT_OVERLAP) {
2582 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);
2585 port_proceeding(portlist, message_type, param);
2588 /* PORT sends ALERTING message */
2589 case MESSAGE_ALERTING:
2590 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);
2591 if (e_state!=EPOINT_STATE_OUT_SETUP
2592 && e_state!=EPOINT_STATE_OUT_OVERLAP
2593 && e_state!=EPOINT_STATE_OUT_PROCEEDING) {
2594 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);
2597 port_alerting(portlist, message_type, param);
2600 /* PORT sends CONNECT message */
2601 case MESSAGE_CONNECT:
2602 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);
2603 if (e_state!=EPOINT_STATE_OUT_SETUP
2604 && e_state!=EPOINT_STATE_OUT_OVERLAP
2605 && e_state!=EPOINT_STATE_OUT_PROCEEDING
2606 && e_state!=EPOINT_STATE_OUT_ALERTING) {
2607 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
2610 port_connect(portlist, message_type, param);
2613 /* PORT sends DISCONNECT message */
2614 case MESSAGE_DISCONNECT: /* port is disconnected */
2615 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);
2616 port_disconnect_release(portlist, message_type, param);
2619 /* PORT sends a RELEASE message */
2620 case MESSAGE_RELEASE: /* port releases */
2621 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);
2622 /* portlist is release at port_disconnect_release, thanx Paul */
2623 port_disconnect_release(portlist, message_type, param);
2626 /* PORT sends a TIMEOUT message */
2627 case MESSAGE_TIMEOUT:
2628 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);
2629 port_timeout(portlist, message_type, param);
2630 break; /* release */
2632 /* PORT sends a NOTIFY message */
2633 case MESSAGE_NOTIFY:
2634 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);
2635 port_notify(portlist, message_type, param);
2638 /* PORT sends a PROGRESS message */
2639 case MESSAGE_PROGRESS:
2640 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);
2641 port_progress(portlist, message_type, param);
2644 /* PORT sends a SUSPEND message */
2645 case MESSAGE_SUSPEND:
2646 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);
2647 port_suspend(portlist, message_type, param);
2648 break; /* suspend */
2650 /* PORT sends a RESUME message */
2651 case MESSAGE_RESUME:
2652 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);
2653 port_resume(portlist, message_type, param);
2657 kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
2658 /* port assigns bchannel */
2659 case MESSAGE_BCHANNEL: /* bchannel assignment messafe */
2660 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);
2661 /* only one port is expected to be connected to bchannel */
2662 message = message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
2663 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_IN);
2667 /* PORT requests DTMF */
2668 case MESSAGE_ENABLEKEYPAD:
2669 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);
2670 port_enablekeypad(portlist, message_type, param);
2673 case MESSAGE_DISABLE_DEJITTER:
2674 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming disable dejitter message (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
2675 port_disable_dejitter(portlist, message_type, param);
2680 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);
2683 /* Note: this endpoint may be destroyed, so we MUST return */
2687 /* messages from join
2689 /* join MESSAGE_CRYPT */
2690 void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
2693 switch(param->crypt.type) {
2694 /* message from remote port to "crypt manager" */
2695 case CU_ACTK_REQ: /* activate key-exchange */
2696 case CU_ACTS_REQ: /* activate shared key */
2697 case CU_DACT_REQ: /* deactivate */
2698 case CU_INFO_REQ: /* request last info message */
2699 cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
2702 /* message from "crypt manager" to user */
2703 case CU_ACTK_CONF: /* key-echange done */
2704 case CU_ACTS_CONF: /* shared key done */
2705 case CU_DACT_CONF: /* deactivated */
2706 case CU_DACT_IND: /* deactivated */
2707 case CU_ERROR_IND: /* receive error message */
2708 case CU_INFO_IND: /* receive info message */
2709 case CU_INFO_CONF: /* receive info message */
2710 encrypt_result(param->crypt.type, (char *)param->crypt.data);
2714 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);
2719 /* join MESSAGE_INFORMATION */
2720 void EndpointAppPBX::join_information(struct port_list *portlist, int message_type, union parameter *param)
2722 struct lcr_msg *message;
2727 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
2728 memcpy(&message->param.information, ¶m->information, sizeof(struct dialing_info));
2729 message_put(message);
2730 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2731 portlist = portlist->next;
2735 /* join MESSAGE_FACILITY */
2736 void EndpointAppPBX::join_facility(struct port_list *portlist, int message_type, union parameter *param)
2738 struct lcr_msg *message;
2740 if (!e_ext.facility && e_ext.number[0]) {
2745 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_FACILITY);
2746 memcpy(&message->param.facilityinfo, ¶m->facilityinfo, sizeof(struct facility_info));
2747 message_put(message);
2748 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2749 portlist = portlist->next;
2753 /* join MESSAGE_MORE */
2754 void EndpointAppPBX::join_overlap(struct port_list *portlist, int message_type, union parameter *param)
2756 struct lcr_msg *message;
2758 new_state(EPOINT_STATE_IN_OVERLAP);
2761 if (e_join_pattern && e_ext.own_setup) {
2762 /* disconnect audio */
2763 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2764 message->param.audiopath = 0;
2765 message_put(message);
2767 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2768 if (e_dialinginfo.id[0])
2769 set_tone(portlist, "dialing");
2771 set_tone(portlist, "dialtone");
2774 if (e_dialinginfo.id[0]) {
2775 set_tone(portlist, "dialing");
2777 if (e_ext.number[0])
2778 set_tone(portlist, "dialpbx");
2780 set_tone(portlist, "dialtone");
2784 /* join MESSAGE_PROCEEDING */
2785 void EndpointAppPBX::join_proceeding(struct port_list *portlist, int message_type, union parameter *param)
2787 struct lcr_msg *message;
2789 new_state(EPOINT_STATE_IN_PROCEEDING);
2791 /* own proceeding tone */
2792 if (e_join_pattern) {
2793 /* connect / disconnect audio */
2794 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2795 if (e_ext.own_proceeding)
2796 message->param.audiopath = 0;
2798 message->param.audiopath = 1;
2799 message_put(message);
2801 // UCPY(e_join_tone, "proceeding");
2803 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2804 message_put(message);
2805 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2807 set_tone(portlist, "proceeding");
2810 /* join MESSAGE_ALERTING */
2811 void EndpointAppPBX::join_alerting(struct port_list *portlist, int message_type, union parameter *param)
2813 struct lcr_msg *message;
2815 new_state(EPOINT_STATE_IN_ALERTING);
2817 /* own alerting tone */
2818 if (e_join_pattern) {
2819 /* connect / disconnect audio */
2820 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2821 if (e_ext.own_alerting)
2822 message->param.audiopath = 0;
2824 message->param.audiopath = 1;
2825 message_put(message);
2828 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_ALERTING);
2829 message_put(message);
2830 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2832 if (e_action) if (e_action->index == ACTION_OUTDIAL || e_action->index == ACTION_EXTERNAL) {
2833 set_tone(portlist, "ringing");
2836 if (e_ext.number[0])
2837 set_tone(portlist, "ringpbx");
2839 set_tone(portlist, "ringing");
2841 if (e_ext.number[0])
2842 e_dtmf = 1; /* allow dtmf */
2845 /* join MESSAGE_CONNECT */
2846 void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
2848 struct lcr_msg *message;
2851 new_state(EPOINT_STATE_CONNECT);
2852 // UCPY(e_join_tone, "");
2854 if (e_ext.number[0])
2855 e_dtmf = 1; /* allow dtmf */
2858 unsched_timer(&e_powerdial_timeout);
2859 memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
2861 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
2862 memcpy(&message->param, param, sizeof(union parameter));
2864 /* screen clip if prefix is required */
2865 if (e_ext.number[0] && message->param.connectinfo.id[0] && e_ext.clip_prefix[0]) {
2866 SCPY(message->param.connectinfo.id, e_ext.clip_prefix);
2867 SCAT(message->param.connectinfo.id, numberrize_callerinfo(e_connectinfo.id,e_connectinfo.ntype, options.national, options.international));
2868 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2871 /* use internal caller id */
2872 if (e_ext.number[0] && e_connectinfo.extension[0] && (message->param.connectinfo.present!=INFO_PRESENT_RESTRICTED || e_ext.anon_ignore)) {
2873 SCPY(message->param.connectinfo.id, e_connectinfo.extension);
2874 message->param.connectinfo.ntype = INFO_NTYPE_UNKNOWN;
2877 /* handle restricted caller ids */
2878 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);
2879 /* display callerid if desired for extension */
2880 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));
2882 /* use conp, if enabld */
2883 // if (!e_ext.centrex)
2884 // message->param.connectinfo.name[0] = '\0';
2887 message_put(message);
2888 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2890 set_tone(portlist, NULL);
2892 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2893 message->param.audiopath = 1;
2894 message_put(message);
2899 /* join MESSAGE_DISCONNECT MESSAGE_RELEASE */
2900 void EndpointAppPBX::join_disconnect_release(int message_type, union parameter *param)
2903 struct lcr_msg *message;
2904 struct port_list *portlist = NULL;
2908 /* be sure that we are active */
2910 e_tx_state = NOTIFY_STATE_ACTIVE;
2912 /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
2913 if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
2914 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
2916 /* set time for power dialing */
2917 schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
2920 /* set redial tone */
2921 if (ea_endpoint->ep_portlist) {
2924 set_tone(ea_endpoint->ep_portlist, "redial");
2925 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);
2926 /* send proceeding when powerdialing and still setup (avoid dialing timeout) */
2927 if (e_state==EPOINT_STATE_IN_OVERLAP) {
2928 new_state(EPOINT_STATE_IN_PROCEEDING);
2929 if (ea_endpoint->ep_portlist) {
2930 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_PROCEEDING);
2931 message_put(message);
2932 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
2934 /* caused the error, that the first knock sound was not there */
2935 /* set_tone(portlist, "proceeding"); */
2937 /* send display of powerdialing */
2938 if (e_ext.display_dialing) {
2939 portlist = ea_endpoint->ep_portlist;
2941 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
2943 SPRINT(message->param.notifyinfo.display, "Retry %d of %d", e_powercount, e_powerlimit);
2945 SPRINT(message->param.notifyinfo.display, "Retry %d", e_powercount);
2946 message_put(message);
2947 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
2948 portlist = portlist->next;
2958 if ((e_state!=EPOINT_STATE_CONNECT
2959 && e_state!=EPOINT_STATE_OUT_DISCONNECT
2960 && e_state!=EPOINT_STATE_IN_OVERLAP
2961 && e_state!=EPOINT_STATE_IN_PROCEEDING
2962 && e_state!=EPOINT_STATE_IN_ALERTING)
2963 || !ea_endpoint->ep_portlist) { /* or no port */
2964 process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
2965 release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
2966 return; /* must exit here */
2969 if (!e_join_cause) {
2970 e_join_cause = param->disconnectinfo.cause;
2971 e_join_location = param->disconnectinfo.location;
2974 /* on release we need the audio again! */
2975 if (message_type == MESSAGE_RELEASE) {
2977 ea_endpoint->ep_join_id = 0;
2979 /* disconnect and select tone */
2980 new_state(EPOINT_STATE_OUT_DISCONNECT);
2981 SPRINT(cause, "cause_%02x", param->disconnectinfo.cause);
2982 /* if own_cause, we must release the join */
2983 if (e_ext.own_cause /* own cause */
2984 || !e_join_pattern) { /* no patterns */
2985 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);
2986 if (message_type != MESSAGE_RELEASE)
2987 release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
2989 } else { /* else we enable audio */
2990 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
2991 message->param.audiopath = 1;
2992 message_put(message);
2994 /* send disconnect message */
2995 SCPY(e_tone, cause);
2996 portlist = ea_endpoint->ep_portlist;
2998 set_tone(portlist, cause);
2999 message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
3000 portlist = portlist->next;
3004 /* join MESSAGE_SETUP */
3005 void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, union parameter *param)
3007 struct lcr_msg *message;
3008 // struct interface *interface;
3010 /* if we already in setup state, we just update the dialing with new digits */
3011 if (e_state == EPOINT_STATE_OUT_SETUP
3012 || e_state == EPOINT_STATE_OUT_OVERLAP) {
3013 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we are in setup state, so we do overlap dialing.\n", ea_endpoint->ep_serial);
3014 /* if digits changed, what we have already dialed */
3015 if (!!strncmp(e_dialinginfo.id,param->setup.dialinginfo.id,strlen(e_dialinginfo.id))) {
3016 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);
3017 /* release all ports */
3018 while((portlist = ea_endpoint->ep_portlist)) {
3019 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
3020 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
3021 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3022 message_put(message);
3023 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3024 ea_endpoint->free_portlist(portlist);
3027 /* disconnect audio */
3028 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3029 message->param.audiopath = 0;
3030 message_put(message);
3032 /* get dialing info */
3033 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3034 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3035 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3036 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3037 new_state(EPOINT_STATE_OUT_OVERLAP);
3040 schedule_timer(&e_redial_timeout, 1, 0);
3043 /* if we have a pending redial, so we just adjust the dialing number */
3044 if (e_redial_timeout.active) {
3045 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);
3046 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3049 if (!ea_endpoint->ep_portlist) {
3050 PERROR("ERROR: overlap dialing to a NULL port relation\n");
3052 if (ea_endpoint->ep_portlist->next) {
3053 PERROR("ERROR: overlap dialing to a port_list port relation\n");
3055 if (e_state == EPOINT_STATE_OUT_SETUP) {
3057 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);
3058 SCAT(e_dialing_queue, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3061 /* get what we have not dialed yet */
3062 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));
3063 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_INFORMATION);
3064 SCPY(message->param.information.id, param->setup.dialinginfo.id + strlen(e_dialinginfo.id));
3065 message->param.information.ntype = INFO_NTYPE_UNKNOWN;
3066 message_put(message);
3067 logmessage(message->type, &message->param, ea_endpoint->ep_portlist->port_id, DIRECTION_OUT);
3069 /* always store what we have dialed or queued */
3070 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3074 if (e_state != EPOINT_STATE_IDLE) {
3075 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in idle state.\n", ea_endpoint->ep_serial);
3078 /* if an internal extension is dialed, copy that number */
3079 if (param->setup.dialinginfo.itype==INFO_ITYPE_ISDN_EXTENSION || param->setup.dialinginfo.itype==INFO_ITYPE_VBOX)
3080 SCPY(e_ext.number, param->setup.dialinginfo.id);
3081 /* if an internal extension is dialed, get extension's info about caller */
3082 if (e_ext.number[0]) {
3083 if (!read_extension(&e_ext, e_ext.number)) {
3084 e_ext.number[0] = '\0';
3085 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the called terminal='%s' is not found in directory tree!\n", ea_endpoint->ep_serial, e_ext.number);
3089 memcpy(&e_callerinfo, ¶m->setup.callerinfo, sizeof(e_callerinfo));
3090 memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
3091 memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
3092 memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
3093 memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
3095 /* process (voice over) data calls */
3096 if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
3097 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) handling data call as audio call: '%s'\n", ea_endpoint->ep_serial, e_ext.number);
3098 memset(&e_capainfo, 0, sizeof(e_capainfo));
3099 e_capainfo.bearer_capa = INFO_BC_AUDIO;
3100 e_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
3101 e_capainfo.bearer_info1 = (options.law=='u')?INFO_INFO1_ULAW:INFO_INFO1_ALAW;
3104 new_state(EPOINT_STATE_OUT_SETUP);
3105 /* call special setup routine */
3109 /* join MESSAGE_mISDNSIGNAL */
3110 void EndpointAppPBX::join_mISDNsignal(struct port_list *portlist, int message_type, union parameter *param)
3112 struct lcr_msg *message;
3115 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_mISDNSIGNAL);
3116 memcpy(&message->param, param, sizeof(union parameter));
3117 message_put(message);
3118 portlist = portlist->next;
3122 /* join MESSAGE_BRIDE */
3123 void EndpointAppPBX::join_bridge(struct port_list *portlist, int message_type, union parameter *param)
3125 struct lcr_msg *message;
3128 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
3129 memcpy(&message->param, param, sizeof(union parameter));
3130 message_put(message);
3131 portlist = portlist->next;
3135 /* join MESSAGE_NOTIFY */
3136 void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
3138 struct lcr_msg *message;
3141 if (param->notifyinfo.notify) {
3142 new_state = track_notify(e_tx_state, param->notifyinfo.notify);
3143 // /* if notification was generated locally, we turn hold music on/off */
3144 // if (param->notifyinfo.local)
3145 // 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)
3149 if (new_state!=NOTIFY_STATE_HOLD && new_state!=NOTIFY_STATE_SUSPEND) {
3150 if (!strcmp(e_tone, "hold")) { // don't interrupt other tones
3152 set_tone(portlist, "");
3153 portlist = portlist->next;
3156 portlist = ea_endpoint->ep_portlist;
3161 if (new_state==NOTIFY_STATE_HOLD || new_state==NOTIFY_STATE_SUSPEND) {
3163 set_tone(portlist, "hold");
3164 portlist = portlist->next;
3166 portlist = ea_endpoint->ep_portlist;
3171 /* save new state */
3172 e_tx_state = new_state;
3175 /* notify port(s) about it */
3177 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
3178 memcpy(&message->param.notifyinfo, ¶m->notifyinfo, sizeof(struct notify_info));
3179 /* handle restricted caller ids */
3180 apply_callerid_restriction(&e_ext, message->param.notifyinfo.id, &message->param.notifyinfo.ntype, &message->param.notifyinfo.present, 0, message->param.notifyinfo.extension, NULL);
3181 /* display callerid if desired for extension */
3182 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));
3183 message_put(message);
3184 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
3185 portlist = portlist->next;
3189 /* join MESSAGE_DTMF */
3190 void EndpointAppPBX::join_dtmf(struct port_list *portlist, int message_type, union parameter *param)
3192 struct lcr_msg *message;
3195 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DTMF);
3196 memcpy(&message->param, param, sizeof(union parameter));
3197 message_put(message);
3198 portlist = portlist->next;
3202 /* join MESSAGE_DISABLE_DEJITTER */
3203 void EndpointAppPBX::join_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param)
3205 struct lcr_msg *message;
3208 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISABLE_DEJITTER);
3209 memcpy(&message->param, param, sizeof(union parameter));
3210 message_put(message);
3211 portlist = portlist->next;
3215 /* JOIN sends messages to the endpoint
3217 void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
3219 struct port_list *portlist;
3220 struct lcr_msg *message;
3223 PERROR("EPOINT(%d) error: JOIN == NULL.\n", ea_endpoint->ep_serial);
3227 portlist = ea_endpoint->ep_portlist;
3229 // 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);
3230 switch(message_type) {
3231 /* JOIN SENDS TONE message */
3233 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);
3234 set_tone(portlist, param->tone.name);
3237 /* JOIN SENDS CRYPT message */
3239 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);
3240 join_crypt(portlist, message_type, param);
3243 /* JOIN sends INFORMATION message */
3244 case MESSAGE_INFORMATION:
3245 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);
3246 join_information(portlist, message_type, param);
3249 /* JOIN sends FACILITY message */
3250 case MESSAGE_FACILITY:
3251 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);
3252 join_facility(portlist, message_type, param);
3255 /* JOIN sends OVERLAP message */
3256 case MESSAGE_OVERLAP:
3257 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);
3258 if (e_state!=EPOINT_STATE_IN_SETUP
3259 && e_state!=EPOINT_STATE_IN_OVERLAP) {
3260 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3263 join_overlap(portlist, message_type, param);
3266 /* JOIN sends PROCEEDING message */
3267 case MESSAGE_PROCEEDING:
3268 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);
3269 if(e_state!=EPOINT_STATE_IN_OVERLAP) {
3270 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup state.\n", ea_endpoint->ep_serial);
3273 join_proceeding(portlist, message_type, param);
3276 /* JOIN sends ALERTING message */
3277 case MESSAGE_ALERTING:
3278 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);
3279 if (e_state!=EPOINT_STATE_IN_OVERLAP
3280 && e_state!=EPOINT_STATE_IN_PROCEEDING) {
3281 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup or proceeding state.\n", ea_endpoint->ep_serial);
3284 join_alerting(portlist, message_type, param);
3287 /* JOIN sends CONNECT message */
3288 case MESSAGE_CONNECT:
3289 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);
3290 if (e_state!=EPOINT_STATE_IN_OVERLAP
3291 && e_state!=EPOINT_STATE_IN_PROCEEDING
3292 && e_state!=EPOINT_STATE_IN_ALERTING) {
3293 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ignored because we are not in setup, proceeding or alerting state.\n", ea_endpoint->ep_serial);
3296 join_connect(portlist, message_type, param);
3299 /* JOIN sends DISCONNECT/RELEASE message */
3300 case MESSAGE_DISCONNECT: /* JOIN disconnect */
3301 case MESSAGE_RELEASE: /* JOIN releases */
3302 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);
3303 join_disconnect_release(message_type, param);
3306 /* JOIN sends SETUP message */
3308 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);
3309 join_setup(portlist, message_type, param);
3312 /* JOIN sends special mISDNSIGNAL message */
3313 case MESSAGE_mISDNSIGNAL: /* isdn message to port */
3314 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);
3315 join_mISDNsignal(portlist, message_type, param);
3318 /* JOIN sends bridge message */
3319 case MESSAGE_BRIDGE: /* bride message to port */
3320 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);
3321 join_bridge(portlist, message_type, param);
3324 /* JOIN has pattern available */
3325 case MESSAGE_PATTERN: /* indicating pattern available */
3326 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);
3327 if (!e_join_pattern) {
3328 PDEBUG(DEBUG_EPOINT, "-> pattern becomes available\n");
3332 set_tone(portlist, NULL);
3333 portlist = portlist->next;
3335 /* connect our audio tx and rx (blueboxing should be possibe before connect :)*/
3336 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3337 message->param.audiopath = 1;
3338 message_put(message);
3342 /* JOIN has no pattern available */
3343 case MESSAGE_NOPATTERN: /* indicating no pattern available */
3344 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);
3345 if (e_join_pattern) {
3346 PDEBUG(DEBUG_EPOINT, "-> pattern becomes unavailable\n");
3348 /* disconnect our audio tx and rx */
3349 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3350 message->param.audiopath = 0;
3351 message_put(message);
3356 /* JOIN (dunno at the moment) */
3357 case MESSAGE_REMOTE_AUDIO:
3358 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);
3359 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3360 message->param.audiopath = param->channel;
3361 message_put(message);
3365 /* JOIN sends a notify message */
3366 case MESSAGE_NOTIFY:
3367 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);
3368 join_notify(portlist, message_type, param);
3371 /* JOIN wants keypad / dtmf */
3372 case MESSAGE_ENABLEKEYPAD:
3373 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);
3376 trace_header("ENABLE KEYPAD", DIRECTION_NONE);
3380 /* JOIN sends a DTMF message */
3382 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);
3383 join_dtmf(portlist, message_type, param);
3386 /* JOIN sends a DISABLE_DEJITTER message */
3387 case MESSAGE_DISABLE_DEJITTER:
3388 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received disable dejitter.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
3389 join_disable_dejitter(portlist, message_type, param);
3393 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);
3398 /* pick_join will connect the first incoming call found. the endpoint
3399 * will receivce a MESSAGE_CONNECT.
3401 int match_list(char *list, char *item)
3403 char *end, *next = NULL;
3405 /* no list make matching */
3410 /* eliminate white spaces */
3411 while (*list > '\0' && *list <= ' ')
3417 /* if end of list is reached, we return */
3418 if (list[0] == '\0')
3420 /* if we have more than one entry (left) */
3421 if ((end = strchr(list, ',')))
3424 next = end = strchr(list, '\0');
3425 while (*(end-1) <= ' ')
3427 /* if string part matches item */
3428 if (!strncmp(list, item, end-list))
3434 void EndpointAppPBX::pick_join(char *extensions)
3436 struct lcr_msg *message;
3437 struct port_list *portlist;
3439 class EndpointAppPBX *eapp, *found;
3441 class JoinPBX *joinpbx;
3442 struct join_relation *relation;
3445 /* find an endpoint that is ringing internally or vbox with higher priority */
3448 eapp = apppbx_first;
3450 if (eapp!=this && ea_endpoint->ep_portlist) {
3451 portlist = eapp->ea_endpoint->ep_portlist;
3453 if ((port = find_port_id(portlist->port_id))) {
3454 if (port->p_type == PORT_TYPE_VBOX_OUT) {
3455 if (match_list(extensions, eapp->e_ext.number)) {
3461 if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT
3462 && port->p_state==PORT_STATE_OUT_ALERTING)
3463 if (match_list(extensions, eapp->e_ext.number)) {
3467 portlist = portlist->next;
3475 /* if no endpoint found */
3477 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);
3479 set_tone(ea_endpoint->ep_portlist, "cause_10");
3480 message_disconnect_port(ea_endpoint->ep_portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
3481 new_state(EPOINT_STATE_OUT_DISCONNECT);
3486 if (ea_endpoint->ep_join_id) {
3487 PERROR("EPOINT(%d) we already have a join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3490 if (!eapp->ea_endpoint->ep_join_id) {
3491 PERROR("EPOINT(%d) ringing endpoint has no join.\n", ea_endpoint->ep_serial);
3494 join = find_join_id(eapp->ea_endpoint->ep_join_id);
3496 PERROR("EPOINT(%d) ringing endpoint's join not found.\n", ea_endpoint->ep_serial);
3499 if (join->j_type != JOIN_TYPE_PBX) {
3500 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) ringing endpoint's join is not a PBX join, so we must reject.\n", ea_endpoint->ep_serial);
3503 joinpbx = (class JoinPBX *)join;
3504 relation = joinpbx->j_relation;
3506 PERROR("EPOINT(%d) ringing endpoint's join has no relation. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3509 while (relation->epoint_id != eapp->ea_endpoint->ep_serial) {
3510 relation = relation->next;
3512 PERROR("EPOINT(%d) ringing endpoint's join has no relation to that join. SOFTWARE ERROR.\n", ea_endpoint->ep_serial);
3517 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) found ringing endpoint: %d.\n", ea_endpoint->ep_serial, eapp->ea_endpoint->ep_serial);
3519 if (options.deb & DEBUG_EPOINT) {
3520 class Join *debug_c = join_first;
3521 class Endpoint *debug_e = epoint_first;
3522 class Port *debug_p = port_first;
3524 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(before)");
3526 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3528 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3529 debug_c = debug_c->next;
3531 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3533 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3534 debug_e = debug_e->next;
3536 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3538 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld (active)\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3539 debug_p = debug_p->next;
3544 ea_endpoint->ep_join_id = eapp->ea_endpoint->ep_join_id; /* we get the join */
3545 relation->epoint_id = ea_endpoint->ep_serial; /* the join gets us */
3546 eapp->ea_endpoint->ep_join_id = 0; /* the ringing endpoint will get disconnected */
3548 /* connnecting our endpoint */
3549 new_state(EPOINT_STATE_CONNECT);
3550 if (e_ext.number[0])
3552 set_tone(ea_endpoint->ep_portlist, NULL);
3554 /* now we send a release to the ringing endpoint */
3555 message = message_create(ea_endpoint->ep_join_id, eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3556 message->param.disconnectinfo.cause = CAUSE_NONSELECTED; /* non selected user clearing */
3557 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3558 message_put(message);
3560 /* we send a connect to the join with our caller id */
3561 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_CONNECT);
3562 SCPY(message->param.connectinfo.id, e_callerinfo.id);
3563 message->param.connectinfo.present = e_callerinfo.present;
3564 message->param.connectinfo.screen = e_callerinfo.screen;
3565 message->param.connectinfo.itype = e_callerinfo.itype;
3566 message->param.connectinfo.ntype = e_callerinfo.ntype;
3567 message_put(message);
3569 /* we send a connect to our port with the remote callerid */
3570 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
3571 SCPY(message->param.connectinfo.id, eapp->e_callerinfo.id);
3572 message->param.connectinfo.present = eapp->e_callerinfo.present;
3573 message->param.connectinfo.screen = eapp->e_callerinfo.screen;
3574 message->param.connectinfo.itype = eapp->e_callerinfo.itype;
3575 message->param.connectinfo.ntype = eapp->e_callerinfo.ntype;
3576 /* handle restricted caller ids */
3577 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);
3578 /* display callerid if desired for extension */
3579 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));
3580 message_put(message);
3582 /* we send a connect to the audio path (not for vbox) */
3583 message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
3584 message->param.audiopath = 1;
3585 message_put(message);
3587 /* beeing paranoid, we make call update */
3588 trigger_work(&joinpbx->j_updatebridge);
3590 if (options.deb & DEBUG_EPOINT) {
3591 class Join *debug_c = join_first;
3592 class Endpoint *debug_e = epoint_first;
3593 class Port *debug_p = port_first;
3595 joinpbx_debug(joinpbx, "EndpointAppPBX::pick_join(after)");
3597 PDEBUG(DEBUG_EPOINT, "showing all joins:\n");
3599 PDEBUG(DEBUG_EPOINT, "join=%ld\n", debug_c->j_serial);
3600 debug_c = debug_c->next;
3602 PDEBUG(DEBUG_EPOINT, "showing all endpoints:\n");
3604 PDEBUG(DEBUG_EPOINT, "ep=%ld, join=%ld\n", debug_e->ep_serial, debug_e->ep_join_id);
3605 debug_e = debug_e->next;
3607 PDEBUG(DEBUG_EPOINT, "showing all ports:\n");
3609 PDEBUG(DEBUG_EPOINT, "port=%ld, ep=%ld\n", debug_p->p_serial, ACTIVE_EPOINT(debug_p->p_epointlist));
3610 debug_p = debug_p->next;
3616 /* join calls (look for a join that is on hold (same isdn interface/terminal))
3618 int EndpointAppPBX::join_join(void)
3621 struct lcr_msg *message;
3622 struct join_relation *add_relation, *remove_relation;
3623 struct join_relation **add_relation_pointer, **remove_relation_pointer;
3624 class Join *our_join, *other_join, *add_join, *remove_join;
3625 class JoinPBX *our_joinpbx, *other_joinpbx, *add_joinpbx, *remove_joinpbx;
3626 class EndpointAppPBX *other_eapp, *remove_eapp;
3627 class Port *our_port, *other_port;
3628 class Pdss1 *our_pdss1, *other_pdss1;
3629 class Endpoint *temp_epoint;
3631 /* are we a candidate to join a join? */
3632 our_join = find_join_id(ea_endpoint->ep_join_id);
3634 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3637 if (our_join->j_type != JOIN_TYPE_PBX) {
3638 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3641 our_joinpbx = (class JoinPBX *)our_join;
3642 if (!ea_endpoint->ep_portlist) {
3643 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3646 if (!e_ext.number[0]) {
3647 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3650 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3652 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3655 if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
3656 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3659 our_pdss1 = (class Pdss1 *)our_port;
3661 /* find an endpoint that has the same mISDNport/ces that we are on */
3662 other_eapp = apppbx_first;
3664 if (other_eapp == this) {
3665 other_eapp = other_eapp->next;
3668 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);
3669 if (other_eapp->e_ext.number[0] /* has terminal */
3670 && other_eapp->ea_endpoint->ep_portlist /* has port */
3671 && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3672 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3673 if (other_port) { /* port still exists */
3674 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3675 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3676 other_pdss1 = (class Pdss1 *)other_port;
3677 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);
3678 if (1 //other_pdss1->p_m_hold /* port is on hold */
3679 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3680 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3683 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3686 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3689 other_eapp = other_eapp->next;
3692 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3695 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3697 /* if we have the same join */
3698 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3699 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3702 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3704 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3707 if (other_join->j_type != JOIN_TYPE_PBX) {
3708 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3711 other_joinpbx = (class JoinPBX *)other_join;
3712 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3713 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3717 /* now find out which is ACTIVE-IDLE and which is ACTIVE-HELD */
3718 if (our_pdss1->p_m_hold && !other_pdss1->p_m_hold) {
3719 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) our relation is on hold and other is active, so we move our relations to other relations\n", ea_endpoint->ep_serial);
3721 remove_join = our_join;
3722 remove_joinpbx = our_joinpbx;
3723 add_join = other_join;
3724 add_joinpbx = other_joinpbx;
3726 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) our relation is active or other is on hold, so we move ohter relations to our relations\n", ea_endpoint->ep_serial);
3727 remove_eapp = other_eapp;
3728 remove_join = other_join;
3729 remove_joinpbx = other_joinpbx;
3730 add_join = our_join;
3731 add_joinpbx = our_joinpbx;
3734 /* remove relation to endpoint for join on hold */
3735 remove_relation = remove_joinpbx->j_relation;
3736 remove_relation_pointer = &remove_joinpbx->j_relation;
3737 while(remove_relation) {
3738 if (remove_relation->epoint_id == remove_eapp->ea_endpoint->ep_serial) {
3739 /* detach other endpoint */
3740 *remove_relation_pointer = remove_relation->next;
3741 FREE(remove_relation, sizeof(struct join_relation));
3743 remove_relation = *remove_relation_pointer;
3744 remove_eapp->ea_endpoint->ep_join_id = 0;
3748 /* change join/hold pointer of endpoint to the new join */
3749 temp_epoint = find_epoint_id(remove_relation->epoint_id);
3751 if (temp_epoint->ep_join_id == remove_join->j_serial)
3752 temp_epoint->ep_join_id = add_join->j_serial;
3755 remove_relation_pointer = &remove_relation->next;
3756 remove_relation = remove_relation->next;
3758 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint removed, other enpoints on join relinked.\n", ea_endpoint->ep_serial);
3760 /* join call relations */
3761 add_relation = add_joinpbx->j_relation;
3762 add_relation_pointer = &add_joinpbx->j_relation;
3763 while(add_relation) {
3764 add_relation_pointer = &add_relation->next;
3765 add_relation = add_relation->next;
3767 *add_relation_pointer = remove_joinpbx->j_relation;
3768 remove_joinpbx->j_relation = NULL;
3769 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
3771 /* release endpoint */
3772 message = message_create(remove_joinpbx->j_serial, remove_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
3773 message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
3774 message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
3775 message_put(message);
3777 /* if we are not a partyline, we get partyline state from other join */
3778 add_joinpbx->j_partyline += remove_joinpbx->j_partyline;
3780 /* remove empty join */
3782 PDEBUG(DEBUG_EPOINT, "EPOINT(%d)join completely removed!\n", ea_endpoint->ep_serial);
3784 /* mixer must update */
3785 trigger_work(&add_joinpbx->j_updatebridge);
3787 /* we send a retrieve to that endpoint */
3788 // mixer will update the hold-state of the join and send it to the endpoints is changes
3790 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
3796 int EndpointAppPBX::join_3pty(void)
3799 class Join *our_join, *other_join;
3800 class JoinPBX *our_joinpbx, *other_joinpbx;
3801 class EndpointAppPBX *other_eapp;
3802 class Port *our_port, *other_port;
3803 class Pdss1 *our_pdss1, *other_pdss1;
3805 /* are we a candidate to join a join? */
3806 our_join = find_join_id(ea_endpoint->ep_join_id);
3808 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3811 if (our_join->j_type != JOIN_TYPE_PBX) {
3812 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
3815 our_joinpbx = (class JoinPBX *)our_join;
3816 if (!ea_endpoint->ep_portlist) {
3817 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
3820 if (!e_ext.number[0]) {
3821 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
3824 our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
3826 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
3829 if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
3830 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
3833 our_pdss1 = (class Pdss1 *)our_port;
3835 /* find an endpoint that has the same mISDNport/ces that we are on */
3836 other_eapp = apppbx_first;
3838 if (other_eapp == this) {
3839 other_eapp = other_eapp->next;
3842 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);
3843 if (other_eapp->e_ext.number[0] /* has terminal */
3844 && other_eapp->ea_endpoint->ep_portlist /* has port */
3845 && other_eapp->ea_endpoint->ep_join_id) { /* has join */
3846 other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
3847 if (other_port) { /* port still exists */
3848 if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
3849 || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
3850 other_pdss1 = (class Pdss1 *)other_port;
3851 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);
3852 if (1 //other_pdss1->p_m_hold /* port is on hold */
3853 && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
3854 && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
3857 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
3860 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
3863 other_eapp = other_eapp->next;
3866 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
3869 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
3871 /* if we have the same join */
3872 if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
3873 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
3876 other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
3878 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3881 if (other_join->j_type != JOIN_TYPE_PBX) {
3882 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
3885 other_joinpbx = (class JoinPBX *)other_join;
3886 if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
3887 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
3891 if (our_joinpbx->j_3pty) {
3892 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join already doing 3PTY.\n", ea_endpoint->ep_serial);
3895 if (other_joinpbx->j_3pty) {
3896 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join already doing 3PTY.\n", ea_endpoint->ep_serial);
3900 /* set 3PTY bridge */
3901 other_joinpbx->j_3pty = our_joinpbx->j_serial;
3902 our_joinpbx->j_3pty = other_joinpbx->j_serial;
3904 /* mixer must update */
3905 trigger_work(&our_joinpbx->j_updatebridge);
3906 trigger_work(&other_joinpbx->j_updatebridge);
3908 /* we send a retrieve to that endpoint */
3909 // mixer will update the hold-state of the join and send it to the endpoints is changes
3911 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
3917 int EndpointAppPBX::split_3pty(void)
3920 class Join *our_join, *other_join;
3921 class JoinPBX *our_joinpbx, *other_joinpbx;
3923 /* are we a candidate to join a join? */
3924 our_join = find_join_id(ea_endpoint->ep_join_id);
3926 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3929 if (our_join->j_type != JOIN_TYPE_PBX) {
3930 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: join is not a pbx join.\n", ea_endpoint->ep_serial);
3933 our_joinpbx = (class JoinPBX *)our_join;
3935 if (!our_joinpbx->j_3pty) {
3936 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: we don't have a 3PTY.\n", ea_endpoint->ep_serial);
3940 other_join = find_join_id(our_joinpbx->j_3pty);
3942 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
3945 if (other_join->j_type != JOIN_TYPE_PBX) {
3946 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: join is not a pbx join.\n", ea_endpoint->ep_serial);
3949 other_joinpbx = (class JoinPBX *)other_join;
3951 our_joinpbx->j_3pty = 0;
3952 other_joinpbx->j_3pty = 0;
3954 /* mixer must update */
3955 trigger_work(&our_joinpbx->j_updatebridge);
3956 trigger_work(&other_joinpbx->j_updatebridge);
3958 /* we send a retrieve to that endpoint */
3959 // mixer will update the hold-state of the join and send it to the endpoints is changes
3961 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: no mISDN support anyway.\n", ea_endpoint->ep_serial);
3967 /* check if we have an external call
3968 * this is used to check for encryption ability
3970 int EndpointAppPBX::check_external(const char **errstr, class Port **port)
3972 struct join_relation *relation;
3974 class JoinPBX *joinpbx;
3975 class Endpoint *epoint;
3977 /* some paranoia check */
3978 if (!ea_endpoint->ep_portlist) {
3979 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we have no port.\n", ea_endpoint->ep_serial);
3980 *errstr = "No Call";
3983 if (!e_ext.number[0]) {
3984 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) error: we are not internal extension.\n", ea_endpoint->ep_serial);
3985 *errstr = "No Call";
3989 /* check if we have a join with 2 parties */
3990 join = find_join_id(ea_endpoint->ep_join_id);
3992 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we have currently no join.\n", ea_endpoint->ep_serial);
3993 *errstr = "No Call";
3996 if (join->j_type != JOIN_TYPE_PBX) {
3997 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join is not a pbx join.\n", ea_endpoint->ep_serial);
3998 *errstr = "No PBX Call";
4001 joinpbx = (class JoinPBX *)join;
4002 relation = joinpbx->j_relation;
4004 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no relation.\n", ea_endpoint->ep_serial);
4005 *errstr = "No Call";
4008 if (!relation->next) {
4009 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd relation.\n", ea_endpoint->ep_serial);
4010 *errstr = "No Call";
4013 if (relation->next->next) {
4014 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has more than two relations.\n", ea_endpoint->ep_serial);
4015 *errstr = "Err: Conference";
4018 if (relation->epoint_id == ea_endpoint->ep_serial) {
4019 relation = relation->next;
4020 if (relation->epoint_id == ea_endpoint->ep_serial) {
4021 PERROR("EPOINT(%d) SOFTWARE ERROR: both join relations are related to our endpoint.\n", ea_endpoint->ep_serial);
4022 *errstr = "Software Error";
4027 /* check remote port for external call */
4028 epoint = find_epoint_id(relation->epoint_id);
4030 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) join has no 2nd endpoint.\n", ea_endpoint->ep_serial);
4031 *errstr = "No Call";
4034 if (!epoint->ep_portlist) {
4035 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not port.\n", ea_endpoint->ep_serial);
4036 *errstr = "No Call";
4039 *port = find_port_id(epoint->ep_portlist->port_id);
4041 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has an none existing port.\n", ea_endpoint->ep_serial);
4042 *errstr = "No Call";
4045 if (((*port)->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) { /* port is not external isdn */
4046 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
4047 *errstr = "No Ext Call";
4050 if ((*port)->p_state != PORT_STATE_CONNECT) {
4051 PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint's port is not in connected state.\n", ea_endpoint->ep_serial);
4052 *errstr = "No Ext Connect";
4058 void EndpointAppPBX::logmessage(int message_type, union parameter *param, unsigned int port_id, int dir)
4060 const char *logtext = "unknown";
4063 switch(message_type) {
4065 trace_header("SETUP", dir);
4066 if (dir == DIRECTION_OUT)
4067 add_trace("to", NULL, "CH(%lu)", port_id);
4068 if (dir == DIRECTION_IN)
4069 add_trace("from", NULL, "CH(%lu)", port_id);
4070 if (param->setup.callerinfo.extension[0])
4071 add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
4072 if (param->setup.callerinfo.interface[0])
4073 add_trace("interface", "from", "%s", param->setup.callerinfo.interface);
4074 if (param->setup.dialinginfo.interfaces[0])
4075 add_trace("interface", "to", "%s", param->setup.dialinginfo.interfaces);
4076 add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
4077 switch(param->setup.callerinfo.present) {
4078 case INFO_PRESENT_RESTRICTED:
4079 add_trace("caller id", "present", "restricted");
4081 case INFO_PRESENT_ALLOWED:
4082 add_trace("caller id", "present", "allowed");
4085 add_trace("caller id", "present", "not available");
4087 if (param->setup.callerinfo.ntype2) {
4088 add_trace("caller id2", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id2, param->setup.callerinfo.ntype2, options.national, options.international));
4089 switch(param->setup.callerinfo.present) {
4090 case INFO_PRESENT_RESTRICTED:
4091 add_trace("caller id2", "present", "restricted");
4093 case INFO_PRESENT_ALLOWED:
4094 add_trace("caller id2", "present", "allowed");
4097 add_trace("caller id2", "present", "not available");
4100 if (param->setup.redirinfo.id[0]) {
4101 add_trace("redir'ing", "number", "%s", numberrize_callerinfo(param->setup.redirinfo.id, param->setup.redirinfo.ntype, options.national, options.international));
4102 switch(param->setup.redirinfo.present) {
4103 case INFO_PRESENT_RESTRICTED:
4104 add_trace("redir'ing", "present", "restricted");
4106 case INFO_PRESENT_ALLOWED:
4107 add_trace("redir'ing", "present", "allowed");
4110 add_trace("redir'ing", "present", "not available");
4113 if (param->setup.dialinginfo.id[0])
4114 add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
4115 if (param->setup.dialinginfo.keypad[0])
4116 add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
4117 if (param->setup.dialinginfo.display[0])
4118 add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
4119 if (param->setup.dialinginfo.sending_complete)
4120 add_trace("complete", NULL, "true", param->setup.dialinginfo.sending_complete);
4124 case MESSAGE_OVERLAP:
4125 trace_header("SETUP ACKNOWLEDGE", dir);
4126 if (dir == DIRECTION_OUT)
4127 add_trace("to", NULL, "CH(%lu)", port_id);
4128 if (dir == DIRECTION_IN)
4129 add_trace("from", NULL, "CH(%lu)", port_id);
4133 case MESSAGE_PROCEEDING:
4134 trace_header("PROCEEDING", dir);
4135 if (dir == DIRECTION_OUT)
4136 add_trace("to", NULL, "CH(%lu)", port_id);
4137 if (dir == DIRECTION_IN)
4138 add_trace("from", NULL, "CH(%lu)", port_id);
4142 case MESSAGE_ALERTING:
4143 trace_header("ALERTING", dir);
4144 if (dir == DIRECTION_OUT)
4145 add_trace("to", NULL, "CH(%lu)", port_id);
4146 if (dir == DIRECTION_IN)
4147 add_trace("from", NULL, "CH(%lu)", port_id);
4151 case MESSAGE_CONNECT:
4152 trace_header("CONNECT", dir);
4153 if (dir == DIRECTION_OUT)
4154 add_trace("to", NULL, "CH(%lu)", port_id);
4155 if (dir == DIRECTION_IN)
4156 add_trace("from", NULL, "CH(%lu)", port_id);
4157 if (param->connectinfo.extension[0])
4158 add_trace("extension", NULL, "%s", param->connectinfo.extension);
4159 add_trace("connect id", "number", "%s", numberrize_callerinfo(param->connectinfo.id, param->connectinfo.ntype, options.national, options.international));
4160 switch(param->connectinfo.present) {
4161 case INFO_PRESENT_RESTRICTED:
4162 add_trace("connect id", "present", "restricted");
4164 case INFO_PRESENT_ALLOWED:
4165 add_trace("connect id", "present", "allowed");
4168 add_trace("connect id", "present", "not available");
4170 if (param->connectinfo.display[0])
4171 add_trace("display", NULL, "%s", param->connectinfo.display);
4175 case MESSAGE_DISCONNECT:
4176 case MESSAGE_RELEASE:
4177 if (message_type == MESSAGE_DISCONNECT)
4178 trace_header("DISCONNECT", dir);
4180 trace_header("RELEASE", dir);
4181 if (dir == DIRECTION_OUT)
4182 add_trace("to", NULL, "CH(%lu)", port_id);
4183 if (dir == DIRECTION_IN)
4184 add_trace("from", NULL, "CH(%lu)", port_id);
4185 add_trace("cause", "value", "%d", param->disconnectinfo.cause);
4186 switch(param->disconnectinfo.location) {
4188 add_trace("cause", "location", "0-User");
4190 case LOCATION_PRIVATE_LOCAL:
4191 add_trace("cause", "location", "1-Local-PBX");
4193 case LOCATION_PUBLIC_LOCAL:
4194 add_trace("cause", "location", "2-Local-Exchange");
4196 case LOCATION_TRANSIT:
4197 add_trace("cause", "location", "3-Transit");
4199 case LOCATION_PUBLIC_REMOTE:
4200 add_trace("cause", "location", "4-Remote-Exchange");
4202 case LOCATION_PRIVATE_REMOTE:
4203 add_trace("cause", "location", "5-Remote-PBX");
4205 case LOCATION_INTERNATIONAL:
4206 add_trace("cause", "location", "7-International-Exchange");
4208 case LOCATION_BEYOND:
4209 add_trace("cause", "location", "10-Beyond-Interworking");
4212 add_trace("cause", "location", "%d", param->disconnectinfo.location);
4214 if (param->disconnectinfo.display[0])
4215 add_trace("display", NULL, "%s", param->disconnectinfo.display);
4219 case MESSAGE_NOTIFY:
4220 switch(param->notifyinfo.notify) {
4225 logtext = "USER_SUSPENDED";
4228 logtext = "BEARER_SERVICE_CHANGED";
4231 logtext = "USER_RESUMED";
4234 logtext = "CONFERENCE_ESTABLISHED";
4237 logtext = "CONFERENCE_DISCONNECTED";
4240 logtext = "OTHER_PARTY_ADDED";
4243 logtext = "ISOLATED";
4246 logtext = "REATTACHED";
4249 logtext = "OTHER_PARTY_ISOLATED";
4252 logtext = "OTHER_PARTY_REATTACHED";
4255 logtext = "OTHER_PARTY_SPLIT";
4258 logtext = "OTHER_PARTY_DISCONNECTED";
4261 logtext = "CONFERENCE_FLOATING";
4264 logtext = "CONFERENCE_DISCONNECTED_PREEMTED";
4267 logtext = "CONFERENCE_FLOATING_SERVED_USER_PREEMTED";
4270 logtext = "CALL_IS_A_WAITING_CALL";
4273 logtext = "DIVERSION_ACTIVATED";
4276 logtext = "RESERVED_CT_1";
4279 logtext = "RESERVED_CT_2";
4282 logtext = "REVERSE_CHARGING";
4285 logtext = "REMOTE_HOLD";
4288 logtext = "REMOTE_RETRIEVAL";
4291 logtext = "CALL_IS_DIVERTING";
4294 SPRINT(buffer, "%d", param->notifyinfo.notify - 0x80);
4298 trace_header("NOTIFY", dir);
4299 if (dir == DIRECTION_OUT)
4300 add_trace("to", NULL, "CH(%lu)", port_id);
4301 if (dir == DIRECTION_IN)
4302 add_trace("from", NULL, "CH(%lu)", port_id);
4303 if (param->notifyinfo.notify)
4304 add_trace("indicator", NULL, "%s", logtext);
4305 if (param->notifyinfo.id[0]) {
4306 add_trace("redir'on", "number", "%s", numberrize_callerinfo(param->notifyinfo.id, param->notifyinfo.ntype, options.national, options.international));
4307 switch(param->notifyinfo.present) {
4308 case INFO_PRESENT_RESTRICTED:
4309 add_trace("redir'on", "present", "restricted");
4311 case INFO_PRESENT_ALLOWED:
4312 add_trace("redir'on", "present", "allowed");
4315 add_trace("redir'on", "present", "not available");
4318 if (param->notifyinfo.display[0])
4319 add_trace("display", NULL, "%s", param->notifyinfo.display);
4323 case MESSAGE_PROGRESS:
4324 switch(param->progressinfo.progress) {
4326 logtext = "Call is not end to end ISDN";
4329 logtext = "Destination address is non-ISDN";
4332 logtext = "Origination address is non-ISDN";
4335 logtext = "Call has returned to the ISDN";
4338 logtext = "In-band info or pattern available";
4341 SPRINT(buffer, "%d", param->progressinfo.progress);
4345 trace_header("PROGRESS", dir);
4346 if (dir == DIRECTION_OUT)
4347 add_trace("to", NULL, "CH(%lu)", port_id);
4348 if (dir == DIRECTION_IN)
4349 add_trace("from", NULL, "CH(%lu)", port_id);
4350 add_trace("indicator", NULL, "%s", logtext);
4351 switch(param->progressinfo.location) {
4353 add_trace("cause", "location", "0-User");
4355 case LOCATION_PRIVATE_LOCAL:
4356 add_trace("cause", "location", "1-Local-PBX");
4358 case LOCATION_PUBLIC_LOCAL:
4359 add_trace("cause", "location", "2-Local-Exchange");
4361 case LOCATION_TRANSIT:
4362 add_trace("cause", "location", "3-Transit");
4364 case LOCATION_PUBLIC_REMOTE:
4365 add_trace("cause", "location", "4-Remote-Exchange");
4367 case LOCATION_PRIVATE_REMOTE:
4368 add_trace("cause", "location", "5-Remote-PBX");
4370 case LOCATION_INTERNATIONAL:
4371 add_trace("cause", "location", "7-International-Exchange");
4373 case LOCATION_BEYOND:
4374 add_trace("cause", "location", "10-Beyond-Interworking");
4377 add_trace("cause", "location", "%d", param->progressinfo.location);
4382 case MESSAGE_INFORMATION:
4383 trace_header("INFORMATION", dir);
4384 if (dir == DIRECTION_OUT)
4385 add_trace("to", NULL, "CH(%lu)", port_id);
4386 if (dir == DIRECTION_IN)
4387 add_trace("from", NULL, "CH(%lu)", port_id);
4388 if (param->information.id[0])
4389 add_trace("dialing", NULL, "%s", param->information.id);
4390 if (param->information.display[0])
4391 add_trace("display", NULL, "%s", param->information.display);
4392 if (param->information.sending_complete)
4393 add_trace("complete", NULL, "true", param->information.sending_complete);
4397 case MESSAGE_FACILITY:
4398 trace_header("FACILITY", dir);
4399 if (dir == DIRECTION_OUT)
4400 add_trace("to", NULL, "CH(%lu)", port_id);
4401 if (dir == DIRECTION_IN)
4402 add_trace("from", NULL, "CH(%lu)", port_id);
4407 trace_header("TONE", dir);
4408 if (dir == DIRECTION_OUT)
4409 add_trace("to", NULL, "CH(%lu)", port_id);
4410 if (dir == DIRECTION_IN)
4411 add_trace("from", NULL, "CH(%lu)", port_id);
4412 if (param->tone.name[0]) {
4413 add_trace("directory", NULL, "%s", param->tone.dir[0]?param->tone.dir:"default");
4414 add_trace("name", NULL, "%s", param->tone.name);
4416 add_trace("off", NULL, NULL);
4420 case MESSAGE_SUSPEND:
4421 case MESSAGE_RESUME:
4422 if (message_type == MESSAGE_SUSPEND)
4423 trace_header("SUSPEND", dir);
4425 trace_header("RESUME", dir);
4426 if (dir == DIRECTION_OUT)
4427 add_trace("to", NULL, "CH(%lu)", port_id);
4428 if (dir == DIRECTION_IN)
4429 add_trace("from", NULL, "CH(%lu)", port_id);
4430 if (param->parkinfo.len)
4431 add_trace("length", NULL, "%d", param->parkinfo.len);
4436 case MESSAGE_BCHANNEL:
4437 trace_header("BCHANNEL", dir);
4438 switch(param->bchannel.type) {
4439 case BCHANNEL_REQUEST:
4440 add_trace("type", NULL, "request");
4442 case BCHANNEL_ASSIGN:
4443 add_trace("type", NULL, "assign");
4445 case BCHANNEL_ASSIGN_ACK:
4446 add_trace("type", NULL, "assign_ack");
4448 case BCHANNEL_REMOVE:
4449 add_trace("type", NULL, "remove");
4451 case BCHANNEL_REMOVE_ACK:
4452 add_trace("type", NULL, "remove_ack");
4455 if (param->bchannel.addr)
4456 add_trace("address", NULL, "%x", param->bchannel.addr);
4462 if (param->threepty.begin)
4463 trace_header("Begin3PTY", dir);
4464 if (param->threepty.end)
4465 trace_header("End3PTY", dir);
4466 if (param->threepty.invoke)
4467 add_trace("action", NULL, "invoke");
4468 if (param->threepty.result)
4469 add_trace("action", NULL, "result");
4470 if (param->threepty.error)
4471 add_trace("action", NULL, "error");
4472 add_trace("invoke-id", NULL, "%d", param->threepty.invoke_id);
4476 case MESSAGE_DISABLE_DEJITTER:
4477 trace_header("DISBALE_DEJITTER", dir);
4479 add_trace("queue", NULL, "%d", param->queue);
4484 PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
4488 void EndpointAppPBX::message_disconnect_port(struct port_list *portlist, int cause, int location, const char *display)
4490 struct lcr_msg *message;
4494 if (!portlist->port_id)
4497 if (!e_connectedmode) {
4498 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DISCONNECT);
4499 message->param.disconnectinfo.cause = cause;
4500 message->param.disconnectinfo.location = location;
4502 SCPY(message->param.disconnectinfo.display, display);
4504 SCPY(message->param.disconnectinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4506 message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_NOTIFY);
4508 SCPY(message->param.notifyinfo.display, display);
4510 SCPY(message->param.notifyinfo.display, get_isdn_cause(cause, location, e_ext.display_cause));
4512 message_put(message);
4513 logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);