Adding simple bridge application to forward calls without PBX app.
authorAndreas Eversberg <jolly@eversberg.eu>
Mon, 16 Jan 2012 08:14:22 +0000 (09:14 +0100)
committerAndreas Eversberg <jolly@eversberg.eu>
Mon, 16 Jan 2012 08:14:22 +0000 (09:14 +0100)
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.

22 files changed:
Makefile.am
appbridge.cpp [new file with mode: 0644]
appbridge.h [new file with mode: 0644]
apppbx.cpp
dss1.cpp
endpoint.h
endpointapp.cpp
endpointapp.h
gsm_bs.cpp
gsm_ms.cpp
interface.c
interface.h
join.h
joinpbx.cpp
joinremote.cpp
main.h
port.cpp
remote.cpp
sip.cpp
socket_server.c
ss5.cpp
vbox.cpp

index 629bb50..a5396b3 100644 (file)
@@ -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)
 
diff --git a/appbridge.cpp b/appbridge.cpp
new file mode 100644 (file)
index 0000000..50808ca
--- /dev/null
@@ -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 */
+}
+
diff --git a/appbridge.h b/appbridge.h
new file mode 100644 (file)
index 0000000..2e4ea06
--- /dev/null
@@ -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);
+};
+
+
+
index bf7988b..cf6f840 100644 (file)
@@ -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;
 
index f0834af..6a718ab 100644 (file)
--- a/dss1.cpp
+++ b/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 */
index a3080bc..a74da30 100644 (file)
@@ -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 */
index 158b3d6..da797de 100644 (file)
 /*
  * 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;
+}
index a24faae..4147c51 100644 (file)
@@ -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);
+
index ed1d2c0..9608be6 100644 (file)
@@ -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 */
index dbd3351..ae99930 100644 (file)
@@ -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 */
index 60e058f..89aa582 100644 (file)
@@ -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 ...]]",
index ea9cbad..4640187 100644 (file)
@@ -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 */
diff --git a/join.h b/join.h
index 442aa5d..331dbc7 100644 (file)
--- a/join.h
+++ b/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;
+
index a98765f..6440f58 100644 (file)
@@ -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));
index 7c03dcd..dbeb0f9 100644 (file)
@@ -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
diff --git a/main.h b/main.h
index 9a97f3a..e0b2193 100644 (file)
--- a/main.h
+++ b/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"
index d6b70c8..8fed914 100644 (file)
--- a/port.cpp
+++ b/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);
 }
 
index 8d7c0bf..e7b9009 100644 (file)
@@ -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);
        }
diff --git a/sip.cpp b/sip.cpp
index 48ce05d..94e9760 100644 (file)
--- a/sip.cpp
+++ b/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) */
index 2fba2eb..800d18d 100644 (file)
@@ -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);
                                }
                        }
diff --git a/ss5.cpp b/ss5.cpp
index a12f936..7157d8f 100644 (file)
--- a/ss5.cpp
+++ b/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 */
index c8c3012..b0268cc 100644 (file)
--- a/vbox.cpp
+++ b/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] == '/')