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;
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;
SCPY(msgtext, name);
/* init trace with given values */
- start_trace(0,
+ start_trace(-1,
NULL,
numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
e_dialinginfo.id,
/* 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;
}
}
/* check for channel form selection list */
*channel = 0;
- selchannel = ifport->out_channel;
- while(selchannel) {
- switch(selchannel->channel) {
- case CHANNEL_FREE: /* free channel */
- if (mISDNport->b_reserved >= mISDNport->b_num)
- break; /* all channel in use or reserverd */
- /* find channel */
- i = 0;
- while(i < mISDNport->b_num) {
- if (mISDNport->b_port[i] == NULL) {
- *channel = i+1+(i>=15);
- trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- add_trace("channel", NULL, "%d", *channel);
- end_trace();
- break;
- }
- i++;
- }
- if (*channel)
- break;
- trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
+#ifdef WITH_SS5
+ if (mISDNport->ss5) {
+ class Pss5 *port;
+ port = ss5_hunt_line(mISDNport);
+ if (port) {
+ *channel = port->p_m_b_channel;
+ trace_header("CHANNEL SELECTION (selecting SS5 channel)", DIRECTION_NONE);
add_trace("port", NULL, "%d", ifport->portnum);
add_trace("position", NULL, "%d", index);
+ add_trace("channel", NULL, "%d", *channel);
end_trace();
- break;
-
- case CHANNEL_ANY: /* don't ask for channel */
- if (mISDNport->b_reserved >= mISDNport->b_num) {
- trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
+ }
+ } else
+#endif
+ {
+ selchannel = ifport->out_channel;
+ while(selchannel) {
+ switch(selchannel->channel) {
+ case CHANNEL_FREE: /* free channel */
+ if (mISDNport->b_reserved >= mISDNport->b_num)
+ break; /* all channel in use or reserverd */
+ /* find channel */
+ i = 0;
+ while(i < mISDNport->b_num) {
+ if (mISDNport->b_port[i] == NULL) {
+ *channel = i+1+(i>=15);
+ trace_header("CHANNEL SELECTION (selecting free channel)", DIRECTION_NONE);
+ add_trace("port", NULL, "%d", ifport->portnum);
+ add_trace("position", NULL, "%d", index);
+ add_trace("channel", NULL, "%d", *channel);
+ end_trace();
+ break;
+ }
+ i++;
+ }
+ if (*channel)
+ break;
+ trace_header("CHANNEL SELECTION (no channel is 'free')", DIRECTION_NONE);
add_trace("port", NULL, "%d", ifport->portnum);
add_trace("position", NULL, "%d", index);
- add_trace("total", NULL, "%d", mISDNport->b_num);
- add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
end_trace();
- break; /* all channel in use or reserverd */
- }
- trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- end_trace();
- *channel = CHANNEL_ANY;
- break;
-
- case CHANNEL_NO: /* call waiting */
- trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- end_trace();
- *channel = CHANNEL_NO;
- break;
+ break;
- default:
- if (selchannel->channel<1 || selchannel->channel==16) {
- trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- add_trace("channel", NULL, "%d", selchannel->channel);
- end_trace();
- break; /* invalid channels */
- }
- i = selchannel->channel-1-(selchannel->channel>=17);
- if (i >= mISDNport->b_num) {
- trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
+ case CHANNEL_ANY: /* don't ask for channel */
+ if (mISDNport->b_reserved >= mISDNport->b_num) {
+ trace_header("CHANNEL SELECTION (cannot ask for 'any' channel, all reserved)", DIRECTION_NONE);
+ add_trace("port", NULL, "%d", ifport->portnum);
+ add_trace("position", NULL, "%d", index);
+ add_trace("total", NULL, "%d", mISDNport->b_num);
+ add_trace("reserved", NULL, "%d", mISDNport->b_reserved);
+ end_trace();
+ break; /* all channel in use or reserverd */
+ }
+ trace_header("CHANNEL SELECTION (using 'any' channel)", DIRECTION_NONE);
add_trace("port", NULL, "%d", ifport->portnum);
add_trace("position", NULL, "%d", index);
- add_trace("channel", NULL, "%d", selchannel->channel);
- add_trace("channels", NULL, "%d", mISDNport->b_num);
end_trace();
- break; /* channel not in port */
- }
- if (mISDNport->b_port[i] == NULL) {
- *channel = selchannel->channel;
- trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
+ *channel = CHANNEL_ANY;
+ break;
+
+ case CHANNEL_NO: /* call waiting */
+ trace_header("CHANNEL SELECTION (using 'no' channel, call-waiting)", DIRECTION_NONE);
add_trace("port", NULL, "%d", ifport->portnum);
add_trace("position", NULL, "%d", index);
- add_trace("channel", NULL, "%d", *channel);
end_trace();
+ *channel = CHANNEL_NO;
+ break;
+
+ default:
+ if (selchannel->channel<1 || selchannel->channel==16) {
+ trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
+ add_trace("port", NULL, "%d", ifport->portnum);
+ add_trace("position", NULL, "%d", index);
+ add_trace("channel", NULL, "%d", selchannel->channel);
+ end_trace();
+ break; /* invalid channels */
+ }
+ i = selchannel->channel-1-(selchannel->channel>=17);
+ if (i >= mISDNport->b_num) {
+ trace_header("CHANNEL SELECTION (channel out of range)", DIRECTION_NONE);
+ add_trace("port", NULL, "%d", ifport->portnum);
+ add_trace("position", NULL, "%d", index);
+ add_trace("channel", NULL, "%d", selchannel->channel);
+ add_trace("channels", NULL, "%d", mISDNport->b_num);
+ end_trace();
+ break; /* channel not in port */
+ }
+ if (mISDNport->b_port[i] == NULL) {
+ *channel = selchannel->channel;
+ trace_header("CHANNEL SELECTION (selecting given channel)", DIRECTION_NONE);
+ add_trace("port", NULL, "%d", ifport->portnum);
+ add_trace("position", NULL, "%d", index);
+ add_trace("channel", NULL, "%d", *channel);
+ end_trace();
+ break;
+ }
break;
}
- break;
+ if (*channel)
+ break; /* found channel */
+ selchannel = selchannel->next;
}
- if (*channel)
- break; /* found channel */
- selchannel = selchannel->next;
}
/* if channel was found, return mISDNport and channel */
}
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 */
}
p = e_ext.cfnr;
if (*p) {
/* when cfnr is done, out_setup() will setup the call */
- if (e_cfnr_call) {
+ if (e_cfnr_call_timeout.active) {
/* 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);
}
}
}
/* 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
+#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
if (mISDNport) {
/* 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
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");
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;
/* *********************** external call */
default:
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: '%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id);
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dialing external: called='%s' keypad='%s'\n", ea_endpoint->ep_serial, e_dialinginfo.id, e_dialinginfo.keypad);
/* call to extenal interfaces */
- p = e_dialinginfo.id;
+ if (e_dialinginfo.keypad[0])
+ p = e_dialinginfo.keypad;
+ else
+ p = e_dialinginfo.id;
do {
number[0] = '\0';
while(*p!=',' && *p!='\0')
}
/* 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->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
earlyb = mISDNport->earlyb;
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) created port %s\n", ea_endpoint->ep_serial, port->p_name);
memset(&dialinginfo, 0, sizeof(dialinginfo));
- SCPY(dialinginfo.id, number);
+ if (e_dialinginfo.keypad[0])
+ SCPY(dialinginfo.keypad, number);
+ else
+ 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);
//printf("EXTERNAL caller=%s,id=%s,dial=%s\n", param.setup.networkid, param.setup.callerinfo.id, param.setup.dialinginfo.id);
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_SETUP);
memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
- SCPY(message->param.setup.dialinginfo.id, number);
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));
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 */
-extern int quit;
-int EndpointAppPBX::handler(void)
+ return 0;
+}
+
+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();
- /* 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);
+
+ 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();
+
+ return 0;
+}
+
+int callback_timeout(struct lcr_timer *timer, void *instance, int index)
+{
+ class EndpointAppPBX *ea = (class EndpointAppPBX *)instance;
- /* handle connection to user */
- if (e_state == EPOINT_STATE_IDLE) {
+ 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();
}
- /* 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';
}
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));
+
+ /* 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;
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);
if (e_action->index == ACTION_VBOX_PLAY) {
/* concat dialing string */
SCAT(e_dialinginfo.id, param->information.id);
- process_dialing();
+ process_dialing(0);
return;
}
}
/* 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;
+
+ 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 */
}
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);
}
}
}
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 */
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 */
/* 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 */
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;
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)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
}
if (param->setup.dialinginfo.id[0])
add_trace("dialing", NULL, "%s", param->setup.dialinginfo.id);
+ if (param->setup.dialinginfo.keypad[0])
+ add_trace("keypad", NULL, "%s", param->setup.dialinginfo.keypad);
if (param->setup.dialinginfo.display[0])
add_trace("display", NULL, "%s", param->setup.dialinginfo.display);
if (param->setup.dialinginfo.sending_complete)