class EndpointAppPBX *apppbx_first = NULL;
+int action_timeout(struct lcr_timer *timer, void *instance, int index);
+int match_timeout(struct lcr_timer *timer, void *instance, int index);
+int redial_timeout(struct lcr_timer *timer, void *instance, int index);
+int powerdial_timeout(struct lcr_timer *timer, void *instance, int index);
+int cfnr_timeout(struct lcr_timer *timer, void *instance, int index);
+int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index);
+int password_timeout(struct lcr_timer *timer, void *instance, int index);
+int callback_timeout(struct lcr_timer *timer, void *instance, int index);
+
/*
* EndpointAppPBX constructor
*/
{
class EndpointAppPBX **apppointer;
+ memset(&e_crypt_handler, 0, sizeof(e_crypt_handler));
+ add_timer(&e_crypt_handler, crypt_handler, this, 0);
+ memset(&e_vbox_refresh, 0, sizeof(e_vbox_refresh));
+ add_timer(&e_vbox_refresh, vbox_refresh, this, 0);
+ memset(&e_action_timeout, 0, sizeof(e_action_timeout));
+ add_timer(&e_action_timeout, action_timeout, this, 0);
+ memset(&e_match_timeout, 0, sizeof(e_match_timeout));
+ add_timer(&e_match_timeout, match_timeout, this, 0);
+ memset(&e_redial_timeout, 0, sizeof(e_redial_timeout));
+ add_timer(&e_redial_timeout, redial_timeout, this, 0);
+ memset(&e_powerdial_timeout, 0, sizeof(e_powerdial_timeout));
+ add_timer(&e_powerdial_timeout, powerdial_timeout, this, 0);
+ memset(&e_cfnr_timeout, 0, sizeof(e_cfnr_timeout));
+ add_timer(&e_cfnr_timeout, cfnr_timeout, this, 0);
+ memset(&e_cfnr_call_timeout, 0, sizeof(e_cfnr_call_timeout));
+ add_timer(&e_cfnr_call_timeout, cfnr_call_timeout, this, 0);
+ memset(&e_callback_timeout, 0, sizeof(e_callback_timeout));
+ add_timer(&e_callback_timeout, callback_timeout, this, 0);
+ memset(&e_password_timeout, 0, sizeof(e_password_timeout));
+ add_timer(&e_password_timeout, password_timeout, this, 0);
+ e_powerdial_on = 0;
+
/* add application to chain */
next = NULL;
apppointer = &apppbx_first;
memset(&e_connectinfo, 0, sizeof(struct connect_info));
memset(&e_redirinfo, 0, sizeof(struct redir_info));
memset(&e_capainfo, 0, sizeof(struct capa_info));
+ memset(&e_rtpinfo, 0, sizeof(struct rtp_info));
e_start = e_stop = 0;
e_origin = origin;
e_ruleset = ruleset_main;
e_rule = e_ruleset->rule_first;
e_rule_nesting = 0;
e_action = NULL;
- e_action_timeout = 0;
- e_match_timeout = 0;
e_match_to_action = NULL;
e_select = 0;
e_extdialing = e_dialinginfo.id;
e_hold = 0;
// e_join_tone[0] = e_hold_tone[0] = '\0';
e_join_pattern /*= e_hold_pattern*/ = 0;
- e_redial = 0;
e_tone[0] = '\0';
e_adminid = 0; // will be set, if call was initiated via admin socket
- e_powerdialing = 0;
e_powerdelay = 0;
e_powerlimit = 0;
- e_callback = 0;
e_cbdialing[0] = '\0';
e_cbcaller[0] = '\0';
e_cbto[0] = '\0';
e_dtmf_time = 0;
e_dtmf_last = 0;
e_enablekeypad = 0;
- e_cfnr_release = 0;
- e_cfnr_call = 0;
- e_password_timeout = 0;
e_multipoint_cause = 0;
e_multipoint_location = 0;
e_dialing_queue[0] = '\0';
{
class EndpointAppPBX *temp, **tempp;
+ del_timer(&e_crypt_handler);
+ del_timer(&e_vbox_refresh);
+ del_timer(&e_action_timeout);
+ del_timer(&e_match_timeout);
+ del_timer(&e_redial_timeout);
+ del_timer(&e_powerdial_timeout);
+ del_timer(&e_cfnr_timeout);
+ del_timer(&e_cfnr_call_timeout);
+ del_timer(&e_callback_timeout);
+ del_timer(&e_password_timeout);
+
/* detach */
temp =apppbx_first;
tempp = &apppbx_first;
/* release join and port (as specified)
*/
-void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause)
+void EndpointAppPBX::release(int release, int joinlocation, int joincause, int portlocation, int portcause, int force)
{
struct port_list *portlist;
struct lcr_msg *message;
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = portcause;
message->param.disconnectinfo.location = portlocation;
+ message->param.disconnectinfo.force = force; // set, if port should release imediately
message_put(message);
logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
}
}
/* if callback is enabled, call back with the given caller id */
- if (e_callback) {
+ if (e_callback_timeout.active) {
/* reset some stuff */
new_state(EPOINT_STATE_IDLE);
memset(&e_connectinfo, 0, sizeof(struct connect_info));
if (e_ruleset)
e_rule = e_ruleset->rule_first;
e_action = NULL;
- e_action_timeout = 0;
- e_match_timeout = 0;
+ unsched_timer(&e_action_timeout);
+ unsched_timer(&e_match_timeout);
+ unsched_timer(&e_cfnr_timeout);
+ unsched_timer(&e_cfnr_call_timeout);
e_match_to_action = NULL;
//e_select = 0;
e_extdialing = e_dialinginfo.id;
e_dtmf_time = 0;
e_dtmf_last = 0;
e_enablekeypad = 0;
- e_cfnr_release = 0;
- e_cfnr_call = 0;
e_multipoint_cause = 0;
e_multipoint_location = 0;
e_dialing_queue[0] = '\0';
}
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) do pending release of epoint itself.\n", ea_endpoint->ep_serial);
- ea_endpoint->ep_use--; /* when e_lock is 0, the endpoint will be deleted */
+ if (--ea_endpoint->ep_use <= 0) /* when e_lock is 0, the endpoint will be deleted */
+ trigger_work(&ea_endpoint->ep_delete);
return;
}
}
}
}
+/* hunts for the given interface
+ * it does not need to have an mISDNport instance */
+struct interface *EndpointAppPBX::hunt_interface(char *ifname)
+{
+ struct interface *interface;
+ int there_is_an_external = 0;
+
+ interface = interface_first;
+
+ /* first find the given interface or, if not given, one with no extension */
+ checknext:
+ if (!interface) {
+ if (!there_is_an_external && !(ifname && ifname[0])) {
+ trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
+ add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
+ end_trace();
+ }
+ return(NULL);
+ }
+
+ /* check for given interface */
+ if (ifname && ifname[0]) {
+ if (!strcasecmp(interface->name, ifname)) {
+ /* found explicit interface */
+ trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
+ end_trace();
+ goto foundif;
+ }
+ } else {
+ if (interface->external) {
+ there_is_an_external = 1;
+ /* found non extension */
+ trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", interface->name);
+ end_trace();
+ goto foundif;
+ }
+ }
+
+ interface = interface->next;
+ goto checknext;
+foundif:
+
+ return interface;
+}
+
/*
* hunts an mISDNport that is available for an outgoing call
if (!interface) {
if (!there_is_an_external && !(ifname && ifname[0])) {
trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
- add_trace("info", NULL, "Add 'external' parameter to interface.conf.");
+ add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
end_trace();
}
return(NULL);
* ports will be created and a setup is sent if everything is ok. otherwhise
* the endpoint is destroyed.
*/
-void EndpointAppPBX::out_setup(void)
+void EndpointAppPBX::out_setup(int cfnr)
{
struct dialing_info dialinginfo;
class Port *port;
int cause = CAUSE_RESSOURCEUNAVAIL;
const char *p;
char cfp[64];
+ struct interface *interface;
struct mISDNport *mISDNport;
char portname[32];
char *dirname;
int channel = 0;
int earlyb;
int mode = B_MODE_TRANSPARENT;
+ struct admin_list *admin;
/* set bchannel mode */
mode = e_capainfo.source_mode;
}
if (atemp) {
PERROR("EPOINT(%d) noknocking and currently a call\n", ea_endpoint->ep_serial);
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYSPE_ join, port */
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_BUSY, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYSPE_ join, port */
return; /* must exit here */
}
}
// if (!read_extension(&e_ext, exten))
if (!read_extension(&e_ext, e_dialinginfo.id)) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) extension %s not configured\n", ea_endpoint->ep_serial, e_dialinginfo.id);
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
return; /* must exit here */
}
+ e_dialinginfo.sending_complete = 1;
if (e_dialinginfo.itype == INFO_ITYPE_VBOX) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing directly to VBOX\n", ea_endpoint->ep_serial);
p = e_ext.cfnr;
if (*p) {
/* when cfnr is done, out_setup() will setup the call */
- if (e_cfnr_call) {
+ if (cfnr) {
/* present to forwarded party */
if (e_ext.anon_ignore && e_callerinfo.id[0]) {
e_callerinfo.present = INFO_PRESENT_ALLOWED;
goto cfnr_only;
}
if (!!strcmp(p, "vbox") || (e_capainfo.bearer_capa==INFO_BC_AUDIO) || (e_capainfo.bearer_capa==INFO_BC_SPEECH)) {
- e_cfnr_release = now + e_ext.cfnr_delay;
- e_cfnr_call = now + e_ext.cfnr_delay + 1; /* call one second after release */
+ schedule_timer(&e_cfnr_timeout, e_ext.cfnr_delay, 0);
+ schedule_timer(&e_cfnr_call_timeout, e_ext.cfnr_delay + 1, 0); /* call one second after release */
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);
}
}
SCCAT(ifname, *p++);
if (*p == ',')
p++;
- /* found interface */
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
- /* hunt for mISDNport and create Port */
- mISDNport = hunt_port(ifname, &channel);
- if (!mISDNport) {
- trace_header("INTERFACE (not found or busy)", DIRECTION_NONE);
+ /* search interface */
+ interface = hunt_interface(ifname);
+ if (!interface) {
+ trace_header("INTERFACE (not found)", DIRECTION_NONE);
add_trace("interface", NULL, "%s", ifname);
end_trace();
continue;
}
- /* creating INTERNAL port */
- SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
-#ifdef WITH_SS5
- if (mISDNport->ss5)
- port = ss5_hunt_line(mISDNport);
- else
+ /* found interface */
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
+#ifdef WITH_GSM_BS
+ if (interface->gsm_bs) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
+ } else
#endif
- if (!mISDNport->gsm)
- port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
- else
-#ifdef WITH_GSM
- port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-#else
- port = NULL;
+#ifdef WITH_GSM_MS
+ if (interface->gsm_ms) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
+ } else
#endif
+#ifdef WITH_GSM_MS
+ if (interface->sip) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+ } else
+#endif
+ {
+ /* hunt for mISDNport and create Port */
+ mISDNport = hunt_port(ifname, &channel);
+ if (!mISDNport) {
+ trace_header("INTERFACE (busy)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
+ end_trace();
+ continue;
+ }
+
+ SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+#ifdef WITH_SS5
+ if (mISDNport->ss5)
+ port = ss5_hunt_line(mISDNport);
+ else
+#endif
+ if (mISDNport->ifport->remote) {
+ admin = admin_first;
+ while(admin) {
+ if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
+ break;
+ admin = admin->next;
+ }
+ if (!admin) {
+ trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+ add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+ end_trace();
+ continue;
+ }
+ port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
+ } else
+ port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+ }
if (!port)
- FATAL("No memory for Port instance\n");
+ FATAL("Failed to create Port instance\n");
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
memset(&dialinginfo, 0, sizeof(dialinginfo));
SCPY(dialinginfo.id, e_dialinginfo.id);
dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
dialinginfo.ntype = e_dialinginfo.ntype;
/* create port_list relation */
- portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
+ portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, interface->is_earlyb == IS_YES);
if (!portlist) {
PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
delete port;
memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
+ memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
//terminal SCPY(message->param.setup.from_terminal, e_ext.number);
//terminal if (e_dialinginfo.id)
//terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
end_trace();
if (!ea_endpoint->ep_join_id)
break;
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
return; /* must exit here */
}
break;
p++;
/* found number */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
- /* hunt for mISDNport and create Port */
- /* hunt for mISDNport and create Port */
- mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
- if (!mISDNport) {
- trace_header("INTERFACE (too busy)", DIRECTION_NONE);
- add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
+ /* search interface */
+ interface = hunt_interface(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL);
+ if (!interface) {
+ trace_header("INTERFACE (not found)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
end_trace();
goto check_anycall_extern;
}
- /* creating EXTERNAL port*/
- SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
-#ifdef WITH_SS5
- if (mISDNport->ss5)
- port = ss5_hunt_line(mISDNport);
- else
+ /* found interface */
+#ifdef WITH_GSM_BS
+ if (interface->gsm_bs) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface);
+ } else
#endif
- if (!mISDNport->gsm)
- port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
- else
-#ifdef WITH_GSM
- port = new Pgsm(PORT_TYPE_GSM_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-#else
- port = NULL;
+#ifdef WITH_GSM_MS
+ if (interface->gsm_ms) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface);
+ } else
+#endif
+#ifdef WITH_GSM_MS
+ if (interface->sip) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+ } else
#endif
+ {
+ /* hunt for mISDNport and create Port */
+ mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
+ if (!mISDNport) {
+ trace_header("INTERFACE (too busy)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
+ end_trace();
+ goto check_anycall_extern;
+ }
+ /* creating EXTERNAL port*/
+ SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+#ifdef WITH_SS5
+ if (mISDNport->ss5)
+ port = ss5_hunt_line(mISDNport);
+ else
+#endif
+ if (mISDNport->ifport->remote) {
+ admin = admin_first;
+ while(admin) {
+ if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
+ break;
+ admin = admin->next;
+ }
+ if (!admin) {
+ trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+ add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+ end_trace();
+ continue;
+ }
+ port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
+ } else
+ port = new Pdss1((mISDNport->ntmode)?PORT_TYPE_DSS1_NT_OUT:PORT_TYPE_DSS1_TE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
+ }
if (!port)
FATAL("No memory for Port instance\n");
- earlyb = mISDNport->earlyb;
+ earlyb = (interface->is_earlyb == IS_YES);
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
memset(&dialinginfo, 0, sizeof(dialinginfo));
if (e_dialinginfo.keypad[0])
SCPY(dialinginfo.id, number);
dialinginfo.itype = INFO_ITYPE_ISDN;
dialinginfo.ntype = e_dialinginfo.ntype;
- portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
+ dialinginfo.sending_complete = e_dialinginfo.sending_complete;
+ portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, earlyb);
if (!portlist) {
PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
delete port;
memcpy(&message->param.setup.redirinfo, &e_redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &e_callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &e_capainfo, sizeof(struct capa_info));
+ memcpy(&message->param.setup.rtpinfo, &e_rtpinfo, sizeof(struct rtp_info));
//terminal SCPY(message->param.setup.from_terminal, e_ext.number);
//terminal if (e_dialinginfo.id)
//terminal SCPY(message->param.setup.to_terminal, e_dialinginfo.id);
end_trace();
if (!ea_endpoint->ep_join_id)
break;
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOCHANNEL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
return; /* must exit here */
}
break;
}
+int action_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
-/* handler for endpoint
- */
+ if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
+ return 0;
+
+ unsched_timer(&ea->e_redial_timeout);
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea->ea_endpoint->ep_serial);
+ ea->e_multipoint_cause = 0;
+ ea->e_multipoint_location = 0;
+ ea->new_state(EPOINT_STATE_IN_OVERLAP);
+ ea->e_join_pattern = 0;
+ ea->process_dialing(1);
+ /* we must exit, because our endpoint might be gone */
+
+ return 0;
+}
-extern int quit;
-int EndpointAppPBX::handler(void)
+int match_timeout(struct lcr_timer *timer, void *instance, int index)
{
- if (e_crypt_state!=CM_ST_NULL) {
- cryptman_handler();
- }
-
- /* process answering machine (play) handling */
- if (e_action) {
- if (e_action->index == ACTION_VBOX_PLAY)
- vbox_handler();
-
- /* process action timeout */
- if (e_action_timeout)
- if (now_d >= e_action_timeout) {
- if (e_state!=EPOINT_STATE_CONNECT) {
- e_redial = 0;
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current action timed out.\n", ea_endpoint->ep_serial);
- e_multipoint_cause = 0;
- e_multipoint_location = 0;
- new_state(EPOINT_STATE_IN_OVERLAP);
- e_join_pattern = 0;
- process_dialing();
- return(1); /* we must exit, because our endpoint might be gone */
- } else
- e_action_timeout = 0;
- }
- } else {
- /* process action timeout */
- if (e_match_timeout)
- if (now_d >= e_match_timeout) {
- e_redial = 0;
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea_endpoint->ep_serial);
- process_dialing();
- return(1); /* we must exit, because our endpoint might be gone */
- }
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+
+ if (!ea->e_action) {
+ unsched_timer(&ea->e_redial_timeout);
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) we got a match timeout.\n", ea->ea_endpoint->ep_serial);
+ ea->process_dialing(0);
+ /* we must exit, because our endpoint might be gone */
}
+ return 0;
+}
- /* process redialing (epoint redials to port) */
- if (e_redial) {
- if (now_d >= e_redial) {
- e_redial = 0;
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea_endpoint->ep_serial);
+int redial_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
- new_state(EPOINT_STATE_OUT_SETUP);
- /* call special setup routine */
- out_setup();
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial.\n", ea->ea_endpoint->ep_serial);
- return(1);
- }
- }
+ ea->new_state(EPOINT_STATE_OUT_SETUP);
+ /* call special setup routine */
+ ea->out_setup(0);
- /* process powerdialing (epoint redials to epoint) */
- if (e_powerdialing > 0) {
- if (now_d >= e_powerdialing) {
- e_powerdialing = -1; /* leave power dialing on */
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea_endpoint->ep_serial);
+ return 0;
+}
- /* redial */
- e_ruleset = ruleset_main;
- if (e_ruleset)
- e_rule = e_ruleset->rule_first;
- e_action = NULL;
- new_state(EPOINT_STATE_IN_OVERLAP);
- process_dialing();
- return(1);
- }
- }
+int powerdial_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
- /* process call forward no response */
- if (e_cfnr_release) {
- struct port_list *portlist;
- struct lcr_msg *message;
+ /* leave power dialing on */
+ ea->e_powerdial_on = 1;
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting redial of powerdial.\n", ea->ea_endpoint->ep_serial);
- if (now >= e_cfnr_release) {
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea_endpoint->ep_serial);
- e_cfnr_release = 0;
+ /* redial */
+ ea->e_ruleset = ruleset_main;
+ if (ea->e_ruleset)
+ ea->e_rule = ea->e_ruleset->rule_first;
+ ea->e_action = NULL;
+ ea->new_state(EPOINT_STATE_IN_OVERLAP);
+ ea->process_dialing(0);
- /* release all ports */
- while((portlist = ea_endpoint->ep_portlist)) {
- message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
- ea_endpoint->free_portlist(portlist);
- }
- /* put on hold */
- message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
- message->param.audiopath = 0;
- message_put(message);
- /* indicate no patterns */
- message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
- message_put(message);
- /* set setup state, since we have no response from the new join */
- new_state(EPOINT_STATE_OUT_SETUP);
- }
- } else
- if (e_cfnr_call) {
- if (now >= e_cfnr_call) {
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-busy time has expired, calling the forwarded number: %s.\n", ea_endpoint->ep_serial, e_ext.cfnr);
- out_setup();
- e_cfnr_call = 0;
- }
+ return 0;
+}
+
+int cfnr_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+ struct port_list *portlist;
+ struct lcr_msg *message;
+
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) call-forward-no-response time has expired, hanging up.\n", ea->ea_endpoint->ep_serial);
+
+ /* release all ports */
+ while((portlist = ea->ea_endpoint->ep_portlist)) {
+ message = message_create(ea->ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
+ message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal clearing */
+ message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+ message_put(message);
+ ea->logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+ ea->ea_endpoint->free_portlist(portlist);
}
+ /* put on hold */
+ message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
+ message->param.audiopath = 0;
+ message_put(message);
+ /* indicate no patterns */
+ message = message_create(ea->ea_endpoint->ep_serial, ea->ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_NOPATTERN);
+ message_put(message);
+ /* set setup state, since we have no response from the new join */
+ ea->new_state(EPOINT_STATE_OUT_SETUP);
- /* handle connection to user */
- if (e_state == EPOINT_STATE_IDLE) {
+ return 0;
+}
+
+int cfnr_call_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+
+ 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);
+ ea->out_setup(1);
+
+ return 0;
+}
+
+int callback_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+
+ if (ea->e_state == EPOINT_STATE_IDLE) {
/* epoint is idle, check callback */
- if (e_callback)
- if (now_d >= e_callback) {
- e_callback = 0; /* done with callback */
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea_endpoint->ep_serial);
- new_state(EPOINT_STATE_OUT_SETUP);
- out_setup();
- return(1);
- }
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) starting callback.\n", ea->ea_endpoint->ep_serial);
+ ea->new_state(EPOINT_STATE_OUT_SETUP);
+ ea->out_setup(0);
}
- /* check for password timeout */
- if (e_action)
- if (e_action->index==ACTION_PASSWORD || e_action->index==ACTION_PASSWORD_WRITE) {
+ return 0;
+}
+
+int password_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
+
+ if (ea->e_action->index==ACTION_PASSWORD || ea->e_action->index==ACTION_PASSWORD_WRITE) {
struct port_list *portlist;
- if (now >= e_password_timeout) {
- e_ruleset = ruleset_main;
- if (e_ruleset)
- e_rule = e_ruleset->rule_first;
- e_action = NULL;
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea_endpoint->ep_serial, e_extdialing);
- trace_header("PASSWORD timeout", DIRECTION_NONE);
- end_trace();
- e_connectedmode = 0;
- e_dtmf = 0;
- new_state(EPOINT_STATE_OUT_DISCONNECT);
- portlist = ea_endpoint->ep_portlist;
- if (portlist) {
- message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
- set_tone(portlist, "cause_10");
- }
- return(1);
+ ea->e_ruleset = ruleset_main;
+ if (ea->e_ruleset)
+ ea->e_rule = ea->e_ruleset->rule_first;
+ ea->e_action = NULL;
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) password timeout %s\n", ea->ea_endpoint->ep_serial, ea->e_extdialing);
+ ea->trace_header("PASSWORD timeout", DIRECTION_NONE);
+ end_trace();
+ ea->e_connectedmode = 0;
+ ea->e_dtmf = 0;
+ ea->new_state(EPOINT_STATE_OUT_DISCONNECT);
+ portlist = ea->ea_endpoint->ep_portlist;
+ if (portlist) {
+ ea->message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+ ea->set_tone(portlist, "cause_10");
}
}
-
- return(0);
-}
+ return 0;
+}
/* doing a hookflash */
void EndpointAppPBX::hookflash(void)
{
class Port *port;
+ time_t now;
/* be sure that we are active */
notify_active();
port->set_echotest(0);
}
if (ea_endpoint->ep_join_id) {
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
}
e_ruleset = ruleset_main;
if (e_ruleset)
e_join_pattern = 0;
if (e_dialinginfo.id[0]) {
set_tone(ea_endpoint->ep_portlist, "dialing");
- process_dialing();
+ process_dialing(0);
} else {
set_tone(ea_endpoint->ep_portlist, "dialpbx");
}
+ time(&now);
e_dtmf_time = now;
e_dtmf_last = '\0';
}
char buffer[256];
int writeext; /* flags need to write extension after modification */
class Port *port;
- struct interface *interface;
logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
+ memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
+
+ /* convert (inter-)national number type */
+ SCPY(e_dialinginfo.id, numberrize_callerinfo(e_dialinginfo.id, e_dialinginfo.ntype, options.national, options.international));
+ e_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
+
// e_dtmf = param->setup.dtmf;
/* screen incoming caller id */
- interface = interface_first;
- while(interface) {
- if (!strcmp(e_callerinfo.interface, interface->name)) {
- break;
- }
- interface = interface->next;
- }
- if (interface) {
- do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, interface);
- do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, interface);
+ if (e_callerinfo.interface[0]) {
+ do_screen(0, e_callerinfo.id, sizeof(e_callerinfo.id), &e_callerinfo.ntype, &e_callerinfo.present, e_callerinfo.interface);
+ do_screen(0, e_callerinfo.id2, sizeof(e_callerinfo.id2), &e_callerinfo.ntype2, &e_callerinfo.present2, e_callerinfo.interface);
}
/* process extension */
else
set_tone(portlist, "dialtone");
}
- process_dialing();
+ process_dialing(0);
if (e_state == EPOINT_STATE_IN_SETUP) {
/* request MORE info, if not already at higher state */
new_state(EPOINT_STATE_IN_OVERLAP);
/* port MESSAGE_INFORMATION */
void EndpointAppPBX::port_information(struct port_list *portlist, int message_type, union parameter *param)
{
+ struct lcr_msg *message;
+
logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
/* ignore information message without digit information */
if (e_action->index == ACTION_VBOX_PLAY) {
/* concat dialing string */
SCAT(e_dialinginfo.id, param->information.id);
- process_dialing();
+ process_dialing(0);
return;
}
/* keypad when connected */
if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
- if (e_ext.keypad || e_enablekeypad) {
+ if (e_enablekeypad) {
+ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
+ memcpy(&message->param, param, sizeof(union parameter));
+ message_put(message);
+ return;
+ }
+ if (e_ext.keypad) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) keypad information received during connect: %s.\n", ea_endpoint->ep_serial, param->information.id);
/* processing keypad function */
if (param->information.id[0] == '0') {
}
/* concat dialing string */
SCAT(e_dialinginfo.id, param->information.id);
- process_dialing();
+ process_dialing(0);
}
/* port MESSAGE_DTMF */
void EndpointAppPBX::port_dtmf(struct port_list *portlist, int message_type, union parameter *param)
{
+ time_t now;
+ struct lcr_msg *message;
+
+ time(&now);
+
/* only if dtmf detection is enabled */
if (!e_dtmf) {
trace_header("DTMF (disabled)", DIRECTION_IN);
if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
- process_dialing();
+ process_dialing(0);
}
/* continue to process *X# sequences */
}
/* check for *X# sequence */
if (e_state == EPOINT_STATE_CONNECT || e_state == EPOINT_STATE_IN_ALERTING) {
+ if (e_enablekeypad) {
+ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, message_type);
+ memcpy(&message->param, param, sizeof(union parameter));
+ message_put(message);
+ return;
+ }
if (e_dtmf_time+3 < now) {
/* the last digit was too far in the past to be a sequence */
if (param->dtmf == '*')
if (strlen(e_dialinginfo.id)+1 < sizeof(e_dialinginfo.id)) {
e_dialinginfo.id[strlen(e_dialinginfo.id)+1] = '\0';
e_dialinginfo.id[strlen(e_dialinginfo.id)] = param->dtmf;
- process_dialing();
+ process_dialing(0);
}
}
}
unsigned int port_id = portlist->port_id;
struct port_list *tportlist;
class Port *port;
- struct interface *interface;
+ time_t now;
logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
}
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) removing all other ports (end)\n", ea_endpoint->ep_serial);
+ time(&now);
e_start = now;
- /* screen incoming connected id */
- interface = interface_first;
- while(interface) {
- if (!strcmp(e_connectinfo.interface, interface->name)) {
- break;
- }
- interface = interface->next;
- }
- if (interface)
- do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, interface);
+ if (e_callerinfo.interface[0])
+ do_screen(0, e_connectinfo.id, sizeof(e_connectinfo.id), &e_connectinfo.ntype, &e_connectinfo.present, e_connectinfo.interface);
/* screen connected name */
if (e_ext.name[0])
message_put(message);
}
- e_cfnr_call = e_cfnr_release = 0;
+ unsched_timer(&e_cfnr_timeout);
+ unsched_timer(&e_cfnr_call_timeout);
if (e_ext.number[0])
e_dtmf = 1; /* allow dtmf */
/* other calls with no caller id (or not available for the extension) and force colp */
if ((e_connectinfo.id[0]=='\0' || (e_connectinfo.present==INFO_PRESENT_RESTRICTED && !e_ext.anon_ignore))&& e_ext.colp==COLP_FORCE) {
e_connectinfo.ntype = INFO_NTYPE_NOTPRESENT;
- if (portlist->port_type==PORT_TYPE_DSS1_TE_OUT || portlist->port_type==PORT_TYPE_DSS1_NT_OUT || portlist->port_type==PORT_TYPE_GSM_OUT) { /* external extension answered */
+ if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT) {
+ /* external extension answered */
port = find_port_id(portlist->port_id);
if (port) {
SCPY(e_connectinfo.id, nationalize_callerinfo(port->p_dialinginfo.id, &e_connectinfo.ntype, options.national, options.international));
/* make call state to enter password */
new_state(EPOINT_STATE_IN_OVERLAP);
e_action = &action_password_write;
- e_match_timeout = 0;
+ unsched_timer(&e_match_timeout);
e_match_to_action = NULL;
e_dialinginfo.id[0] = '\0';
e_extdialing = strchr(e_dialinginfo.id, '\0');
- e_password_timeout = now+20;
- process_dialing();
+ schedule_timer(&e_password_timeout, 20, 0);
+ process_dialing(0);
} else {
/* incoming call (callback) */
e_ruleset = ruleset_main;
e_extdialing = e_dialinginfo.id;
if (e_dialinginfo.id[0]) {
set_tone(portlist, "dialing");
- process_dialing();
+ process_dialing(0);
} else {
set_tone(portlist, "dialpbx");
}
}
}
- e_cfnr_call = e_cfnr_release = 0;
+ unsched_timer(&e_cfnr_timeout);
+ unsched_timer(&e_cfnr_call_timeout);
/* process hangup */
process_hangup(e_join_cause, e_join_location);
}
if (message_type == MESSAGE_RELEASE)
ea_endpoint->free_portlist(portlist);
- release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, callcause, portcause */
+ release(RELEASE_ALL, location, cause, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, callcause, portcause */
return; /* must exit here */
}
add_trace("state", NULL, "outgoing setup/dialing");
end_trace();
/* no user responding */
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
return; /* must exit here */
case PORT_STATE_IN_SETUP:
end_trace();
param->disconnectinfo.cause = CAUSE_NOUSER; /* no user responding */
param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOUSER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
return; /* must exit here */
case PORT_STATE_IN_PROCEEDING:
end_trace();
param->disconnectinfo.cause = CAUSE_NOANSWER; /* no answer */
param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NOANSWER, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
return; /* must exit here */
case PORT_STATE_CONNECT:
end_trace();
param->disconnectinfo.cause = CAUSE_NORMAL; /* normal */
param->disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
return; /* must exit here */
case PORT_STATE_IN_ALERTING:
add_trace("state", NULL, "disconnect");
end_trace();
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) in this special case, we release due to disconnect timeout.\n", ea_endpoint->ep_serial);
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL);
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
return; /* must exit here */
default:
message_disconnect_port(portlist, param->disconnectinfo.cause, param->disconnectinfo.location, "");
portlist = portlist->next;
}
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
}
/* port MESSAGE_NOTIFY */
}
+/* port MESSAGE_PROGRESS */
+void EndpointAppPBX::port_progress(struct port_list *portlist, int message_type, union parameter *param)
+{
+ logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+ struct lcr_msg *message;
+
+ /* signal to call tool */
+ admin_call_response(e_adminid, ADMIN_CALL_PROGRESS, "", 0, param->progressinfo.location, param->progressinfo.progress);
+
+ /* send progress to call if available */
+ if (ea_endpoint->ep_join_id) {
+ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_PROGRESS);
+ memcpy(&message->param.progressinfo, ¶m->progressinfo, sizeof(struct progress_info));
+ message_put(message);
+ }
+
+}
+
/* port MESSAGE_FACILITY */
void EndpointAppPBX::port_facility(struct port_list *portlist, int message_type, union parameter *param)
{
}
+/* port MESSAGE_ENABLEKEYPAD */
+void EndpointAppPBX::port_enablekeypad(struct port_list *portlist, int message_type, union parameter *param)
+{
+ struct lcr_msg *message;
+
+ logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+ message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_ENABLEKEYPAD);
+ memcpy(&message->param, param, sizeof(union parameter));
+ message_put(message);
+}
+
/* port sends message to the endpoint
*/
// PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
switch(message_type) {
- case MESSAGE_DATA: /* data from port */
- /* check if there is a call */
- if (!ea_endpoint->ep_join_id)
- break;
- /* continue if only one portlist */
- if (ea_endpoint->ep_portlist->next != NULL)
- break;
- /* forward message */
- message_forward(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, param);
- break;
-
case MESSAGE_TONE_EOF: /* tone is end of file */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) current tone is now end of file.\n", ea_endpoint->ep_serial);
if (e_action) {
port_notify(portlist, message_type, param);
break;
+ /* PORT sends a PROGRESS message */
+ case MESSAGE_PROGRESS:
+ 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);
+ port_progress(portlist, message_type, param);
+ break;
+
/* PORT sends a SUSPEND message */
case MESSAGE_SUSPEND:
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);
break;
#endif
+ /* PORT requests DTMF */
+ case MESSAGE_ENABLEKEYPAD:
+ 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);
+ port_enablekeypad(portlist, message_type, param);
+ break;
+
default:
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);
void EndpointAppPBX::join_connect(struct port_list *portlist, int message_type, union parameter *param)
{
struct lcr_msg *message;
+ time_t now;
new_state(EPOINT_STATE_CONNECT);
// UCPY(e_join_tone, "");
if (e_ext.number[0])
e_dtmf = 1; /* allow dtmf */
- e_powerdialing = 0;
+ e_powerdial_on = 0;
+ unsched_timer(&e_powerdial_timeout);
memcpy(&e_connectinfo, ¶m->connectinfo, sizeof(e_callerinfo));
if(portlist) {
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_CONNECT);
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
message->param.audiopath = 1;
message_put(message);
+ time(&now);
e_start = now;
}
char cause[16];
struct lcr_msg *message;
struct port_list *portlist = NULL;
+ time_t now;
/* be sure that we are active */
notify_active();
e_tx_state = NOTIFY_STATE_ACTIVE;
- /* we are powerdialing, if e_powerdialing is set and limit is not exceeded if given */
- if (e_powerdialing && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+ /* we are powerdialing, if e_powerdial_on is set and limit is not exceeded if given */
+ if (e_powerdial_on && ((e_powercount+1)<e_powerlimit || e_powerlimit<1)) {
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL,0 ); /* RELEASE_TYPE, join, port */
/* set time for power dialing */
- e_powerdialing = now_d + e_powerdelay; /* set redial in the future */
+ schedule_timer(&e_powerdial_timeout, (int)e_powerdelay, 0); /* set redial in the future */
e_powercount++;
/* set redial tone */
}
/* set stop time */
+ time(&now);
e_stop = now;
if ((e_state!=EPOINT_STATE_CONNECT
&& e_state!=EPOINT_STATE_IN_ALERTING)
|| !ea_endpoint->ep_portlist) { /* or no port */
process_hangup(param->disconnectinfo.cause, param->disconnectinfo.location);
- release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause); /* RELEASE_TYPE, join, port */
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, param->disconnectinfo.cause, 0); /* RELEASE_TYPE, join, port */
return; /* must exit here */
}
/* save cause */
|| !e_join_pattern) { /* no patterns */
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);
if (message_type != MESSAGE_RELEASE)
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL); /* RELEASE_TYPE, join, port */
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0); /* RELEASE_TYPE, join, port */
e_join_pattern = 0;
} else { /* else we enable audio */
message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_AUDIOPATH);
new_state(EPOINT_STATE_OUT_OVERLAP);
/* get time */
- e_redial = now_d + 1; /* set redial one second in the future */
+ schedule_timer(&e_redial_timeout, 1, 0);
return;
}
/* if we have a pending redial, so we just adjust the dialing number */
- if (e_redial) {
+ if (e_redial_timeout.active) {
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);
memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
return;
memcpy(&e_dialinginfo, ¶m->setup.dialinginfo, sizeof(e_dialinginfo));
memcpy(&e_redirinfo, ¶m->setup.redirinfo, sizeof(e_redirinfo));
memcpy(&e_capainfo, ¶m->setup.capainfo, sizeof(e_capainfo));
+ memcpy(&e_rtpinfo, ¶m->setup.rtpinfo, sizeof(e_rtpinfo));
/* process (voice over) data calls */
if (e_ext.datacall && e_capainfo.bearer_capa!=INFO_BC_SPEECH && e_capainfo.bearer_capa!=INFO_BC_AUDIO) {
new_state(EPOINT_STATE_OUT_SETUP);
/* call special setup routine */
- out_setup();
+ out_setup(0);
}
/* join MESSAGE_mISDNSIGNAL */
}
}
+/* join MESSAGE_BRIDE */
+void EndpointAppPBX::join_bridge(struct port_list *portlist, int message_type, union parameter *param)
+{
+ struct lcr_msg *message;
+
+ while(portlist) {
+ message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
+ memcpy(&message->param, param, sizeof(union parameter));
+ message_put(message);
+ portlist = portlist->next;
+ }
+}
+
/* join MESSAGE_NOTIFY */
void EndpointAppPBX::join_notify(struct port_list *portlist, int message_type, union parameter *param)
{
}
}
+/* join MESSAGE_DTMF */
+void EndpointAppPBX::join_dtmf(struct port_list *portlist, int message_type, union parameter *param)
+{
+ struct lcr_msg *message;
+
+ while(portlist) {
+ message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_DTMF);
+ memcpy(&message->param, param, sizeof(union parameter));
+ message_put(message);
+ portlist = portlist->next;
+ }
+}
+
/* JOIN sends messages to the endpoint
*/
void EndpointAppPBX::ea_message_join(unsigned int join_id, int message_type, union parameter *param)
portlist = ea_endpoint->ep_portlist;
- /* send MESSAGE_DATA to port */
- if (message_type == MESSAGE_DATA) {
- if (join_id == ea_endpoint->ep_join_id) { // still linked with JOIN
- /* skip if no port relation */
- if (!portlist)
- return;
- /* skip if more than one port relation */
- if (portlist->next)
- return;
- /* forward audio data to port */
- message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
- return;
- }
- }
-
// 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);
switch(message_type) {
/* JOIN SENDS TONE message */
join_mISDNsignal(portlist, message_type, param);
break;
-#if 0
- kann nach dem test gelöscht werden, da eine direkte funktion im join und im mISDN zum austausch der message existiert
- /* JOIN requests bchannel */
- case MESSAGE_BCHANNEL: /* indicates the need of own bchannel access */
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received bchannel assignment %d from join.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->bchannel.type);
- /* only one port is expected to be connected to bchannel */
- if (!portlist)
- break;
- if (portlist->next)
- break;
- e_join_pattern = 1;
- SCPY(e_tone, "");
- set_tone(portlist, NULL);
- message = message_forward(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, param);
- logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+ /* JOIN sends bridge message */
+ case MESSAGE_BRIDGE: /* bride message to port */
+ 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);
+ join_bridge(portlist, message_type, param);
break;
-#endif
/* JOIN has pattern available */
case MESSAGE_PATTERN: /* indicating pattern available */
end_trace();
break;
+ /* JOIN sends a DTMF message */
+ case MESSAGE_DTMF:
+ 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);
+ join_dtmf(portlist, message_type, param);
+ break;
+
default:
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);
}
while(42) {
/* eliminate white spaces */
- while (*list <= ' ')
+ while (*list > '\0' && *list <= ' ')
list++;
if (*list == ',') {
list++;
break;
}
}
- if ((port->p_type==PORT_TYPE_DSS1_NT_OUT || port->p_type==PORT_TYPE_DSS1_TE_OUT || port->p_type==PORT_TYPE_GSM_OUT)
+ if ((portlist->port_type & PORT_CLASS_DIR_MASK) == PORT_CLASS_DIR_OUT
&& port->p_state==PORT_STATE_OUT_ALERTING)
if (match_list(extensions, eapp->e_ext.number)) {
found = eapp;
message_put(message);
/* beeing paranoid, we make call update */
- joinpbx->j_updatebridge = 1;
+ trigger_work(&joinpbx->j_updatebridge);
if (options.deb & DEBUG_EPOINT) {
class Join *debug_c = join_first;
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
return;
}
- if ((our_port->p_type&PORT_CLASS_mISDN_MASK) != PORT_CLASS_mISDN_DSS1) {
+ if ((our_port->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port is not isdn.\n", ea_endpoint->ep_serial);
return;
}
PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
/* mixer must update */
- our_joinpbx->j_updatebridge = 1; /* update mixer flag */
+ trigger_work(&our_joinpbx->j_updatebridge);
/* we send a retrieve to that endpoint */
// mixer will update the hold-state of the join and send it to the endpoints is changes
*errstr = "No Call";
return(1);
}
- if (((*port)->p_type&PORT_CLASS_mISDN_MASK)!=PORT_CLASS_mISDN_DSS1) { /* port is not external isdn */
+ if (((*port)->p_type & PORT_CLASS_mISDN_MASK) != PORT_CLASS_DSS1) { /* port is not external isdn */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) 2nd endpoint has not an external port.\n", ea_endpoint->ep_serial);
*errstr = "No Ext Call";
return(1);
end_trace();
break;
+ case MESSAGE_PROGRESS:
+ switch(param->progressinfo.progress) {
+ case 0x01:
+ logtext = "Call is not end to end ISDN";
+ break;
+ case 0x02:
+ logtext = "Destination address is non-ISDN";
+ break;
+ case 0x03:
+ logtext = "Origination address is non-ISDN";
+ break;
+ case 0x04:
+ logtext = "Call has returned to the ISDN";
+ break;
+ case 0x08:
+ logtext = "In-band info or pattern available";
+ break;
+ default:
+ SPRINT(buffer, "%d", param->progressinfo.progress);
+ logtext = buffer;
+
+ }
+ trace_header("PROGRESS", dir);
+ if (dir == DIRECTION_OUT)
+ add_trace("to", NULL, "CH(%lu)", port_id);
+ if (dir == DIRECTION_IN)
+ add_trace("from", NULL, "CH(%lu)", port_id);
+ add_trace("indicator", NULL, "%s", logtext);
+ switch(param->progressinfo.location) {
+ case LOCATION_USER:
+ add_trace("cause", "location", "0-User");
+ break;
+ case LOCATION_PRIVATE_LOCAL:
+ add_trace("cause", "location", "1-Local-PBX");
+ break;
+ case LOCATION_PUBLIC_LOCAL:
+ add_trace("cause", "location", "2-Local-Exchange");
+ break;
+ case LOCATION_TRANSIT:
+ add_trace("cause", "location", "3-Transit");
+ break;
+ case LOCATION_PUBLIC_REMOTE:
+ add_trace("cause", "location", "4-Remote-Exchange");
+ break;
+ case LOCATION_PRIVATE_REMOTE:
+ add_trace("cause", "location", "5-Remote-PBX");
+ break;
+ case LOCATION_INTERNATIONAL:
+ add_trace("cause", "location", "7-International-Exchange");
+ break;
+ case LOCATION_BEYOND:
+ add_trace("cause", "location", "10-Beyond-Interworking");
+ break;
+ default:
+ add_trace("cause", "location", "%d", param->progressinfo.location);
+ }
+ end_trace();
+ break;
+
case MESSAGE_INFORMATION:
trace_header("INFORMATION", dir);
if (dir == DIRECTION_OUT)