222 lines
7.3 KiB
C++
222 lines
7.3 KiB
C++
/*****************************************************************************\
|
|
** **
|
|
** LCR **
|
|
** **
|
|
**---------------------------------------------------------------------------**
|
|
** Copyright: Andreas Eversberg **
|
|
** **
|
|
** mISDN remote **
|
|
** **
|
|
\*****************************************************************************/
|
|
|
|
#include "main.h"
|
|
|
|
unsigned int new_remote = 0x00000001;
|
|
|
|
/*
|
|
* 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)
|
|
{
|
|
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;
|
|
|
|
/* 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);
|
|
|
|
PDEBUG(DEBUG_GSM, "Created new RemotePort(%s).\n", portname);
|
|
|
|
}
|
|
|
|
/*
|
|
* destructor
|
|
*/
|
|
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);
|
|
|
|
}
|
|
|
|
/*
|
|
* endpoint sends messages to the port
|
|
*/
|
|
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))
|
|
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;
|
|
return 0;
|
|
}
|
|
bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
|
|
|
|
/* attach only if not already */
|
|
epointlist = p_epointlist;
|
|
while(epointlist) {
|
|
if (epointlist->epoint_id == epoint_id)
|
|
break;
|
|
epointlist = epointlist->next;
|
|
}
|
|
if (!epointlist)
|
|
epointlist_new(epoint_id);
|
|
|
|
/* set context to pbx */
|
|
SCPY(param->setup.context, "pbx");
|
|
}
|
|
|
|
/* 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);
|
|
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;
|
|
return 0;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
void Premote::message_remote(int message_type, union parameter *param)
|
|
{
|
|
class Endpoint *epoint;
|
|
struct lcr_msg *message;
|
|
int channel;
|
|
int ret;
|
|
|
|
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);
|
|
|
|
/* 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);
|
|
|
|
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");
|
|
|
|
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;
|
|
}
|
|
|
|
/* 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));
|
|
message_put(message);
|
|
|
|
if (message_type == MESSAGE_RELEASE) {
|
|
new_state(PORT_STATE_RELEASE);
|
|
delete this;
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* select free bchannel from loopback interface */
|
|
int Premote::hunt_bchannel(void)
|
|
{
|
|
return loop_hunt_bchannel(this, p_m_mISDNport);
|
|
}
|
|
|
|
|
|
|