#include "main.h"
-unsigned int new_remote = 0x00000001;
+unsigned int new_remote = 1000;
/*
* constructor
*/
-Premote::Premote(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode, int remote_id) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
+Premote::Premote(int type, char *portname, struct port_settings *settings, struct interface *interface, int remote_id) : Port(type, portname, settings, interface)
{
union parameter param;
- p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
- p_m_r_ref = new_remote++;
- SCPY(p_m_r_remote_app, mISDNport->ifport->remote_app);
- p_m_r_handle = 0;
+ p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
+ p_r_ref = new_remote++;
+ SCPY(p_r_remote_app, interface->remote_app);
+ p_r_tones = (interface->is_tones == IS_YES);
+ p_r_earlyb = (interface->is_earlyb == IS_YES);
/* send new ref to remote socket */
memset(¶m, 0, sizeof(union parameter));
if (type == PORT_TYPE_REMOTE_OUT)
param.newref.direction = 1; /* new ref from lcr */
- p_m_r_remote_id = remote_id;
- if (admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_NEWREF, ¶m) < 0)
- FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", mISDNport->ifport->remote_app);
+ p_r_remote_id = remote_id;
+ if (admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_NEWREF, ¶m) < 0)
+ FATAL("No socket with remote application '%s' found, this shall not happen. because we already created one.\n", p_r_remote_app);
- PDEBUG(DEBUG_GSM, "Created new RemotePort(%s).\n", portname);
+ PDEBUG(DEBUG_PORT, "Created new RemotePort(%s).\n", portname);
}
*/
Premote::~Premote()
{
- /* need to remote (import) external channel from remote application */
- if (p_m_r_handle) {
- message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_REMOVE, p_m_r_handle, 0, 0, 0, 0, 0, 0, 1);
- chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
- add_trace("type", NULL, "remove");
- add_trace("channel", NULL, "%d.%d", p_m_r_handle>>8, p_m_r_handle&0xff);
- end_trace();
- }
-
- PDEBUG(DEBUG_GSM, "Destroyed Remote process(%s).\n", p_name);
-
+ PDEBUG(DEBUG_PORT, "Destroyed Remote process(%s).\n", p_name);
}
/*
*/
int Premote::message_epoint(unsigned int epoint_id, int message_type, union parameter *param)
{
- struct lcr_msg *message;
- int channel;
- int ret;
struct epoint_list *epointlist;
- if (PmISDN::message_epoint(epoint_id, message_type, param))
+ if (Port::message_epoint(epoint_id, message_type, param))
return 1;
- if (message_type == MESSAGE_SETUP) {
- ret = channel = hunt_bchannel();
- if (ret < 0)
- goto no_channel;
- /* open channel */
- ret = seize_bchannel(channel, 1);
- if (ret < 0) {
- no_channel:
- message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 34;
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- delete this;
+ switch (message_type) {
+ case MESSAGE_SETUP:
+ struct interface *interface;
+ interface = getinterfacebyname(p_interface_name);
+ if (!interface) {
+ PERROR("Cannot find interface %s.\n", p_interface_name);
return 0;
}
- bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-
/* attach only if not already */
epointlist = p_epointlist;
while(epointlist) {
epointlist_new(epoint_id);
/* set context to pbx */
- SCPY(param->setup.context, "pbx");
+ if (!param->setup.dialinginfo.context[0]) {
+ if (interface->remote_context[0])
+ SCPY(param->setup.dialinginfo.context, interface->remote_context);
+ else
+ SCPY(param->setup.dialinginfo.context, "lcr");
+ }
+ memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo));
+ memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo));
+ memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
+ memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
+ /* screen */
+ do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_interface_name);
+ do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_interface_name);
+ do_screen(1, p_redirinfo.id, sizeof(p_redirinfo.id), &p_redirinfo.ntype, &p_redirinfo.present, p_interface_name);
+ memcpy(¶m->setup.callerinfo, &p_callerinfo, sizeof(p_callerinfo));
+ memcpy(¶m->setup.redirinfo, &p_redirinfo, sizeof(p_redirinfo));
+
+ new_state(PORT_STATE_OUT_SETUP);
+ break;
+
+ case MESSAGE_PROCEEDING:
+ new_state(PORT_STATE_IN_PROCEEDING);
+ break;
+
+ case MESSAGE_ALERTING:
+ new_state(PORT_STATE_IN_ALERTING);
+ break;
+
+ case MESSAGE_CONNECT:
+ memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo));
+ new_state(PORT_STATE_CONNECT);
+ break;
+
+ case MESSAGE_DISCONNECT:
+ new_state(PORT_STATE_OUT_DISCONNECT);
+ break;
+
+ case MESSAGE_RELEASE:
+ new_state(PORT_STATE_RELEASE);
+ break;
}
/* look for Remote's interface */
- if (admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, message_type, param)<0) {
- PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all remote ports.\n", p_m_mISDNport->ifport->remote_app);
+ if (admin_message_from_lcr(p_r_remote_id, p_r_ref, message_type, param)<0) {
+ PERROR("No socket with remote application '%s' found, this shall not happen. Closing socket shall cause release of all remote ports.\n", p_r_remote_app);
return 0;
}
- /* enable audio path */
- if (message_type == MESSAGE_SETUP) {
- union parameter newparam;
- memset(&newparam, 0, sizeof(union parameter));
- admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_PATTERN, &newparam);
- newparam.audiopath = 1;
- admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_AUDIOPATH, &newparam);
- }
-
if (message_type == MESSAGE_RELEASE) {
new_state(PORT_STATE_RELEASE);
delete this;
{
class Endpoint *epoint;
struct lcr_msg *message;
- int channel;
- int ret;
+ struct interface *interface;
+
+ switch (message_type) {
+ case MESSAGE_TRAFFIC:
+ if (p_dov_rx)
+ dov_rx(param->traffic.data, param->traffic.len);
+ /* record audio */
+ if (p_record)
+ record(param->traffic.data, param->traffic.len, 0); // from down
+ if (p_tap)
+ tap(param->traffic.data, param->traffic.len, 0); // from down
+ bridge_tx(param->traffic.data, param->traffic.len);
+ if (p_tone_name[0]) {
+ read_audio(param->traffic.data, param->traffic.len);
+ /* record audio */
+ if (p_record)
+ record(param->traffic.data, param->traffic.len, 1); // from up
+ if (p_tap)
+ tap(param->traffic.data, param->traffic.len, 1); // from up
+ admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param);
+ } else if (p_dov_tx) {
+ /* use receeived traffic to trigger sending DOV */
+ dov_tx(param->traffic.data, param->traffic.len);
+ admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, param);
+ }
+ return;
+
+ case MESSAGE_SETUP:
+ interface = getinterfacebyname(p_interface_name);
+ if (!interface) {
+ PERROR("Cannot find interface %s.\n", p_interface_name);
+ return;
+ }
- if (message_type == MESSAGE_SETUP) {
/* enable audio path */
- union parameter newparam;
- memset(&newparam, 0, sizeof(union parameter));
- admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_PATTERN, &newparam);
- newparam.audiopath = 1;
- admin_message_from_lcr(p_m_r_remote_id, p_m_r_ref, MESSAGE_AUDIOPATH, &newparam);
+ if (interface->is_tones == IS_YES) {
+ union parameter newparam;
+ memset(&newparam, 0, sizeof(union parameter));
+ admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_PATTERN, &newparam);
+ newparam.audiopath = 1;
+ admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_AUDIOPATH, &newparam);
+ }
/* set source interface */
param->setup.callerinfo.itype = p_callerinfo.itype;
- param->setup.callerinfo.isdn_port = p_m_portnum;
- SCPY(param->setup.callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+ SCPY(param->setup.callerinfo.interface, interface->name);
- ret = channel = hunt_bchannel();
- if (ret < 0)
- goto no_channel;
-
- /* open channel */
- ret = seize_bchannel(channel, 1);
- if (ret < 0) {
- no_channel:
- message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
- message->param.disconnectinfo.cause = 34;
- message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
- message_put(message);
- new_state(PORT_STATE_RELEASE);
- delete this;
- return;
- }
- bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-
/* create endpoint */
if (p_epointlist)
FATAL("Incoming call but already got an endpoint.\n");
if (!(epoint = new Endpoint(p_serial, 0)))
FATAL("No memory for Endpoint instance\n");
- if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming
- FATAL("No memory for Endpoint Application instance\n");
+ epoint->ep_app = new_endpointapp(epoint, 0, interface->app); //incoming
epointlist_new(epoint->ep_serial);
- }
- /* set serial on bchannel message
- * also ref is given, so we send message with ref */
- if (message_type == MESSAGE_BCHANNEL) {
- int i = p_m_b_index;
- unsigned int portid = (mISDNloop.port<<8) + i+1+(i>=15);
- switch (param->bchannel.type) {
- case BCHANNEL_REQUEST:
- p_m_r_handle = portid;
- message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_ASSIGN, portid, 0, 0, 0, 0, 0, 0, 1);
- chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
- add_trace("type", NULL, "assign");
- add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
- end_trace();
- break;
- case BCHANNEL_RELEASE:
- p_m_r_handle = 0;
- message_bchannel_to_remote(p_m_r_remote_id, p_m_r_ref, BCHANNEL_REMOVE, portid, 0, 0, 0, 0, 0, 0, 1);
- chan_trace_header(p_m_mISDNport, this, "MESSAGE_BCHANNEL (to remote application)", DIRECTION_NONE);
- add_trace("type", NULL, "remove");
- add_trace("channel", NULL, "%d.%d", portid>>8, portid&0xff);
- end_trace();
- break;
- }
- return;
+ memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo));
+ memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo));
+ memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo));
+ memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo));
+
+ new_state(PORT_STATE_IN_SETUP);
+ break;
+
+ case MESSAGE_PROCEEDING:
+ new_state(PORT_STATE_OUT_PROCEEDING);
+ break;
+
+ case MESSAGE_ALERTING:
+ new_state(PORT_STATE_OUT_ALERTING);
+ break;
+
+ case MESSAGE_CONNECT:
+ memcpy(&p_connectinfo, ¶m->connectinfo, sizeof(p_connectinfo));
+ new_state(PORT_STATE_CONNECT);
+ break;
+
+ case MESSAGE_DISCONNECT:
+ new_state(PORT_STATE_IN_DISCONNECT);
+ break;
+
+ case MESSAGE_RELEASE:
+ new_state(PORT_STATE_RELEASE);
+ break;
}
-
+
/* cannot just forward, because param is not of container "struct lcr_msg" */
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, message_type);
memcpy(&message->param, param, sizeof(message->param));
}
}
-/* select free bchannel from loopback interface */
-int Premote::hunt_bchannel(void)
+/* receive from remote Port instance */
+int Premote::bridge_rx(unsigned char *data, int len)
{
- return loop_hunt_bchannel(this, p_m_mISDNport);
-}
+ union parameter newparam;
+ int l;
+ int ret;
+
+ if ((ret = Port::bridge_rx(data, len)))
+ return ret;
+
+ /* send tones, if connected, or if early audio is enabled in proceeding/alerting state */
+ if (p_state != PORT_STATE_CONNECT
+ && !(p_r_earlyb
+ && (p_state == PORT_STATE_OUT_PROCEEDING
+ || p_state == PORT_STATE_OUT_ALERTING))
+ && !(p_r_tones
+ && (p_state == PORT_STATE_IN_PROCEEDING
+ || p_state == PORT_STATE_IN_ALERTING)))
+ return 0;
+ if (p_tone_name[0])
+ return 0;
+
+ memset(&newparam, 0, sizeof(union parameter));
+ /* split, if exeeds data size */
+ while(len) {
+ l = (len > (int)sizeof(newparam.traffic.data)) ? sizeof(newparam.traffic.data) : len;
+ newparam.traffic.len = l;
+ len -= l;
+ memcpy(newparam.traffic.data, data, l);
+ data += l;
+ /* record audio */
+ if (p_record)
+ record(data, len, 1); // from up
+ if (p_tap)
+ tap(data, len, 1); // from up
+ admin_message_from_lcr(p_r_remote_id, p_r_ref, MESSAGE_TRAFFIC, &newparam);
+ }
+
+ return 0;
+}