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
*/
-EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin)
+EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin, EAPP_TYPE_PBX)
{
class EndpointAppPBX **apppointer;
+#ifdef WITH_CRYPT
+ memset(&e_crypt_handler, 0, sizeof(e_crypt_handler));
+ add_timer(&e_crypt_handler, crypt_handler, this, 0);
+#endif
+ 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';
+#ifdef WITH_CRYPT
e_crypt = CRYPT_OFF;
e_crypt_state = CM_ST_NULL;
e_crypt_keyengine_busy = 0;
- e_crypt_info[0] = '\0';
+ e_crypt_info[0] = '\0';
+#endif
e_overlap = 0;
e_vbox[0] = '\0';
e_tx_state = NOTIFY_STATE_ACTIVE;
{
class EndpointAppPBX *temp, **tempp;
+#ifdef WITH_CRYPT
+ del_timer(&e_crypt_handler);
+#endif
+ 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';
+#ifdef WITH_CRYPT
e_crypt = 0;
e_crypt_state = CM_ST_NULL;
e_crypt_keyengine_busy = 0;
e_crypt_info[0] = '\0';
+#endif
e_tone[0] = '\0';
e_overlap = 0;
e_vbox[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;
}
}
join_join();
break;
+#ifdef WITH_CRYPT
/* crypt shared */
case '7':
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) shared key encryption selected.\n", ea_endpoint->ep_serial);
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) encryption off selected.\n", ea_endpoint->ep_serial);
encrypt_off();
break;
+#endif
default:
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) unsupported keypad digit '%c'.\n", ea_endpoint->ep_serial, digit);
}
-/*
- * hunts an mISDNport that is available for an outgoing call
- * if no ifname was given, any interface that is not an extension
- * will be searched.
- */
-struct mISDNport *EndpointAppPBX::hunt_port(char *ifname, int *channel)
-{
- struct interface *interface;
- struct interface_port *ifport, *ifport_start;
- struct select_channel *selchannel;
- struct mISDNport *mISDNport;
- int index, i;
-
- interface = interface_first;
-
- /* first find the given interface or, if not given, one with no extension */
- checknext:
- if (!interface)
- return(NULL);
-
- /* check for given interface */
- if (ifname) {
- if (!strcasecmp(interface->name, ifname)) {
- /* found explicit interface */
- trace_header("CHANNEL SELECTION (found interface)", DIRECTION_NONE);
- add_trace("interface", NULL, "%s", ifname);
- end_trace();
- goto foundif;
- }
-
- } else {
- if (!interface->extension) {
- /* found non extension */
- trace_header("CHANNEL SELECTION (found non extension interface)", DIRECTION_NONE);
- add_trace("interface", NULL, "%s", interface->name);
- end_trace();
- goto foundif;
- }
- }
-
- interface = interface->next;
- goto checknext;
-foundif:
-
- /* see if interface has ports */
- if (!interface->ifport) {
- /* no ports */
- trace_header("CHANNEL SELECTION (active ports, skipping)", DIRECTION_NONE);
- add_trace("interface", NULL, "%s", interface->name);
- end_trace();
- interface = interface->next;
- goto checknext;
- }
-
- /* select port by algorithm */
- ifport_start = interface->ifport;
- index = 0;
- if (interface->hunt == HUNT_ROUNDROBIN) {
- while(ifport_start->next && index<interface->hunt_next) {
- ifport_start = ifport_start->next;
- index++;
- }
- trace_header("CHANNEL SELECTION (starting round-robin)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport_start->portnum);
- add_trace("position", NULL, "%d", index);
- end_trace();
- }
-
- /* loop ports */
- ifport = ifport_start;
- nextport:
-
- /* see if port is available */
- if (!ifport->mISDNport) {
- trace_header("CHANNEL SELECTION (port not available, skipping)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- end_trace();
- goto portbusy;
- }
- mISDNport = ifport->mISDNport;
-
- /* see if port is administratively blocked */
- if (ifport->block) {
- trace_header("CHANNEL SELECTION (port blocked by admin, skipping)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- end_trace();
- goto portbusy;
- }
-
- /* see if link is up on PTP*/
- if (mISDNport->l2hold && mISDNport->l2link<1) {
- trace_header("CHANNEL SELECTION (port's layer 2 is down, skipping)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- end_trace();
- goto portbusy;
- }
-
- /* 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);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- 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);
- 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;
-
- 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;
- }
- if (*channel)
- break; /* found channel */
- selchannel = selchannel->next;
- }
-
- /* if channel was found, return mISDNport and channel */
- if (*channel) {
- /* setting next port to start next time */
- if (interface->hunt == HUNT_ROUNDROBIN) {
- index++;
- if (!ifport->next)
- index = 0;
- interface->hunt_next = index;
- }
-
- return(mISDNport);
- }
-
- trace_header("CHANNEL SELECTION (skipping, no channel found)", DIRECTION_NONE);
- add_trace("port", NULL, "%d", ifport->portnum);
- add_trace("position", NULL, "%d", index);
- end_trace();
-
- portbusy:
- /* go next port, until all ports are checked */
- index++;
- ifport = ifport->next;
- if (!ifport) {
- index = 0;
- ifport = interface->ifport;
- }
- if (ifport != ifport_start)
- goto nextport;
-
- if (!ifname) {
- interface = interface->next;
- goto checknext;
- }
-
- return(NULL); /* no port found */
-}
-
/* outgoing setup to port(s)
* 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;
+#ifdef WITH_MISDN
struct mISDNport *mISDNport;
+#endif
char portname[32];
char *dirname;
class EndpointAppPBX *atemp;
// char allowed_ports[256];
// char exten[256];
char ifname[sizeof(e_ext.interfaces)],
- number[256];
+ *ifname_p,
+ number[256],
+ *number_p;
struct port_settings port_settings;
+#ifdef WITH_MISDN
int channel = 0;
+#endif
+ struct admin_list *admin;
int earlyb;
int mode = B_MODE_TRANSPARENT;
}
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);
}
}
p = e_ext.interfaces;
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) generating multiple joins for extension %s to interfaces %s\n", ea_endpoint->ep_serial, e_dialinginfo.id, p);
while(*p) {
+ earlyb = 0;
ifname[0] = '\0';
while(*p!=',' && *p!='\0')
if (*p > ' ')
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);
- if (!mISDNport->gsm)
+ /* found interface */
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
+ if (interface->remote) {
+ admin = admin_first;
+ while(admin) {
+ if (admin->remote_name[0] && !strcmp(admin->remote_name, interface->remote_app))
+ break;
+ admin = admin->next;
+ }
+ if (!admin) {
+ trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+ add_trace("application", NULL, "%s", interface->remote_app);
+ end_trace();
+ continue;
+ }
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Premote(PORT_TYPE_REMOTE_OUT, portname, &port_settings, interface, admin->sock);
+ earlyb = (interface->is_earlyb == IS_YES);
+ } else
+#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);
+ earlyb = (interface->is_earlyb == IS_YES);
+ } else
+#endif
+#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);
+ earlyb = (interface->is_earlyb == IS_YES);
+ } else
+#endif
+#ifdef WITH_SIP
+ if (interface->sip) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+ earlyb = (interface->is_earlyb == IS_YES);
+ } else
+#endif
+ {
+#ifdef WITH_MISDN
+ /* 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
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);
+ earlyb = mISDNport->earlyb;
#else
- port = NULL;
+ trace_header("INTERFACE (has no function)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
+ end_trace();
+ continue;
#endif
+ }
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, 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);
p++;
/* external call */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cfp external %s\n", ea_endpoint->ep_serial, cfp);
+#ifdef WITH_MISDN
/* hunt for mISDNport and create Port */
mISDNport = hunt_port(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL, &channel);
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");
earlyb = mISDNport->earlyb;
- } else {
+ } else
+#endif
+ {
port = NULL;
trace_header("INTERFACE (too busy)", DIRECTION_NONE);
add_trace("interface", NULL, "%s", e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:"any interface");
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])
+ number_p = e_dialinginfo.keypad;
+ else
+ number_p = e_dialinginfo.id;
do {
number[0] = '\0';
- while(*p!=',' && *p!='\0')
- SCCAT(number, *p++);
- if (*p == ',')
- p++;
+ while(*number_p!=',' && *number_p!='\0')
+ SCCAT(number, *number_p++);
+ if (*number_p == ',')
+ number_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");
- end_trace();
- goto check_anycall_extern;
- }
- /* creating EXTERNAL port*/
- SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
- 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);
+
+ ifname_p = e_dialinginfo.interfaces;
+ if (*ifname_p == '+')
+ ifname_p++;
+ do {
+ earlyb = 0;
+ ifname[0] = '\0';
+ while(*ifname_p!=',' && *ifname_p!='\0')
+ SCCAT(ifname, *ifname_p++);
+ if (*ifname_p == ',')
+ ifname_p++;
+ /* found interface name */
+
+ /* search interface */
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to number '%s' interface '%s'\n", ea_endpoint->ep_serial, number, ifname[0]?ifname:"any interface");
+ interface = hunt_interface(ifname[0]?ifname:NULL);
+ if (!interface) {
+ trace_header("INTERFACE (not found)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
+ end_trace();
+ continue;
+ }
+ /* found interface */
+ if (interface->remote) {
+ admin = admin_first;
+ while(admin) {
+ if (admin->remote_name[0] && !strcmp(admin->remote_name, interface->remote_app))
+ break;
+ admin = admin->next;
+ }
+ if (!admin) {
+ trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+ add_trace("application", NULL, "%s", interface->remote_app);
+ end_trace();
+ continue;
+ }
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Premote(PORT_TYPE_REMOTE_OUT, portname, &port_settings, interface, admin->sock);
+ earlyb = (interface->is_earlyb == IS_YES);
+ } else
+#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);
+ earlyb = (interface->is_earlyb == IS_YES);
+ } else
+#endif
+#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);
+ earlyb = (interface->is_earlyb == IS_YES);
+ } else
+#endif
+#ifdef WITH_SIP
+ if (interface->sip) {
+ SPRINT(portname, "%s-%d-out", interface->name, 0);
+ port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+ earlyb = (interface->is_earlyb == IS_YES);
+ } else
+#endif
+ {
+#ifdef WITH_MISDN
+ /* hunt for mISDNport and create Port */
+ mISDNport = hunt_port(ifname[0]?ifname:NULL, &channel);
+ if (!mISDNport) {
+ trace_header("INTERFACE (too busy)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname[0]?ifname:"any interface");
+ end_trace();
+ continue;
+ }
+ /* 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);
+ earlyb = mISDNport->earlyb;
#else
- port = NULL;
+ trace_header("INTERFACE (has no function)", DIRECTION_NONE);
+ add_trace("interface", NULL, "%s", ifname);
+ end_trace();
+ continue;
#endif
- if (!port)
- FATAL("No memory for Port instance\n");
- 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);
- dialinginfo.itype = INFO_ITYPE_ISDN;
- dialinginfo.ntype = e_dialinginfo.ntype;
- portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, mISDNport->earlyb);
- if (!portlist) {
- PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
- delete port;
- goto check_anycall_extern;
- }
-//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));
-//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);
- /* handle restricted caller ids */
- apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
- apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
- apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
- /* display callerid if desired for extension */
- SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
- message_put(message);
- logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
- anycall = 1;
- } while(*p);
+ }
+ if (!port)
+ FATAL("No memory for Port instance\n");
+ 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.keypad, number);
+ else
+ SCPY(dialinginfo.id, number);
+ dialinginfo.itype = INFO_ITYPE_ISDN;
+ dialinginfo.ntype = e_dialinginfo.ntype;
+ 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;
+ continue;
+ }
+ //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));
+ 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);
+ /* handle restricted caller ids */
+ apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id, &message->param.setup.callerinfo.ntype, &message->param.setup.callerinfo.present, &message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
+ apply_callerid_restriction(&e_ext, message->param.setup.callerinfo.id2, &message->param.setup.callerinfo.ntype2, &message->param.setup.callerinfo.present2, &message->param.setup.callerinfo.screen2, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name);
+ apply_callerid_restriction(&e_ext, message->param.setup.redirinfo.id, &message->param.setup.redirinfo.ntype, &message->param.setup.redirinfo.present, 0, message->param.setup.redirinfo.extension, NULL);
+ /* display callerid if desired for extension */
+ SCPY(message->param.setup.callerinfo.display, apply_callerid_display(message->param.setup.callerinfo.id, message->param.setup.callerinfo.itype, message->param.setup.callerinfo.ntype, message->param.setup.callerinfo.present, message->param.setup.callerinfo.screen, message->param.setup.callerinfo.extension, message->param.setup.callerinfo.name));
+ message_put(message);
+ logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+ anycall = 1;
+
+ /* found an interface
+ * continue only if + is given, so every interface is calles parallel */
+ if (e_dialinginfo.interfaces[0] != '+')
+ break;
+ } while (*ifname_p);
+ } while(*number_p);
- check_anycall_extern:
/* now we have all ports created */
if (!anycall) {
trace_header("INTERFACE (no free ports found)", DIRECTION_NONE);
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;
+
+ if (!ea->e_action || ea->e_state == EPOINT_STATE_CONNECT)
+ return 0;
-/* handler for endpoint
- */
+ 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(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);
+
+ 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);
- /* handle connection to user */
- if (e_state == EPOINT_STATE_IDLE) {
+ 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);
+ do_screen(0, e_redirinfo.id, sizeof(e_redirinfo.id), &e_redirinfo.ntype, &e_redirinfo.present, 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) {
- if (e_ext.keypad || e_enablekeypad) {
+ 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_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') {
}
if (e_action)
if (e_action->index==ACTION_OUTDIAL
- || e_action->index==ACTION_EXTERNAL
- || e_action->index==ACTION_REMOTE) {
+ || e_action->index==ACTION_EXTERNAL) {
if (!e_extdialing)
set_tone(portlist, "dialing");
else if (!e_extdialing[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 */
}
#endif
/* check for *X# sequence */
- if (e_state == EPOINT_STATE_CONNECT) {
+ 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);
}
}
}
/* port MESSAGE_CRYPT */
void EndpointAppPBX::port_crypt(struct port_list *portlist, int message_type, union parameter *param)
{
+#ifdef WITH_CRYPT
/* send crypt response to cryptman */
if (param->crypt.type == CR_MESSAGE_IND)
cryptman_msg2man(param->crypt.data, param->crypt.len);
else
cryptman_message(param->crypt.type, param->crypt.data, param->crypt.len);
+#endif
}
/* port MESSAGE_OVERLAP */
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);
message_put(message);
/* disable encryption if disconnected */
//PERROR("REMOVE ME: state =%d, %d\n", e_crypt_state, e_crypt);
+#ifdef WITH_CRYPT
if (e_crypt_state)
cryptman_message(CI_DISCONNECT_IND, NULL, 0);
+#endif
return;
} else {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) the port has no patterns.\n", ea_endpoint->ep_serial);
}
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)
{
message_put(message);
}
+/* port MESSAGE_3PTY */
+void EndpointAppPBX::port_3pty(struct port_list *portlist, int message_type, union parameter *param)
+{
+ logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+ struct lcr_msg *message;
+ int rc;
+
+#if 0
+ /* bridge for real */
+ if (param->threepty.begin)
+ rc = join_join();
+ else if (param->threepty.end)
+ rc = -ENOTSUP;
+ else
+ return;
+#else
+ /* 3PTY bridge */
+ if (param->threepty.begin)
+ rc = join_3pty();
+ else if (param->threepty.end)
+ rc = split_3pty();
+ else
+ return;
+#endif
+
+ message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_3PTY);
+ message->param.threepty.begin = param->threepty.begin;
+ message->param.threepty.end = param->threepty.end;
+ if (rc < 0)
+ message->param.threepty.error = 1;
+ else
+ message->param.threepty.result = 1;
+ message->param.threepty.invoke_id = param->threepty.invoke_id;
+ logmessage(message->type, &message->param, portlist->port_id, DIRECTION_OUT);
+ message_put(message);
+}
+
/* port MESSAGE_SUSPEND */
/* NOTE: before supending, the inactive-notification must be done in order to set call mixer */
void EndpointAppPBX::port_suspend(struct port_list *portlist, int message_type, union parameter *param)
ea_endpoint->free_portlist(portlist);
}
-/* port MESSAGE_RESUME */
-/* NOTE: before resume, the active-notification must be done in order to set call mixer */
-void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
+/* port MESSAGE_RESUME */
+/* NOTE: before resume, the active-notification must be done in order to set call mixer */
+void EndpointAppPBX::port_resume(struct port_list *portlist, int message_type, union parameter *param)
+{
+ logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+
+ /* epoint is now resumed */
+ ea_endpoint->ep_park = 0;
+
+}
+
+/* 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 MESSAGE_DISABLE_DEJITTER */
+void EndpointAppPBX::port_disable_dejitter(struct port_list *portlist, int message_type, union parameter *param)
{
- logmessage(message_type, param, portlist->port_id, DIRECTION_IN);
+ struct lcr_msg *message;
- /* epoint is now resumed */
- ea_endpoint->ep_park = 0;
+ 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_DISABLE_DEJITTER);
+ memcpy(&message->param, param, sizeof(union parameter));
+ message_put(message);
}
// 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_facility(portlist, message_type, param);
break;
+ case MESSAGE_3PTY:
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming 3PTY facility (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+ port_3pty(portlist, message_type, param);
+ break;
+
/* PORT sends DTMF message */
case MESSAGE_DTMF: /* dtmf digits received */
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) dtmf digit=%c (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, param->dtmf, e_ext.number, e_callerinfo.id);
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;
+
+ case MESSAGE_DISABLE_DEJITTER:
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) incoming disable dejitter message (terminal '%s', caller id '%s')\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+ port_disable_dejitter(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);
/* join MESSAGE_CRYPT */
void EndpointAppPBX::join_crypt(struct port_list *portlist, int message_type, union parameter *param)
{
+#ifdef WITH_CRYPT
switch(param->crypt.type) {
/* message from remote port to "crypt manager" */
case CU_ACTK_REQ: /* activate key-exchange */
default:
PERROR("EPOINT(%d) epoint with terminal '%s' (caller id '%s') unknown crypt message: '%d'\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id, param->crypt.type);
}
+#endif
}
/* join MESSAGE_INFORMATION */
set_tone(portlist, "ringpbx");
else
set_tone(portlist, "ringing");
+
+ if (e_ext.number[0])
+ e_dtmf = 1; /* allow dtmf */
}
/* join MESSAGE_CONNECT */
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 MESSAGE_DISABLE_DEJITTER */
+void EndpointAppPBX::join_disable_dejitter(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_DISABLE_DEJITTER);
+ 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;
+
+ /* JOIN sends a DISABLE_DEJITTER message */
+ case MESSAGE_DISABLE_DEJITTER:
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint with terminal '%s' (caller id '%s') received disable dejitter.\n", ea_endpoint->ep_serial, e_ext.number, e_callerinfo.id);
+ join_disable_dejitter(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;
/* join calls (look for a join that is on hold (same isdn interface/terminal))
*/
-void EndpointAppPBX::join_join(void)
+int EndpointAppPBX::join_join(void)
{
+#ifdef WITH_MISDN
struct lcr_msg *message;
- struct join_relation *our_relation, *other_relation;
- struct join_relation **our_relation_pointer, **other_relation_pointer;
- class Join *our_join, *other_join;
- class JoinPBX *our_joinpbx, *other_joinpbx;
- class EndpointAppPBX *other_eapp; class Endpoint *temp_epoint;
+ struct join_relation *add_relation, *remove_relation;
+ struct join_relation **add_relation_pointer, **remove_relation_pointer;
+ class Join *our_join, *other_join, *add_join, *remove_join;
+ class JoinPBX *our_joinpbx, *other_joinpbx, *add_joinpbx, *remove_joinpbx;
+ class EndpointAppPBX *other_eapp, *remove_eapp;
class Port *our_port, *other_port;
class Pdss1 *our_pdss1, *other_pdss1;
+ class Endpoint *temp_epoint;
- /* are we a candidate to join a join */
+ /* are we a candidate to join a join? */
our_join = find_join_id(ea_endpoint->ep_join_id);
if (!our_join) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
if (our_join->j_type != JOIN_TYPE_PBX) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
our_joinpbx = (class JoinPBX *)our_join;
if (!ea_endpoint->ep_portlist) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
if (!e_ext.number[0]) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
if (!our_port) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
- 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;
+ return -1;
}
our_pdss1 = (class Pdss1 *)our_port;
- /* find an endpoint that is on hold and has the same mISDNport that we are on */
+ /* find an endpoint that has the same mISDNport/ces that we are on */
other_eapp = apppbx_first;
while(other_eapp) {
if (other_eapp == this) {
|| other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
other_pdss1 = (class Pdss1 *)other_port;
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
- if (other_pdss1->p_m_hold /* port is on hold */
+ if (1 //other_pdss1->p_m_hold /* port is on hold */
&& other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
&& other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
break;
other_eapp = other_eapp->next;
}
if (!other_eapp) {
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn interface with port on hold.\n", ea_endpoint->ep_serial);
- return;
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
+ return -1;
}
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port on hold found.\n", ea_endpoint->ep_serial);
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
/* if we have the same join */
if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we an the other have the same join.\n", ea_endpoint->ep_serial);
- return;
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
+ return -1;
}
other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
if (!other_join) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
if (other_join->j_type != JOIN_TYPE_PBX) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
}
other_joinpbx = (class JoinPBX *)other_join;
if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
- return;
+ return -1;
+ }
+
+ /* now find out which is ACTIVE-IDLE and which is ACTIVE-HELD */
+ if (our_pdss1->p_m_hold && !other_pdss1->p_m_hold) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) our relation is on hold and other is active, so we move our relations to other relations\n", ea_endpoint->ep_serial);
+ remove_eapp = this;
+ remove_join = our_join;
+ remove_joinpbx = our_joinpbx;
+ add_join = other_join;
+ add_joinpbx = other_joinpbx;
+ } else {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) our relation is active or other is on hold, so we move ohter relations to our relations\n", ea_endpoint->ep_serial);
+ remove_eapp = other_eapp;
+ remove_join = other_join;
+ remove_joinpbx = other_joinpbx;
+ add_join = our_join;
+ add_joinpbx = our_joinpbx;
}
/* remove relation to endpoint for join on hold */
- other_relation = other_joinpbx->j_relation;
- other_relation_pointer = &other_joinpbx->j_relation;
- while(other_relation) {
- if (other_relation->epoint_id == other_eapp->ea_endpoint->ep_serial) {
- /* detach other endpoint on hold */
- *other_relation_pointer = other_relation->next;
- FREE(other_relation, sizeof(struct join_relation));
+ remove_relation = remove_joinpbx->j_relation;
+ remove_relation_pointer = &remove_joinpbx->j_relation;
+ while(remove_relation) {
+ if (remove_relation->epoint_id == remove_eapp->ea_endpoint->ep_serial) {
+ /* detach other endpoint */
+ *remove_relation_pointer = remove_relation->next;
+ FREE(remove_relation, sizeof(struct join_relation));
cmemuse--;
- other_relation = *other_relation_pointer;
- other_eapp->ea_endpoint->ep_join_id = 0;
+ remove_relation = *remove_relation_pointer;
+ remove_eapp->ea_endpoint->ep_join_id = 0;
continue;
}
/* change join/hold pointer of endpoint to the new join */
- temp_epoint = find_epoint_id(other_relation->epoint_id);
+ temp_epoint = find_epoint_id(remove_relation->epoint_id);
if (temp_epoint) {
- if (temp_epoint->ep_join_id == other_join->j_serial)
- temp_epoint->ep_join_id = our_join->j_serial;
+ if (temp_epoint->ep_join_id == remove_join->j_serial)
+ temp_epoint->ep_join_id = add_join->j_serial;
}
- other_relation_pointer = &other_relation->next;
- other_relation = other_relation->next;
+ remove_relation_pointer = &remove_relation->next;
+ remove_relation = remove_relation->next;
}
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint on hold removed, other enpoints on join relinked (to our join).\n", ea_endpoint->ep_serial);
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) endpoint removed, other enpoints on join relinked.\n", ea_endpoint->ep_serial);
/* join call relations */
- our_relation = our_joinpbx->j_relation;
- our_relation_pointer = &our_joinpbx->j_relation;
- while(our_relation) {
- our_relation_pointer = &our_relation->next;
- our_relation = our_relation->next;
- }
- *our_relation_pointer = other_joinpbx->j_relation;
- other_joinpbx->j_relation = NULL;
+ add_relation = add_joinpbx->j_relation;
+ add_relation_pointer = &add_joinpbx->j_relation;
+ while(add_relation) {
+ add_relation_pointer = &add_relation->next;
+ add_relation = add_relation->next;
+ }
+ *add_relation_pointer = remove_joinpbx->j_relation;
+ remove_joinpbx->j_relation = NULL;
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) relations joined.\n", ea_endpoint->ep_serial);
- /* release endpoint on hold */
- message = message_create(other_joinpbx->j_serial, other_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
+ /* release endpoint */
+ message = message_create(remove_joinpbx->j_serial, remove_eapp->ea_endpoint->ep_serial, JOIN_TO_EPOINT, MESSAGE_RELEASE);
message->param.disconnectinfo.cause = CAUSE_NORMAL; /* normal */
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
message_put(message);
/* if we are not a partyline, we get partyline state from other join */
- our_joinpbx->j_partyline += other_joinpbx->j_partyline;
+ add_joinpbx->j_partyline += remove_joinpbx->j_partyline;
/* remove empty join */
- delete other_join;
- PDEBUG(DEBUG_EPOINT, "EPOINT(%d)d-join completely removed!\n");
+ delete remove_join;
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d)join completely removed!\n", ea_endpoint->ep_serial);
+
+ /* mixer must update */
+ trigger_work(&add_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
+#else
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
+#endif
+
+ return 0;
+}
+
+int EndpointAppPBX::join_3pty(void)
+{
+#ifdef WITH_MISDN
+ class Join *our_join, *other_join;
+ class JoinPBX *our_joinpbx, *other_joinpbx;
+ class EndpointAppPBX *other_eapp;
+ class Port *our_port, *other_port;
+ class Pdss1 *our_pdss1, *other_pdss1;
+
+ /* are we a candidate to join a join? */
+ our_join = find_join_id(ea_endpoint->ep_join_id);
+ if (!our_join) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ if (our_join->j_type != JOIN_TYPE_PBX) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: join is not a pbx join.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ our_joinpbx = (class JoinPBX *)our_join;
+ if (!ea_endpoint->ep_portlist) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we have no port.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ if (!e_ext.number[0]) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we are not internal extension.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ our_port = find_port_id(ea_endpoint->ep_portlist->port_id);
+ if (!our_port) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our port doesn't exist anymore.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ 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 -1;
+ }
+ our_pdss1 = (class Pdss1 *)our_port;
+
+ /* find an endpoint that has the same mISDNport/ces that we are on */
+ other_eapp = apppbx_first;
+ while(other_eapp) {
+ if (other_eapp == this) {
+ other_eapp = other_eapp->next;
+ continue;
+ }
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint candiate: (ep%d) terminal='%s' port=%s join=%d.\n", ea_endpoint->ep_serial, other_eapp->ea_endpoint->ep_serial, other_eapp->e_ext.number, (other_eapp->ea_endpoint->ep_portlist)?"YES":"NO", other_eapp->ea_endpoint->ep_join_id);
+ if (other_eapp->e_ext.number[0] /* has terminal */
+ && other_eapp->ea_endpoint->ep_portlist /* has port */
+ && other_eapp->ea_endpoint->ep_join_id) { /* has join */
+ other_port = find_port_id(other_eapp->ea_endpoint->ep_portlist->port_id);
+ if (other_port) { /* port still exists */
+ if (other_port->p_type==PORT_TYPE_DSS1_NT_OUT
+ || other_port->p_type==PORT_TYPE_DSS1_NT_IN) { /* port is isdn nt-mode */
+ other_pdss1 = (class Pdss1 *)other_port;
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of type isdn! comparing our portnum=%d with other's portnum=%d hold=%s ces=%d\n", ea_endpoint->ep_serial, our_pdss1->p_m_mISDNport->portnum, other_pdss1->p_m_mISDNport->portnum, (other_pdss1->p_m_hold)?"YES":"NO", other_pdss1->p_m_d_ces);
+ if (1 //other_pdss1->p_m_hold /* port is on hold */
+ && other_pdss1->p_m_mISDNport == our_pdss1->p_m_mISDNport /* same isdn interface */
+ && other_pdss1->p_m_d_ces == our_pdss1->p_m_d_ces) /* same tei+sapi */
+ break;
+ } else {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port is of other type!\n", ea_endpoint->ep_serial);
+ }
+ } else {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) comparing other endpoint's port doesn't exist enymore.\n", ea_endpoint->ep_serial);
+ }
+ }
+ other_eapp = other_eapp->next;
+ }
+ if (!other_eapp) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no other endpoint on same isdn terminal.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) port with same terminal found.\n", ea_endpoint->ep_serial);
+
+ /* if we have the same join */
+ if (other_eapp->ea_endpoint->ep_join_id == ea_endpoint->ep_join_id) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: we and the other have the same join.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ other_join = find_join_id(other_eapp->ea_endpoint->ep_join_id);
+ if (!other_join) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ if (other_join->j_type != JOIN_TYPE_PBX) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join is not a pbx join.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ other_joinpbx = (class JoinPBX *)other_join;
+ if (our_joinpbx->j_partyline && other_joinpbx->j_partyline) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: both joins are partylines.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+
+ if (our_joinpbx->j_3pty) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: our join already doing 3PTY.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ if (other_joinpbx->j_3pty) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: other join already doing 3PTY.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+
+ /* set 3PTY bridge */
+ other_joinpbx->j_3pty = our_joinpbx->j_serial;
+ our_joinpbx->j_3pty = other_joinpbx->j_serial;
/* mixer must update */
- our_joinpbx->j_updatebridge = 1; /* update mixer flag */
+ trigger_work(&our_joinpbx->j_updatebridge);
+ trigger_work(&other_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
+#else
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot join: no mISDN support anyway.\n", ea_endpoint->ep_serial);
+#endif
+
+ return 0;
}
+int EndpointAppPBX::split_3pty(void)
+{
+#ifdef WITH_MISDN
+ class Join *our_join, *other_join;
+ class JoinPBX *our_joinpbx, *other_joinpbx;
+
+ /* are we a candidate to join a join? */
+ our_join = find_join_id(ea_endpoint->ep_join_id);
+ if (!our_join) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: our join doesn't exist anymore.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ if (our_join->j_type != JOIN_TYPE_PBX) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: join is not a pbx join.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ our_joinpbx = (class JoinPBX *)our_join;
+
+ if (!our_joinpbx->j_3pty) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: we don't have a 3PTY.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+
+ other_join = find_join_id(our_joinpbx->j_3pty);
+ if (!other_join) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: other join doesn't exist anymore.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ if (other_join->j_type != JOIN_TYPE_PBX) {
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: join is not a pbx join.\n", ea_endpoint->ep_serial);
+ return -1;
+ }
+ other_joinpbx = (class JoinPBX *)other_join;
+
+ our_joinpbx->j_3pty = 0;
+ other_joinpbx->j_3pty = 0;
+
+ /* mixer must update */
+ trigger_work(&our_joinpbx->j_updatebridge);
+ trigger_work(&other_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
+#else
+ PDEBUG(DEBUG_EPOINT, "EPOINT(%d) cannot split: no mISDN support anyway.\n", ea_endpoint->ep_serial);
+#endif
+
+ return 0;
+}
/* check if we have an external call
* this is used to check for encryption ability
*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);
add_trace("from", NULL, "CH(%lu)", port_id);
if (param->setup.callerinfo.extension[0])
add_trace("extension", NULL, "%s", param->setup.callerinfo.extension);
+ if (param->setup.callerinfo.interface[0])
+ add_trace("interface", "from", "%s", param->setup.callerinfo.interface);
+ if (param->setup.dialinginfo.interfaces[0])
+ add_trace("interface", "to", "%s", param->setup.dialinginfo.interfaces);
add_trace("caller id", "number", "%s", numberrize_callerinfo(param->setup.callerinfo.id, param->setup.callerinfo.ntype, options.national, options.international));
switch(param->setup.callerinfo.present) {
case INFO_PRESENT_RESTRICTED:
}
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)
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)
break;
#endif
+ case MESSAGE_3PTY:
+ if (param->threepty.begin)
+ trace_header("Begin3PTY", dir);
+ if (param->threepty.end)
+ trace_header("End3PTY", dir);
+ if (param->threepty.invoke)
+ add_trace("action", NULL, "invoke");
+ if (param->threepty.result)
+ add_trace("action", NULL, "result");
+ if (param->threepty.error)
+ add_trace("action", NULL, "error");
+ add_trace("invoke-id", NULL, "%d", param->threepty.invoke_id);
+ end_trace();
+ break;
+
+ case MESSAGE_DISABLE_DEJITTER:
+ trace_header("DISBALE_DEJITTER", dir);
+ if (param->queue)
+ add_trace("queue", NULL, "%d", param->queue);
+ end_trace();
+ break;
+
default:
PERROR("EPOINT(%d) message not of correct type (%d)\n", ea_endpoint->ep_serial, message_type);
}