Adding simple bridge application to forward calls without PBX app.
Call received on an interface can directly be forwarded to a given destination interface, instead of routing the call through PBX application. This way calls can be forwarded without going through route.conf. Currently only SIP and GSM destinations are supported. Also there are no tones generated, if one side provides no tones, but the other wants to receive them. The keyword "bridge <output interface>" in interface.conf is used. Without that keyword, incomming calls are handled as usual.
This commit is contained in:
parent
d928442c51
commit
74a7fe54a8
10
Makefile.am
10
Makefile.am
|
@ -134,12 +134,12 @@ endif
|
|||
INCLUDES = $(all_includes) $(GSM_INCLUDE) $(SS5_INCLUDE) $(SIP_INCLUDE) -Wall $(INSTALLATION_DEFINES)
|
||||
|
||||
lcr_SOURCES = \
|
||||
main.c select.c trace.c \ options.c \ tones.c \ alawulaw.c \ cause.c \ interface.c \ message.c \ callerid.c \ socket_server.c \
|
||||
port.cpp \ vbox.cpp \ mISDN.cpp \ dss1.cpp \ loop.c remote.cpp \
|
||||
main.c select.c trace.c options.c tones.c alawulaw.c cause.c interface.c message.c callerid.c socket_server.c \
|
||||
port.cpp vbox.cpp mISDN.cpp dss1.cpp loop.c remote.cpp \
|
||||
$(GSM_SOURCE) $(SS5_SOURCE) $(SIP_SOURCE) \
|
||||
endpoint.cpp \ endpointapp.cpp \
|
||||
apppbx.cpp \ route.c \ action.cpp action_efi.cpp \ action_vbox.cpp \ extension.c \ crypt.cpp \ mail.c \
|
||||
join.cpp \ joinpbx.cpp \ joinremote.cpp
|
||||
endpoint.cpp endpointapp.cpp \
|
||||
appbridge.cpp apppbx.cpp route.c action.cpp action_efi.cpp action_vbox.cpp extension.c crypt.cpp mail.c \
|
||||
join.cpp joinpbx.cpp joinremote.cpp
|
||||
|
||||
lcr_LDADD = $(LIBCRYPTO) -lmisdn -lpthread $(GSM_LIB) $(SIP_LIB)
|
||||
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
/*****************************************************************************\
|
||||
** **
|
||||
** Linux Call Router **
|
||||
** **
|
||||
**---------------------------------------------------------------------------**
|
||||
** Copyright: Andreas Eversberg **
|
||||
** **
|
||||
** The EndpointAppBridge implements direct bridge between interfaces **
|
||||
** **
|
||||
\*****************************************************************************/
|
||||
|
||||
|
||||
#include "main.h"
|
||||
|
||||
class EndpointAppBridge *appbridge_first = NULL;
|
||||
|
||||
/*
|
||||
* EndpointAppBridge constructor
|
||||
*/
|
||||
EndpointAppBridge::EndpointAppBridge(class Endpoint *epoint, int origin) : EndpointApp(epoint, origin, EAPP_TYPE_BRIDGE)
|
||||
{
|
||||
class EndpointAppBridge **apppointer;
|
||||
|
||||
/* add application to chain */
|
||||
next = NULL;
|
||||
apppointer = &appbridge_first;
|
||||
while(*apppointer)
|
||||
apppointer = &((*apppointer)->next);
|
||||
*apppointer = this;
|
||||
|
||||
PDEBUG(DEBUG_EPOINT, "Bridge endpoint created\n");
|
||||
}
|
||||
|
||||
/*
|
||||
* EpointAppBridge destructor
|
||||
*/
|
||||
EndpointAppBridge::~EndpointAppBridge(void)
|
||||
{
|
||||
class EndpointAppBridge *temp, **tempp;
|
||||
|
||||
/* detach */
|
||||
temp =appbridge_first;
|
||||
tempp = &appbridge_first;
|
||||
while(temp) {
|
||||
if (temp == this)
|
||||
break;
|
||||
|
||||
tempp = &temp->next;
|
||||
temp = temp->next;
|
||||
}
|
||||
if (temp == 0)
|
||||
FATAL("Endpoint not in endpoint's list.\n");
|
||||
*tempp = next;
|
||||
|
||||
PDEBUG(DEBUG_EPOINT, "Bridge endpoint destroyed\n");
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* trace header for application
|
||||
*/
|
||||
void EndpointAppBridge::trace_header(const char *name, int direction)
|
||||
{
|
||||
struct trace _trace;
|
||||
|
||||
char msgtext[sizeof(_trace.name)];
|
||||
|
||||
SCPY(msgtext, name);
|
||||
|
||||
/* init trace with given values */
|
||||
start_trace(-1,
|
||||
NULL,
|
||||
"", //numberrize_callerinfo(e_callerinfo.id, e_callerinfo.ntype, options.national, options.international),
|
||||
"", // e_dialinginfo.id,
|
||||
direction,
|
||||
CATEGORY_EP,
|
||||
ea_endpoint->ep_serial,
|
||||
msgtext);
|
||||
}
|
||||
|
||||
/* hunts for the given interface
|
||||
* it does not need to have an mISDNport instance */
|
||||
struct interface *EndpointAppBridge::hunt_interface(char *ifname)
|
||||
{
|
||||
struct interface *interface;
|
||||
int there_is_an_external = 0;
|
||||
|
||||
interface = interface_first;
|
||||
|
||||
/* first find the given interface or, if not given, one with no extension */
|
||||
checknext:
|
||||
if (!interface) {
|
||||
if (!there_is_an_external && !(ifname && ifname[0])) {
|
||||
trace_header("CHANNEL SELECTION (no external interface specified)", DIRECTION_NONE);
|
||||
add_trace("info", NULL, "Add 'extern' parameter to interface.conf.");
|
||||
end_trace();
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* check for given interface */
|
||||
if (ifname && ifname[0]) {
|
||||
if (!strcasecmp(interface->name, ifname)) {
|
||||
/* found explicit interface */
|
||||
trace_header("CHANNEL SELECTION (found given interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", ifname);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
|
||||
} else {
|
||||
if (interface->external) {
|
||||
there_is_an_external = 1;
|
||||
/* found non extension */
|
||||
trace_header("CHANNEL SELECTION (found external interface)", DIRECTION_NONE);
|
||||
add_trace("interface", NULL, "%s", interface->name);
|
||||
end_trace();
|
||||
goto foundif;
|
||||
}
|
||||
}
|
||||
|
||||
interface = interface->next;
|
||||
goto checknext;
|
||||
foundif:
|
||||
|
||||
return interface;
|
||||
}
|
||||
|
||||
|
||||
/* port MESSAGE_SETUP */
|
||||
void EndpointAppBridge::port_setup(struct port_list *portlist, int message_type, union parameter *param)
|
||||
{
|
||||
struct interface *interface_in = interface_first;
|
||||
struct interface *interface_out = interface_first;
|
||||
struct port_settings port_settings;
|
||||
class Port *port = NULL;
|
||||
struct lcr_msg *message;
|
||||
unsigned int bridge_id;
|
||||
unsigned int source_port_id = portlist->port_id;
|
||||
char portname[64];
|
||||
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received setup from='%s' to='%s'\n", ea_endpoint->ep_serial, param->setup.callerinfo.id, param->setup.dialinginfo.id);
|
||||
|
||||
if (!ea_endpoint->ep_portlist) {
|
||||
PERROR("Endpoint has no port in portlist\n");
|
||||
return;
|
||||
}
|
||||
if (ea_endpoint->ep_portlist->next) {
|
||||
PDEBUG(DEBUG_EPOINT, "Endpoint already received setup, ignoring.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
while (interface_in) {
|
||||
if (!strcmp(interface_in->name, param->setup.callerinfo.interface))
|
||||
break;
|
||||
interface_in = interface_in->next;
|
||||
}
|
||||
if (!interface_in) {
|
||||
fail:
|
||||
PERROR("Cannot find source interface %s.\n", param->setup.callerinfo.interface);
|
||||
message = message_create(ea_endpoint->ep_serial, portlist->port_id, EPOINT_TO_PORT, MESSAGE_RELEASE);
|
||||
message->param.disconnectinfo.cause = 47;
|
||||
message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
|
||||
message_put(message);
|
||||
|
||||
/* destroy endpoint */
|
||||
ea_endpoint->ep_use = 0;
|
||||
trigger_work(&ea_endpoint->ep_delete);
|
||||
return;
|
||||
}
|
||||
|
||||
while (interface_out) {
|
||||
if (!strcmp(interface_out->name, interface_in->bridge_if))
|
||||
break;
|
||||
interface_out = interface_out->next;
|
||||
}
|
||||
if (!interface_out) {
|
||||
PERROR("Cannot find destination interface %s.\n", interface_in->bridge_if);
|
||||
goto fail;
|
||||
return;
|
||||
}
|
||||
|
||||
/* create port for interface */
|
||||
SPRINT(portname, "%s-%d-out", interface_out->name, 0);
|
||||
memset(&port_settings, 0, sizeof(port_settings));
|
||||
#ifdef WITH_SIP
|
||||
if (interface_out->sip) {
|
||||
port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface_out);
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_GSM_BS
|
||||
if (interface_out->gsm_bs) {
|
||||
port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, portname, &port_settings, interface_out);
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_GSM_MS
|
||||
if (interface_out->gsm_ms) {
|
||||
port = new Pgsm_bs(PORT_TYPE_GSM_MS_OUT, portname, &port_settings, interface_out);
|
||||
}
|
||||
#endif
|
||||
if (!port)
|
||||
FATAL("Remote interface, but not supported???\n");
|
||||
portlist = ea_endpoint->portlist_new(port->p_serial, port->p_type, interface_out->is_earlyb == IS_YES);
|
||||
if (!portlist)
|
||||
FATAL("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
|
||||
/* forward setup */
|
||||
message_forward(ea_endpoint->ep_serial, port->p_serial, EPOINT_TO_PORT, param);
|
||||
|
||||
/* apply bridge to interfaces */
|
||||
/* FIXME: use mISDN bridge for mISDN ports */
|
||||
bridge_id = join_serial++;
|
||||
message = message_create(ea_endpoint->ep_serial, source_port_id, EPOINT_TO_PORT, MESSAGE_BRIDGE);
|
||||
message->param.bridge_id = bridge_id;
|
||||
message_put(message);
|
||||
message = message_create(ea_endpoint->ep_serial, port->p_serial, EPOINT_TO_PORT, MESSAGE_BRIDGE);
|
||||
message->param.bridge_id = bridge_id;
|
||||
message_put(message);
|
||||
}
|
||||
|
||||
/* port MESSAGE_RELEASE */
|
||||
void EndpointAppBridge::port_release(struct port_list *portlist, int message_type, union parameter *param)
|
||||
{
|
||||
unsigned int remote;
|
||||
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received release from port\n");
|
||||
|
||||
if (!ea_endpoint->ep_portlist || !ea_endpoint->ep_portlist->next)
|
||||
goto out;
|
||||
if (ea_endpoint->ep_portlist->port_id == portlist->port_id)
|
||||
remote = ea_endpoint->ep_portlist->next->port_id;
|
||||
else
|
||||
remote = ea_endpoint->ep_portlist->port_id;
|
||||
/* forward release */
|
||||
message_forward(ea_endpoint->ep_serial, remote, EPOINT_TO_PORT, param);
|
||||
|
||||
out:
|
||||
/* destroy endpoint */
|
||||
ea_endpoint->ep_use = 0;
|
||||
trigger_work(&ea_endpoint->ep_delete);
|
||||
}
|
||||
|
||||
/* port other messages */
|
||||
void EndpointAppBridge::port_other(struct port_list *portlist, int message_type, union parameter *param)
|
||||
{
|
||||
unsigned int remote;
|
||||
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) epoint received message %d from port\n", message_type);
|
||||
|
||||
if (!ea_endpoint->ep_portlist || !ea_endpoint->ep_portlist->next)
|
||||
return;
|
||||
if (ea_endpoint->ep_portlist->port_id == portlist->port_id)
|
||||
remote = ea_endpoint->ep_portlist->next->port_id;
|
||||
else
|
||||
remote = ea_endpoint->ep_portlist->port_id;
|
||||
/* forward release */
|
||||
message_forward(ea_endpoint->ep_serial, remote, EPOINT_TO_PORT, param);
|
||||
}
|
||||
|
||||
/* port sends message to the endpoint
|
||||
*/
|
||||
void EndpointAppBridge::ea_message_port(unsigned int port_id, int message_type, union parameter *param)
|
||||
{
|
||||
struct port_list *portlist;
|
||||
|
||||
portlist = ea_endpoint->ep_portlist;
|
||||
while(portlist) {
|
||||
if (port_id == portlist->port_id)
|
||||
break;
|
||||
portlist = portlist->next;
|
||||
}
|
||||
if (!portlist) {
|
||||
PDEBUG(DEBUG_EPOINT, "EPOINT(%d) warning: port is not related to this endpoint. This may happen, if port has been released after the message was created.\n", ea_endpoint->ep_serial);
|
||||
return;
|
||||
}
|
||||
|
||||
// PDEBUG(DEBUG_EPOINT, "received message %d (terminal %s, caller id %s)\n", message, e_ext.number, e_callerinfo.id);
|
||||
switch(message_type) {
|
||||
/* PORT sends SETUP message */
|
||||
case MESSAGE_SETUP:
|
||||
port_setup(portlist, message_type, param);
|
||||
break;
|
||||
|
||||
/* PORT sends RELEASE message */
|
||||
case MESSAGE_RELEASE:
|
||||
port_release(portlist, message_type, param);
|
||||
break;
|
||||
|
||||
default:
|
||||
port_other(portlist, message_type, param);
|
||||
}
|
||||
|
||||
/* Note: this endpoint may be destroyed, so we MUST return */
|
||||
}
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
/*****************************************************************************\
|
||||
** **
|
||||
** Linux Call Router **
|
||||
** **
|
||||
**---------------------------------------------------------------------------**
|
||||
** Copyright: Andreas Eversberg **
|
||||
** **
|
||||
** EndpointAppBridge header file **
|
||||
** **
|
||||
\*****************************************************************************/
|
||||
|
||||
|
||||
extern class EndpointAppBridge *appbridge_first;
|
||||
|
||||
/* structure of an EndpointAppBridge */
|
||||
class EndpointAppBridge : public EndpointApp
|
||||
{
|
||||
public:
|
||||
EndpointAppBridge(class Endpoint *epoint, int origin);
|
||||
~EndpointAppBridge();
|
||||
|
||||
class EndpointAppBridge *next; /* next in list of apps */
|
||||
|
||||
/* messages */
|
||||
void port_setup(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void port_release(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void port_other(struct port_list *portlist, int message_type, union parameter *param);
|
||||
void ea_message_port(unsigned int port_id, int message, union parameter *param);
|
||||
struct interface *hunt_interface(char *ifname);
|
||||
|
||||
void trace_header(const char *name, int direction);
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -26,7 +26,7 @@ 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;
|
||||
|
||||
|
|
3
dss1.cpp
3
dss1.cpp
|
@ -729,8 +729,7 @@ void Pdss1::setup_ind(unsigned int cmd, unsigned int pid, struct l3_msg *l3m)
|
|||
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, p_m_mISDNport->ifport->interface->app); //incoming
|
||||
epointlist_new(epoint->ep_serial);
|
||||
|
||||
/* send setup message to endpoit */
|
||||
|
|
|
@ -28,6 +28,7 @@ class Endpoint
|
|||
unsigned int ep_serial; /* a unique serial to identify */
|
||||
|
||||
/* applocaton relation */
|
||||
int ep_app_type;
|
||||
class EndpointApp *ep_app; /* link to application class */
|
||||
|
||||
/* port relation */
|
||||
|
|
|
@ -14,9 +14,10 @@
|
|||
/*
|
||||
* EndpointApp constructor
|
||||
*/
|
||||
EndpointApp::EndpointApp(class Endpoint *epoint, int origin)
|
||||
EndpointApp::EndpointApp(class Endpoint *epoint, int origin, int type)
|
||||
{
|
||||
ea_endpoint = epoint;
|
||||
ea_type = type;
|
||||
classuse++;
|
||||
}
|
||||
|
||||
|
@ -40,3 +41,26 @@ void EndpointApp::ea_message_join(unsigned int join_id, int message_type, union
|
|||
PDEBUG(DEBUG_EPOINT, "%s: Spare function.\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
|
||||
/* create endpoint app */
|
||||
class EndpointApp *new_endpointapp(class Endpoint *epoint, int origin, int type)
|
||||
{
|
||||
class EndpointApp *app = NULL;
|
||||
|
||||
switch (type) {
|
||||
case EAPP_TYPE_PBX:
|
||||
app = new EndpointAppPBX(epoint, origin);
|
||||
break;
|
||||
case EAPP_TYPE_BRIDGE:
|
||||
app = new EndpointAppBridge(epoint, origin);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!app)
|
||||
FATAL("Failed to create endpoint APP (type %d)\n", type);
|
||||
|
||||
epoint->ep_app_type = type;
|
||||
epoint->ep_app = app;
|
||||
|
||||
return app;
|
||||
}
|
||||
|
|
|
@ -9,16 +9,21 @@
|
|||
** **
|
||||
\*****************************************************************************/
|
||||
|
||||
#define EAPP_TYPE_PBX 0
|
||||
#define EAPP_TYPE_BRIDGE 1
|
||||
|
||||
/* structure of an EndpointApp */
|
||||
class EndpointApp
|
||||
{
|
||||
public:
|
||||
EndpointApp(class Endpoint *epoint, int origin);
|
||||
EndpointApp(class Endpoint *epoint, int origin, int type);
|
||||
virtual ~EndpointApp();
|
||||
|
||||
int ea_type;
|
||||
class Endpoint *ea_endpoint;
|
||||
virtual void ea_message_port(unsigned int port_id, int message, union parameter *param);
|
||||
virtual void ea_message_join(unsigned int join_id, int message, union parameter *param);
|
||||
};
|
||||
|
||||
class EndpointApp *new_endpointapp(class Endpoint *epoint, int origin, int type);
|
||||
|
||||
|
|
14
gsm_bs.cpp
14
gsm_bs.cpp
|
@ -212,6 +212,17 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
|
|||
class Endpoint *epoint;
|
||||
struct lcr_msg *message;
|
||||
struct gsm_mncc *mode, *proceeding, *frame;
|
||||
struct interface *interface = interface_first;
|
||||
|
||||
while (interface) {
|
||||
if (!strcmp(interface->name, p_g_interface_name))
|
||||
break;
|
||||
interface = interface->next;
|
||||
}
|
||||
if (!interface) {
|
||||
PERROR("Cannot find interface %s.\n", p_g_interface_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* process given callref */
|
||||
gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_IN);
|
||||
|
@ -299,8 +310,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
|
|||
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);
|
||||
|
||||
/* modify lchan to GSM codec V1 */
|
||||
|
|
14
gsm_ms.cpp
14
gsm_ms.cpp
|
@ -68,6 +68,17 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
|
|||
class Endpoint *epoint;
|
||||
struct lcr_msg *message;
|
||||
struct gsm_mncc *mode, *proceeding, *frame;
|
||||
struct interface *interface = interface_first;
|
||||
|
||||
while (interface) {
|
||||
if (!strcmp(interface->name, p_g_interface_name))
|
||||
break;
|
||||
interface = interface->next;
|
||||
}
|
||||
if (!interface) {
|
||||
PERROR("Cannot find interface %s.\n", p_g_interface_name);
|
||||
return;
|
||||
}
|
||||
|
||||
/* process given callref */
|
||||
gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_IN);
|
||||
|
@ -264,8 +275,7 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
|
|||
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);
|
||||
|
||||
/* modify lchan to GSM codec V1 */
|
||||
|
|
17
interface.c
17
interface.c
|
@ -1072,16 +1072,25 @@ static int inter_remote(struct interface *interface, char *filename, int line, c
|
|||
ifport->remote = 1;
|
||||
SCPY(ifport->remote_app, value);
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int inter_shutdown(struct interface *interface, char *filename, int line, char *parameter, char *value)
|
||||
{
|
||||
interface->shutdown = 1;
|
||||
|
||||
return(0);
|
||||
}
|
||||
static int inter_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
|
||||
{
|
||||
if (!value || !value[0]) {
|
||||
SPRINT(interface_error, "Error in %s (line %d): Missing destination interface name.\n", filename, line);
|
||||
return(-1);
|
||||
}
|
||||
interface->app = EAPP_TYPE_BRIDGE;
|
||||
SCPY(interface->bridge_if, value);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
|
@ -1230,6 +1239,10 @@ struct interface_param interface_param[] = {
|
|||
"Prevents sending notify messages to this interface. A call placed on hold will\n"
|
||||
"Not affect the remote end (phone or telcom switch).\n"
|
||||
"This parameter must follow a 'port' parameter."},
|
||||
{"bridge", &inter_bridge, "<destination interface>",
|
||||
"Define bridge application for this interface. All calls received on this\n"
|
||||
"interface will be directly bridged to the given destination interface.\n"
|
||||
"There will be no PBX application, nor routing."},
|
||||
|
||||
#ifdef WITH_SS5
|
||||
{"ccitt5", &inter_ss5, "[<feature> [feature ...]]",
|
||||
|
|
|
@ -89,6 +89,8 @@ struct interface_screen {
|
|||
struct interface {
|
||||
struct interface *next;
|
||||
char name[64]; /* name of interface */
|
||||
int app; /* application to use for interface (0 = PBX) */
|
||||
char bridge_if[64]; /* name of destination interface for bridge application */
|
||||
int external; /* interface used for external calls */
|
||||
int extension; /* calls are handled as extension */
|
||||
int is_tones; /* generate tones */
|
||||
|
|
2
join.h
2
join.h
|
@ -35,3 +35,5 @@ extern class Join *join_first;
|
|||
|
||||
class Join *find_join_id(unsigned int join_id);
|
||||
|
||||
extern unsigned int join_serial;
|
||||
|
||||
|
|
|
@ -917,8 +917,7 @@ int JoinPBX::out_setup(unsigned int epoint_id, int message_type, union parameter
|
|||
epoint = new Endpoint(0, j_serial);
|
||||
if (!epoint)
|
||||
FATAL("No memory for Endpoint instance\n");
|
||||
if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 1))) // outgoing
|
||||
FATAL("No memory for Endpoint Application instance\n");
|
||||
epoint->ep_app = new_endpointapp(epoint, 1, EAPP_TYPE_PBX); // outgoing
|
||||
relation->epoint_id = epoint->ep_serial;
|
||||
/* send setup message to new endpoint */
|
||||
//printf("JOLLY DEBUG: %d\n",join_countrelations(j_serial));
|
||||
|
|
|
@ -85,8 +85,7 @@ void JoinRemote::message_remote(int message_type, union parameter *param)
|
|||
FATAL("No memory for Endpoint instance\n");
|
||||
j_epoint_id = epoint->ep_serial;
|
||||
PDEBUG(DEBUG_JOIN, "Created endpoint %d\n", j_epoint_id);
|
||||
if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 1))) // outgoing
|
||||
FATAL("No memory for Endpoint Application instance\n");
|
||||
epoint->ep_app = new_endpointapp(epoint, 1, EAPP_TYPE_PBX); // outgoing
|
||||
}
|
||||
|
||||
/* set serial on bchannel message
|
||||
|
|
3
main.h
3
main.h
|
@ -32,8 +32,6 @@
|
|||
|
||||
#define NAME "LCR"
|
||||
|
||||
#define DEFAULT_ENDPOINT_APP EndpointAppPBX
|
||||
|
||||
#define VERSION_STRING VERSION
|
||||
|
||||
extern int memuse;
|
||||
|
@ -143,6 +141,7 @@ extern "C" {
|
|||
#include "endpoint.h"
|
||||
#include "endpointapp.h"
|
||||
#include "apppbx.h"
|
||||
#include "appbridge.h"
|
||||
#include "callerid.h"
|
||||
#include "route.h"
|
||||
#include "port.h"
|
||||
|
|
2
port.cpp
2
port.cpp
|
@ -1287,7 +1287,7 @@ int Port::bridge_tx(unsigned char *data, int len)
|
|||
if (!remote)
|
||||
return -EINVAL;
|
||||
|
||||
// printf("Traffic: %u -> %u (bridge %u)\n", p_serial, to_port->p_serial, p_bridge->bridge_id);
|
||||
// printf("Traffic: %u -> %u (bridge %u)\n", p_serial, remote->p_serial, p_bridge->bridge_id);
|
||||
return remote->bridge_rx(data, len);
|
||||
}
|
||||
|
||||
|
|
|
@ -167,8 +167,7 @@ void Premote::message_remote(int message_type, union parameter *param)
|
|||
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, p_m_mISDNport->ifport->interface->app); //incoming
|
||||
|
||||
epointlist_new(epoint->ep_serial);
|
||||
}
|
||||
|
|
15
sip.cpp
15
sip.cpp
|
@ -868,6 +868,7 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
|
|||
PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_s_rtp_ip_remote, p_s_rtp_port_remote);
|
||||
} else {
|
||||
PDEBUG(DEBUG_SIP, "RTP info not given by remote, so we do our own RTP\n");
|
||||
p_s_rtp_bridge = 0;
|
||||
p_s_rtp_payload_type = (options.law=='a') ? RTP_PT_ALAW : RTP_PT_ULAW;
|
||||
|
||||
/* open local RTP peer (if not bridging) */
|
||||
|
@ -1160,6 +1161,17 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
|
|||
class Endpoint *epoint;
|
||||
struct lcr_msg *message;
|
||||
uint8_t payload_type;
|
||||
struct interface *interface = interface_first;
|
||||
|
||||
while (interface) {
|
||||
if (!strcmp(interface->name, inst->interface_name))
|
||||
break;
|
||||
interface = interface->next;
|
||||
}
|
||||
if (!interface) {
|
||||
PERROR("Cannot find interface %s.\n", inst->interface_name);
|
||||
return;
|
||||
}
|
||||
|
||||
if (sip->sip_from && sip->sip_from->a_url)
|
||||
from = sip->sip_from->a_url->url_user;
|
||||
|
@ -1250,8 +1262,7 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
|
|||
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);
|
||||
|
||||
/* send trying (proceeding) */
|
||||
|
|
|
@ -530,7 +530,7 @@ int admin_call(struct admin_list *admin, struct admin_message *msg)
|
|||
|
||||
if (!(epoint = new Endpoint(0, 0)))
|
||||
FATAL("No memory for Endpoint instance\n");
|
||||
if (!(epoint->ep_app = apppbx = new DEFAULT_ENDPOINT_APP(epoint, 1))) // outgoing
|
||||
if (!(epoint->ep_app = apppbx = new EndpointAppPBX(epoint, 1))) // outgoing
|
||||
FATAL("No memory for Endpoint Application instance\n");
|
||||
apppbx->e_adminid = admin->sockserial;
|
||||
admin->epointid = epoint->ep_serial;
|
||||
|
@ -1246,8 +1246,8 @@ int admin_handle_con(struct lcr_fd *fd, unsigned int what, void *instance, int i
|
|||
/*release endpoint if exists */
|
||||
if (admin->epointid) {
|
||||
epoint = find_epoint_id(admin->epointid);
|
||||
if (epoint) {
|
||||
((class DEFAULT_ENDPOINT_APP *)epoint->ep_app)->
|
||||
if (epoint && epoint->ep_app_type == EAPP_TYPE_PBX) {
|
||||
((class EndpointAppPBX *)epoint->ep_app)->
|
||||
release(RELEASE_ALL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, LOCATION_PRIVATE_LOCAL, CAUSE_NORMAL, 0);
|
||||
}
|
||||
}
|
||||
|
|
3
ss5.cpp
3
ss5.cpp
|
@ -1694,8 +1694,7 @@ void Pss5::do_setup(char *dial, int complete)
|
|||
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, p_m_mISDNport->ifport->interface->app); //incoming
|
||||
epointlist_new(epoint->ep_serial);
|
||||
|
||||
/* send setup message to endpoit */
|
||||
|
|
3
vbox.cpp
3
vbox.cpp
|
@ -251,7 +251,8 @@ int VBoxPort::message_epoint(unsigned int epoint_id, int message_id, union param
|
|||
|
||||
case MESSAGE_SETUP: /* dial-out command received from epoint, answer with connect */
|
||||
/* get apppbx */
|
||||
memcpy(&p_vbox_ext, &((class EndpointAppPBX *)(epoint->ep_app))->e_ext, sizeof(p_vbox_ext));
|
||||
if (epoint->ep_app_type == EAPP_TYPE_PBX)
|
||||
memcpy(&p_vbox_ext, &((class EndpointAppPBX *)(epoint->ep_app))->e_ext, sizeof(p_vbox_ext));
|
||||
/* extract optional announcement file */
|
||||
if ((c = strchr(param->setup.dialinginfo.id, ','))) {
|
||||
if (c[1] == '/')
|
||||
|
|
Loading…
Reference in New Issue