/*
- * process init 'internal' / 'external' / 'remote' / 'vbox-record' / 'partyline'...
+ * process init 'internal' / 'external' / 'vbox-record' / 'partyline'...
*/
-int EndpointAppPBX::_action_init_call(char *remote)
+void EndpointAppPBX::action_init_call(void)
{
class Join *join;
- struct port_list *portlist = ea_endpoint->ep_portlist;
- struct admin_list *admin;
/* a created call, this should never happen */
if (ea_endpoint->ep_join_id) {
if (options.deb & DEBUG_EPOINT)
PERROR("EPOINT(%d): We already have a call instance, this should never happen!\n", ea_endpoint->ep_serial);
- return(0);
+ return;
}
/* create join */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): Creating new join instance.\n", ea_endpoint->ep_serial);
- if (remote) {
- admin = admin_first;
- while(admin) {
- if (admin->remote_name[0] && !strcmp(admin->remote_name, remote))
- break;
- admin = admin->next;
- }
- if (!admin) {
- /* resource not available */
- trace_header("ACTION remote (not available)", DIRECTION_NONE);
- add_trace("application", NULL, "%s", remote);
- end_trace();
- message_disconnect_port(portlist, CAUSE_OUTOFORDER, LOCATION_PRIVATE_LOCAL, "");
- new_state(EPOINT_STATE_OUT_DISCONNECT);
- set_tone(portlist,"cause_1b");
- return(0);
- }
- join = new JoinRemote(ea_endpoint->ep_serial, remote, admin->sock);
- }
- else
- join = new JoinPBX(ea_endpoint);
+ join = new JoinPBX(ea_endpoint);
if (!join)
FATAL("No memoy for Join instance.\n");
ea_endpoint->ep_join_id = join->j_serial;
- return(1);
-}
-void EndpointAppPBX::action_init_call(void)
-{
- _action_init_call(NULL);
-}
-void EndpointAppPBX::action_init_remote(void)
-{
+ return;
}
/*
struct capa_info capainfo;
struct caller_info callerinfo;
struct redir_info redirinfo;
+ struct rtp_info rtpinfo;
struct dialing_info dialinginfo;
struct port_list *portlist = ea_endpoint->ep_portlist;
struct lcr_msg *message;
memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
+ memcpy(&rtpinfo, &e_rtpinfo, sizeof(rtpinfo));
memset(&dialinginfo, 0, sizeof(dialinginfo));
dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
SCPY(dialinginfo.id, e_dialinginfo.id);
capainfo.bearer_mode = INFO_BMODE_PACKET;
}
capainfo.bearer_info1 = INFO_INFO1_NONE;
+ capainfo.hlc = INFO_HLC_NONE;
+ capainfo.exthlc = INFO_HLC_NONE;
}
if ((rparam = routeparam(e_action, PARAM_BMODE))) {
capainfo.bearer_mode = rparam->integer_value;
trace_header("ACTION extension (extension doesn't exist)", DIRECTION_NONE);
add_trace("extension", NULL, dialinginfo.id);
end_trace();
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
new_state(EPOINT_STATE_OUT_DISCONNECT);
message_disconnect_port(portlist, CAUSE_UNALLOCATED, LOCATION_PRIVATE_LOCAL, "");
set_tone(portlist, "cause_86");
add_trace("extension", NULL, dialinginfo.id);
end_trace();
new_state(EPOINT_STATE_OUT_DISCONNECT);
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
set_tone(portlist, "cause_81");
return;
memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
+ memcpy(&message->param.setup.rtpinfo, &rtpinfo, sizeof(struct rtp_info));
message_put(message);
}
struct capa_info capainfo;
struct caller_info callerinfo;
struct redir_info redirinfo;
+ struct rtp_info rtpinfo;
struct dialing_info dialinginfo;
char *p;
struct port_list *portlist = ea_endpoint->ep_portlist;
memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
+ memcpy(&rtpinfo, &e_rtpinfo, sizeof(rtpinfo));
memset(&dialinginfo, 0, sizeof(dialinginfo));
dialinginfo.itype = INFO_ITYPE_ISDN;
- dialinginfo.sending_complete = 0;
+// dialinginfo.sending_complete = 0;
SCPY(dialinginfo.id, e_extdialing);
/* process prefix */
if ((rparam = routeparam(e_action, PARAM_PREFIX)))
SPRINT(dialinginfo.id, "%s%s", rparam->string_value, e_extdialing);
+ if ((rparam = routeparam(e_action, PARAM_CONTEXT)))
+ SCPY(dialinginfo.context, rparam->string_value);
+
/* process keypad */
if ((rparam = routeparam(e_action, PARAM_KEYPAD))) {
SCPY(dialinginfo.keypad, dialinginfo.id);
/* process number complete */
if ((rparam = routeparam(e_action, PARAM_COMPLETE)))
- if ((rparam = routeparam(e_action, PARAM_PREFIX)))
- SCPY(dialinginfo.id, rparam->string_value);
dialinginfo.sending_complete = 1;
/* process number type */
capainfo.bearer_mode = INFO_BMODE_PACKET;
}
capainfo.bearer_info1 = INFO_INFO1_NONE;
+ capainfo.hlc = INFO_HLC_NONE;
+ capainfo.exthlc = INFO_HLC_NONE;
}
if ((rparam = routeparam(e_action, PARAM_BMODE))) {
capainfo.bearer_mode = rparam->integer_value;
if (e_ext.rights < 2) {
trace_header("ACTION extern (calling denied)", DIRECTION_NONE);
end_trace();
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0);
set_tone(portlist, "cause_82");
denied:
message_disconnect_port(portlist, CAUSE_REJECTED, LOCATION_PRIVATE_LOCAL, "");
if (e_ext.rights < 3) {
trace_header("ACTION extern (national calls denied)", DIRECTION_NONE);
end_trace();
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0);
set_tone(portlist, "cause_83");
goto denied;
}
if (e_ext.rights < 4) {
trace_header("ACTION extern (international calls denied)", DIRECTION_NONE);
end_trace();
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0);
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_REJECTED, 0, 0, 0);
set_tone(portlist, "cause_84");
goto denied;
}
/* add or update outgoing call */
trace_header("ACTION extern (calling)", DIRECTION_NONE);
add_trace("number", NULL, dialinginfo.id);
+ if (dialinginfo.sending_complete)
+ add_trace("number", "complete", "yes");
if (dialinginfo.interfaces[0])
add_trace("interfaces", NULL, dialinginfo.interfaces);
end_trace();
memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
+ memcpy(&message->param.setup.rtpinfo, &rtpinfo, sizeof(struct rtp_info));
message_put(message);
}
-void EndpointAppPBX::action_dialing_remote(void)
-{
- struct route_param *rparam;
- struct port_list *portlist = ea_endpoint->ep_portlist;
- struct lcr_msg *message;
- struct capa_info capainfo;
- struct caller_info callerinfo;
- struct redir_info redirinfo;
- struct dialing_info dialinginfo;
- char context[128] = "";
- char remote[32];
-
- if (!ea_endpoint->ep_join_id) {
- /* no join yet, sending setup */
- if (!(rparam = routeparam(e_action, PARAM_APPLICATION))) {
- trace_header("ACTION remote (no application given)", DIRECTION_NONE);
- end_trace();
- new_state(EPOINT_STATE_OUT_DISCONNECT);
- message_disconnect_port(portlist, CAUSE_SERVICEUNAVAIL, LOCATION_PRIVATE_LOCAL, "");
- set_tone(portlist, "cause_3f");
- return;
- }
- SCPY(remote, rparam->string_value);
- if (!_action_init_call(remote))
- return;
-
- /* create bearer/caller/dialinginfo */
- memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
- memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
- memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
- memset(&dialinginfo, 0, sizeof(dialinginfo));
-
- if ((rparam = routeparam(e_action, PARAM_CONTEXT))) {
- SCPY(context, rparam->string_value);
- }
- if ((rparam = routeparam(e_action, PARAM_EXTEN))) {
- SCPY(dialinginfo.id, rparam->string_value);
- dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
- } else {
- SCPY(dialinginfo.id, e_extdialing);
- }
- e_extdialing = e_dialinginfo.id + strlen(e_dialinginfo.id);
- /* send setup to remote */
- trace_header("ACTION remote (setup)", DIRECTION_NONE);
- add_trace("number", NULL, dialinginfo.id);
- add_trace("remote", NULL, remote);
- if (context[0])
- add_trace("context", NULL, context);
- end_trace();
- message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_SETUP);
- memcpy(&message->param.setup.dialinginfo, &dialinginfo, sizeof(struct dialing_info));
- memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
- memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
- memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
- SCPY(message->param.setup.context, context);
- message_put(message);
- } else {
- /* send overlap digits */
- trace_header("ACTION remote (dialing)", DIRECTION_NONE);
- add_trace("number", NULL, e_extdialing);
- end_trace();
- if (e_extdialing[0]) {
- message = message_create(ea_endpoint->ep_serial, ea_endpoint->ep_join_id, EPOINT_TO_JOIN, MESSAGE_INFORMATION);
- memcpy(&message->param.information, &e_dialinginfo, sizeof(struct dialing_info));
- SCPY(message->param.information.id, e_extdialing);
- e_extdialing = e_dialinginfo.id + strlen(e_dialinginfo.id);
- message_put(message);
- }
- }
-}
-
-
/*
* process dialing the "am" and record
*/
e_ruleset = NULL;
e_rule = NULL;
e_action = &action_password;
- 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');
/* set timeout */
- e_password_timeout = now+20;
+ schedule_timer(&e_password_timeout, 20, 0);
/* do dialing */
- process_dialing();
+ process_dialing(0);
} else {
/* make call state */
new_state(EPOINT_STATE_IN_OVERLAP);
SCPY(e_dialinginfo.id, last);
e_extdialing = e_dialinginfo.id;
e_action = NULL;
- process_dialing();
+ process_dialing(0);
return;
}
e_extdialing[0] = '\0';
/* do dialing */
SCPY(e_dialinginfo.id, e_ext.last_out[0]);
- e_powerdialing = -1; /* indicates the existence of powerdialing but no redial time given */
+ e_powerdial_on = 1; /* indicates the existence of powerdialing but no redial time given */
e_powercount = 0;
e_action = NULL;
- process_dialing();
+ process_dialing(0);
}
end_trace();
/* set time to callback */
- e_callback = now_d + delay;
+ schedule_timer(&e_callback_timeout, delay, 0);
}
SCPY(e_dialinginfo.id, phone);
e_extdialing = e_dialinginfo.id;
e_action = NULL;
- process_dialing();
+ process_dialing(0);
}
/* if the 'menu' was selected, we will flush all digits */
if (mode) {
e_dialinginfo.id[0] = 0;
+ e_dialinginfo.sending_complete = 0;
e_extdialing = e_dialinginfo.id;
} else {
/* remove digits that are required to match the rule */
/* do dialing with new ruleset */
e_action = NULL;
- process_dialing();
+ process_dialing(0);
}
/* process dialing goto
/*
+ * process dialing release
+ */
+void EndpointAppPBX::action_dialing_release(void)
+{
+ struct route_param *rparam;
+ int cause = CAUSE_NORMAL; /* normal call clearing */
+ int location = LOCATION_PRIVATE_LOCAL;
+ char cause_string[256] = "", display[84] = "";
+
+ /* check cause parameter */
+ if ((rparam = routeparam(e_action, PARAM_CAUSE))) {
+ cause = rparam->integer_value;
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'cause' is given: %d\n", ea_endpoint->ep_serial, cause);
+ }
+ if ((rparam = routeparam(e_action, PARAM_LOCATION))) {
+ location = rparam->integer_value;
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'location' is given: %d\n", ea_endpoint->ep_serial, location);
+ }
+
+
+ /* use cause as sample, if not given later */
+ SPRINT(cause_string, "cause_%02x", cause);
+
+ /* check display */
+ if ((rparam = routeparam(e_action, PARAM_DISPLAY))) {
+ SCPY(display, rparam->string_value);
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d): 'display' is given: %s\n", ea_endpoint->ep_serial, display);
+ }
+
+ /* disconnect only if connect parameter is not given */
+ trace_header("ACTION release", DIRECTION_NONE);
+ add_trace("cause", "value", "%d", cause);
+ add_trace("cause", "location", "%d", location);
+ if (display[0])
+ add_trace("display", NULL, "%s", display);
+ end_trace();
+ e_action = NULL;
+ release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, location, cause, 1);
+ return;
+}
+
+/*
* process dialing help
*/
void EndpointAppPBX::action_dialing_help(void)
e_extdialing = e_dialinginfo.id+strlen(numbering->prefix);
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal %s selected a new menu '%s' dialing: %s\n", ea_endpoint->ep_serial, e_ext.number, numb_actions[numbering->action], e_dialinginfo.id);
nesting?:
- process_dialing();
+ process_dialing(0);
return;
}
int iWaitStatus;
char *command = (char *)"";
char isdn_port[10];
- char *argv[11]; /* check also number of args below */
+ char *argv[12]; /* check also number of args below */
int i = 0;
/* get script / command */
end_trace();
return;
}
+#if 0
argv[i++] = (char *)"/bin/sh";
argv[i++] = (char *)"-c";
argv[i++] = command;
+#endif
argv[i++] = command;
if ((rparam = routeparam(e_action, PARAM_PARAM))) {
argv[i++] = rparam->string_value;
argv[i++] = e_callerinfo.name;
SPRINT(isdn_port, "%d", e_callerinfo.isdn_port);
argv[i++] = isdn_port;
+ argv[i++] = e_callerinfo.imsi;
argv[i++] = NULL; /* check also number of args above */
switch (pid = fork ()) {
case -1:
case 0:
/* To be shure there are no zombies created double fork */
if ((pid2 = fork()) == 0) {
- execve("/bin/sh", argv, environ);
- }
- else {
- /* Exit immediately and release the waiting parent. The subprocess falls to init because the parent died */
- exit(0);
+ execve(command, argv, environ);
}
+ /* Exit immediately and release the waiting parent. The subprocess falls to init because the parent died */
+ exit(0);
break;
default:
trace_header("ACTION execute", DIRECTION_NONE);
}
+/* process pots-retrieve
+ */
+void EndpointAppPBX::action_init_pots_retrieve(void)
+{
+#ifdef ISDN_P_FXS_POTS
+ struct route_param *rparam;
+ struct port_list *portlist = ea_endpoint->ep_portlist;
+ class Port *port;
+ class Pfxs *ourfxs, *fxs;
+ int count = 0;
+ class Endpoint *epoint;
+
+ /* check given call */
+ if (!(rparam = routeparam(e_action, PARAM_POTS_CALL))) {
+ trace_header("ACTION pots-retrieve (no call given)", DIRECTION_NONE);
+ end_trace();
+
+ disconnect:
+ new_state(EPOINT_STATE_OUT_DISCONNECT);
+ message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+ set_tone(portlist, "cause_3f");
+ e_action = NULL;
+ return;
+ }
+
+ /* find call */
+ port = find_port_id(portlist->port_id);
+ if (!port)
+ goto disconnect;
+ if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) {
+ trace_header("ACTION pots-retrieve (call not of FXS type)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+ ourfxs = (class Pfxs *)port;
+
+ port = port_first;
+ while(port) {
+ if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
+ fxs = (class Pfxs *)port;
+ if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) {
+ count++;
+ if (count == rparam->integer_value)
+ break;
+ }
+ }
+ port = port->next;
+ }
+ if (!port) {
+ trace_header("ACTION pots-retrieve (call # does not exist)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+
+ /* release our call */
+ ourfxs->hangup_ind(0);
+
+ /* retrieve selected call */
+ fxs->retrieve_ind(0);
+
+ /* split if selected call is member of a 3pty */
+ epoint = find_epoint_id(ACTIVE_EPOINT(fxs->p_epointlist));
+ if (epoint && epoint->ep_app_type == EAPP_TYPE_PBX) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) try spliting 3pty. this may fail because we don't have a 3pty.\n", epoint->ep_serial);
+ ((class EndpointAppPBX *)epoint->ep_app)->split_3pty();
+ }
+#endif
+}
+
+
+/* process pots-release
+ */
+void EndpointAppPBX::action_init_pots_release(void)
+{
+#ifdef ISDN_P_FXS_POTS
+ struct route_param *rparam;
+ struct port_list *portlist = ea_endpoint->ep_portlist;
+ class Port *port;
+ class Pfxs *ourfxs, *fxs;
+ int count = 0;
+
+ /* check given call */
+ if (!(rparam = routeparam(e_action, PARAM_POTS_CALL))) {
+ trace_header("ACTION pots-release (no call given)", DIRECTION_NONE);
+ end_trace();
+
+ disconnect:
+ new_state(EPOINT_STATE_OUT_DISCONNECT);
+ message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+ set_tone(portlist, "cause_3f");
+ e_action = NULL;
+ return;
+ }
+
+ /* find call */
+ port = find_port_id(portlist->port_id);
+ if (!port)
+ goto disconnect;
+ if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) {
+ trace_header("ACTION pots-release (call not of FXS type)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+ ourfxs = (class Pfxs *)port;
+
+ port = port_first;
+ while(port) {
+ if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
+ fxs = (class Pfxs *)port;
+ if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) {
+ count++;
+ if (count == rparam->integer_value)
+ break;
+ }
+ }
+ port = port->next;
+ }
+ if (!port) {
+ trace_header("ACTION pots-release (call # does not exist)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+
+#if 0
+ /* disconnect our call */
+ new_state(EPOINT_STATE_OUT_DISCONNECT);
+ message_disconnect_port(portlist, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, "");
+ set_tone(portlist, "hangup");
+ e_action = NULL;
+#endif
+
+ /* release selected call */
+ fxs->hangup_ind(0);
+
+ /* indicate timeout, so next action will be processed */
+ process_dialing(1);
+#endif
+}
+
+
+/* process pots-reject
+ */
+void EndpointAppPBX::action_init_pots_reject(void)
+{
+#ifdef ISDN_P_FXS_POTS
+ struct port_list *portlist = ea_endpoint->ep_portlist;
+ class Port *port;
+ class Pfxs *ourfxs, *fxs;
+
+ /* find call */
+ port = find_port_id(portlist->port_id);
+ if (!port)
+ goto disconnect;
+ if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) {
+ trace_header("ACTION pots-reject (call not of FXS type)", DIRECTION_NONE);
+ end_trace();
+ disconnect:
+ new_state(EPOINT_STATE_OUT_DISCONNECT);
+ message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+ set_tone(portlist, "cause_3f");
+ e_action = NULL;
+ return;
+ }
+ ourfxs = (class Pfxs *)port;
+
+ port = port_first;
+ while(port) {
+ if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
+ fxs = (class Pfxs *)port;
+ if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) {
+ if (fxs->p_state == PORT_STATE_OUT_ALERTING)
+ break;
+ }
+ }
+ port = port->next;
+ }
+ if (!port) {
+ trace_header("ACTION pots-reject (no call waiting)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+
+ /* reject alerting call */
+ fxs->reject_ind(0);
+
+ /* indicate timeout, so next action will be processed */
+ process_dialing(1);
+#endif
+}
+
+
+/* process pots-answer
+ */
+void EndpointAppPBX::action_init_pots_answer(void)
+{
+#ifdef ISDN_P_FXS_POTS
+ struct port_list *portlist = ea_endpoint->ep_portlist;
+ class Port *port;
+ class Pfxs *ourfxs, *fxs;
+
+ /* find call */
+ port = find_port_id(portlist->port_id);
+ if (!port)
+ goto disconnect;
+ if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) {
+ trace_header("ACTION pots-answer (call not of FXS type)", DIRECTION_NONE);
+ end_trace();
+ disconnect:
+ new_state(EPOINT_STATE_OUT_DISCONNECT);
+ message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+ set_tone(portlist, "cause_3f");
+ e_action = NULL;
+ return;
+ }
+ ourfxs = (class Pfxs *)port;
+
+ port = port_first;
+ while(port) {
+ if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
+ fxs = (class Pfxs *)port;
+ if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) {
+ if (fxs->p_state == PORT_STATE_OUT_ALERTING)
+ break;
+ }
+ }
+ port = port->next;
+ }
+ if (!port) {
+ trace_header("ACTION pots-answer (no call waiting)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+
+ /* release our call */
+ ourfxs->hangup_ind(0);
+
+ /* answer alerting call */
+ fxs->answer_ind(0);
+#endif
+}
+
+
+/* process pots-3pty
+ */
+void EndpointAppPBX::action_init_pots_3pty(void)
+{
+#ifdef ISDN_P_FXS_POTS
+ struct port_list *portlist = ea_endpoint->ep_portlist;
+ class Port *port;
+ class Pfxs *ourfxs, *fxs, *fxs1 = NULL, *fxs2 = NULL;
+ class Endpoint *epoint;
+ int count = 0;
+
+ /* find call */
+ port = find_port_id(portlist->port_id);
+ if (!port)
+ goto disconnect;
+ if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) {
+ trace_header("ACTION pots-3pty (call not of FXS type)", DIRECTION_NONE);
+ end_trace();
+ disconnect:
+ new_state(EPOINT_STATE_OUT_DISCONNECT);
+ message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+ set_tone(portlist, "cause_3f");
+ e_action = NULL;
+ return;
+ }
+ ourfxs = (class Pfxs *)port;
+
+ port = port_first;
+ while(port) {
+ if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
+ fxs = (class Pfxs *)port;
+ if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) {
+ if (count == 0)
+ fxs1 = fxs;
+ if (count == 1)
+ fxs2 = fxs;
+ count++;
+ }
+ }
+ port = port->next;
+ }
+ if (count != 2) {
+ trace_header("ACTION pots-3pty (exactly two calls don't exist)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+
+ /* release our call */
+ ourfxs->hangup_ind(0);
+
+ /* retrieve latest active call */
+ if (fxs2->p_m_fxs_age > fxs1->p_m_fxs_age) {
+ fxs2->retrieve_ind(0);
+ epoint = find_epoint_id(ACTIVE_EPOINT(fxs2->p_epointlist));
+ } else {
+ fxs1->retrieve_ind(0);
+ epoint = find_epoint_id(ACTIVE_EPOINT(fxs2->p_epointlist));
+ }
+
+ if (!epoint) {
+ trace_header("ACTION pots-3pty (interal error: no endpoint)", DIRECTION_NONE);
+ end_trace();
+ return;
+ }
+
+ if (epoint->ep_app_type != EAPP_TYPE_PBX) {
+ trace_header("ACTION pots-3pty (interal error: endpoint not PBX type)", DIRECTION_NONE);
+ end_trace();
+ return;
+ }
+
+ /* bridge calls */
+ if (((class EndpointAppPBX *)epoint->ep_app)->join_3pty_fxs()) {
+ trace_header("ACTION pots-3pty (interal error: join_3pty_fsx failed)", DIRECTION_NONE);
+ end_trace();
+ return;
+ }
+#endif
+}
+
+/* process pots-transfer
+ */
+void EndpointAppPBX::action_init_pots_transfer(void)
+{
+#ifdef ISDN_P_FXS_POTS
+ struct route_param *rparam;
+ struct port_list *portlist = ea_endpoint->ep_portlist;
+ class Port *port;
+ class Pfxs *ourfxs, *fxs, *fxs1 = NULL, *fxs2 = NULL;
+ int count = 0;
+
+ /* check given call */
+ if (!(rparam = routeparam(e_action, PARAM_POTS_CALL))) {
+ trace_header("ACTION pots-transfer (no call given)", DIRECTION_NONE);
+ end_trace();
+
+ disconnect:
+ new_state(EPOINT_STATE_OUT_DISCONNECT);
+ message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
+ set_tone(portlist, "cause_3f");
+ e_action = NULL;
+ return;
+ }
+
+ /* find call */
+ port = find_port_id(portlist->port_id);
+ if (!port)
+ goto disconnect;
+ if ((port->p_type & PORT_CLASS_POTS_MASK) != PORT_CLASS_POTS_FXS) {
+ trace_header("ACTION pots-transfer (call not of FXS type)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+ ourfxs = (class Pfxs *)port;
+
+ port = port_first;
+ while(port) {
+ if ((port->p_type & PORT_CLASS_POTS_MASK) == PORT_CLASS_POTS_FXS) {
+ fxs = (class Pfxs *)port;
+ if (fxs->p_m_mISDNport == ourfxs->p_m_mISDNport && fxs != ourfxs) {
+ if (count == 0)
+ fxs1 = fxs;
+ if (count == 1)
+ fxs2 = fxs;
+ count++;
+ }
+ }
+ port = port->next;
+ }
+ if (count != 2) {
+ trace_header("ACTION pots-transfer (exactly two calls don't exist)", DIRECTION_NONE);
+ end_trace();
+ goto disconnect;
+ }
+
+ /* retrieve call */
+ if (fxs2->p_m_fxs_age > fxs1->p_m_fxs_age)
+ fxs2->retrieve_ind(0);
+ else
+ fxs1->retrieve_ind(0);
+ /* bridge calls */
+ join_join_fxs();
+#endif
+}
+
+
/* general process dialing of incoming call
* depending on the detected prefix, subfunctions above (action_*) will be
* calles.
*/
-void EndpointAppPBX::process_dialing(void)
+void EndpointAppPBX::process_dialing(int timeout)
{
struct port_list *portlist = ea_endpoint->ep_portlist;
struct lcr_msg *message;
struct route_param *rparam;
+ struct timeval current_time;
+
+ /* set if timeout is active, or if timeout value was given due to timeout action */
+ if (e_action_timeout.active)
+ timeout = 1;
//#warning Due to HANG-BUG somewhere here, I added some HANG-BUG-DEBUGGING output that cannot be disabled. after bug has been found, this will be removed.
//PDEBUG(~0, "HANG-BUG-DEBUGGING: entered porcess_dialing\n");
if (!portlist) {
portlist_error:
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): note: dialing call requires exactly one port object to process dialing. this case could happen due to a parked call. we end dialing here.\n", ea_endpoint->ep_serial, e_ext.number);
- e_action_timeout = 0;
- e_match_timeout = 0;
+ unsched_timer(&e_action_timeout);
+ unsched_timer(&e_match_timeout);
return;
}
if (portlist->next) {
new_state(EPOINT_STATE_OUT_DISCONNECT);
message_disconnect_port(portlist, CAUSE_UNSPECIFIED, LOCATION_PRIVATE_LOCAL, "");
set_tone(portlist, "cause_3f");
- e_action_timeout = 0;
- e_match_timeout = 0;
+ unsched_timer(&e_action_timeout);
+ unsched_timer(&e_match_timeout);
goto end;
}
//PDEBUG(~0, "HANG-BUG-DEBUGGING: before action-timeout processing\n");
/* process timeout */
- if (e_action && e_action_timeout) { /* e_action may be NULL, but e_action_timeout may still be set and must be ignored */
- e_action_timeout = 0;
+ if (e_action && timeout) { /* e_action may be NULL, but e_action_timeout may still be set and must be ignored */
+ unsched_timer(&e_action_timeout);
if (e_state == EPOINT_STATE_CONNECT) {
PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action timed out, but we already have connected, so we stop timer and continue.\n", ea_endpoint->ep_serial);
goto end;
if (e_action->index == ACTION_DISCONNECT
|| e_state == EPOINT_STATE_OUT_DISCONNECT) {
/* release after disconnect */
- 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);
goto end;
}
- release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0);
+ release(RELEASE_JOIN, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0, 0, 0);
e_action = e_action->next;
if (!e_action) {
/* nothing more, so we release */
if (e_state!=EPOINT_STATE_IN_SETUP
&& e_state!=EPOINT_STATE_IN_OVERLAP) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): we are not in incoming setup/overlap state, so we ignore init/dialing process.\n", ea_endpoint->ep_serial, e_rule_nesting);
- e_match_timeout = 0;
+ unsched_timer(&e_match_timeout);
goto end;
}
e_dialinginfo.id[0] = '\0';
e_action = NUMB_ACTION_MENU;
e_menu = 0;
- process_dialing();
- e_match_timeout = 0;
+ process_dialing(0);
+ unsched_timer(&e_match_timeout);
goto end;
}
/* invalid dialing */
}
new_state(EPOINT_STATE_OUT_DISCONNECT);
set_tone(portlist,"cause_1c");
- e_match_timeout = 0;
+ unsched_timer(&e_match_timeout);
goto end;
}
#endif
e_action = &action_internal;
goto process_action;
}
- /* check for chan call */
- if (!strncmp(e_dialinginfo.id, "remote:", 7)) {
- e_extdialing = e_dialinginfo.id+7;
- e_action = &action_remote;
- goto process_action;
- }
/* check for vbox call */
if (!strncmp(e_dialinginfo.id, "vbox:", 5)) {
e_extdialing = e_dialinginfo.id+5;
goto process_action;
}
- if (e_match_timeout && now_d>=e_match_timeout) {
+ gettimeofday(¤t_time, NULL);
+ if (e_match_to_action && TIME_SMALLER(&e_match_timeout.timeout, ¤t_time)) {
/* return timeout rule */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d): terminal '%s' dialing: '%s', timeout in ruleset '%s'\n", ea_endpoint->ep_serial, e_ext.number, e_dialinginfo.id, e_ruleset->name);
- e_match_timeout = 0;
+ unsched_timer(&e_match_timeout);
e_action = e_match_to_action;
+ e_match_to_action = NULL;
e_extdialing = e_match_to_extdialing;
trace_header("ROUTING (timeout)", DIRECTION_NONE);
add_trace("action", NULL, "%s", action_defs[e_action->index].name);
action_timeout:
/* set timeout */
- e_action_timeout = 0;
+ unsched_timer(&e_action_timeout);
if (e_action->timeout) {
- e_action_timeout = now_d + e_action->timeout;
+ schedule_timer(&e_action_timeout, e_action->timeout, 0);
PDEBUG(DEBUG_ROUTE|DEBUG_EPOINT, "EPOINT(%d): action has a timeout of %d secods.\n", ea_endpoint->ep_serial, e_action->timeout);
}