Added bridgin support for GSM and SIP
authorAndreas Eversberg <jolly@eversberg.eu>
Sun, 15 Jan 2012 08:42:35 +0000 (09:42 +0100)
committerAndreas Eversberg <jolly@eversberg.eu>
Sun, 15 Jan 2012 08:42:35 +0000 (09:42 +0100)
The dependency on mISDN (loopback interface) is completely removed
from GSM and SIP interfaces.

The built in bridge of LCR now forwards audio data between these
interface instances or between these instances and other instances.

Additionally both GSM BS and SIP support direct forwarding of RTP
traffic between  other SIP endpoint and OpenBSC, so no traffic is
forwarded by the LCR itself. This is done by forwarding RTP peer
informations between these interface instances.

25 files changed:
action.cpp
apppbx.cpp
apppbx.h
default/interface.conf
default/options.conf
dss1.cpp
gsm.cpp
gsm.h
gsm_bs.cpp
gsm_bs.h
gsm_ms.cpp
gsm_ms.h
interface.c
interface.h
lcradmin.c
mISDN.cpp
mISDN.h
message.h
mncc.h
port.cpp
port.h
sip.cpp
sip.h
socket_server.c
ss5.cpp

index 514c016..e0a884d 100644 (file)
@@ -74,6 +74,7 @@ void EndpointAppPBX::action_dialing_internal(void)
        struct capa_info        capainfo;
        struct caller_info      callerinfo;
        struct redir_info       redirinfo;
+       struct rtp_info         rtpinfo;
        struct dialing_info     dialinginfo;
        struct port_list        *portlist = ea_endpoint->ep_portlist;
        struct lcr_msg          *message;
@@ -91,6 +92,7 @@ void EndpointAppPBX::action_dialing_internal(void)
        memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
        memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
        memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
+       memcpy(&rtpinfo, &e_rtpinfo, sizeof(rtpinfo));
        memset(&dialinginfo, 0, sizeof(dialinginfo));
        dialinginfo.itype = INFO_ITYPE_ISDN_EXTENSION;
        SCPY(dialinginfo.id, e_dialinginfo.id);
@@ -164,6 +166,7 @@ void EndpointAppPBX::action_dialing_internal(void)
        memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
        memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
        memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
+       memcpy(&message->param.setup.rtpinfo, &rtpinfo, sizeof(struct rtp_info));
        message_put(message);
 }
 
@@ -174,6 +177,7 @@ void EndpointAppPBX::action_dialing_external(void)
        struct capa_info capainfo;
        struct caller_info callerinfo;
        struct redir_info redirinfo;
+       struct rtp_info rtpinfo;
        struct dialing_info dialinginfo;
        char *p;
        struct port_list *portlist = ea_endpoint->ep_portlist;
@@ -206,6 +210,7 @@ void EndpointAppPBX::action_dialing_external(void)
        memcpy(&capainfo, &e_capainfo, sizeof(capainfo));
        memcpy(&callerinfo, &e_callerinfo, sizeof(callerinfo));
        memcpy(&redirinfo, &e_redirinfo, sizeof(redirinfo));
+       memcpy(&rtpinfo, &e_rtpinfo, sizeof(rtpinfo));
        memset(&dialinginfo, 0, sizeof(dialinginfo));
        dialinginfo.itype = INFO_ITYPE_ISDN;
 //     dialinginfo.sending_complete = 0;
@@ -321,6 +326,7 @@ void EndpointAppPBX::action_dialing_external(void)
        memcpy(&message->param.setup.redirinfo, &redirinfo, sizeof(struct redir_info));
        memcpy(&message->param.setup.callerinfo, &callerinfo, sizeof(struct caller_info));
        memcpy(&message->param.setup.capainfo, &capainfo, sizeof(struct capa_info));
+       memcpy(&message->param.setup.rtpinfo, &rtpinfo, sizeof(struct rtp_info));
        message_put(message);
 }
 
index 1b119b2..bf7988b 100644 (file)
@@ -72,6 +72,7 @@ EndpointAppPBX::EndpointAppPBX(class Endpoint *epoint, int origin) : EndpointApp
         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;
@@ -573,6 +574,53 @@ void EndpointAppPBX::set_tone(struct port_list *portlist, const char *tone)
        }
 }
 
+/* hunts for the given interface
+ * it does not need to have an mISDNport instance */
+struct interface *EndpointAppPBX::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;
+}
+
 
 /*
  * hunts an mISDNport that is available for an outgoing call
@@ -839,6 +887,7 @@ void EndpointAppPBX::out_setup(int cfnr)
        int                     cause = CAUSE_RESSOURCEUNAVAIL;
        const char              *p;
        char                    cfp[64];
+       struct interface        *interface;
        struct mISDNport        *mISDNport;
        char                    portname[32];
        char                    *dirname;
@@ -963,54 +1012,67 @@ void EndpointAppPBX::out_setup(int cfnr)
                                        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);
-#ifdef WITH_SS5
-                       if (mISDNport->ss5)
-                               port = ss5_hunt_line(mISDNport);
-                       else
-#endif
+                       /* found interface */
+                       PDEBUG(DEBUG_EPOINT, "EPOINT(%d) calling to interface %s\n", ea_endpoint->ep_serial, ifname);
 #ifdef WITH_GSM_BS
-                       if (mISDNport->gsm_bs)
-                               port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-                       else
+                       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);
+                       } else
 #endif
 #ifdef WITH_GSM_MS
-                       if (mISDNport->gsm_ms)
-                               port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-                       else
+                       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);
+                       } else
 #endif
-#ifdef WITH_SIP
-                       if (mISDNport->ifport->interface->sip)
-                               port = new Psip(PORT_TYPE_SIP_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, mISDNport->ifport->interface);
-                       else
+#ifdef WITH_GSM_MS
+                       if (interface->sip) {
+                               SPRINT(portname, "%s-%d-out", interface->name, 0);
+                               port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+                       } else
 #endif
-                       if (mISDNport->ifport->remote) {
-                               admin = admin_first;
-                               while(admin) {
-                                       if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
-                                               break;
-                                       admin = admin->next;
-                               }
-                               if (!admin) {
-                                       trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
-                                       add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+                       {
+                               /* 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;
                                }
-                               port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
-                       } else
-                               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);
+
+                               SPRINT(portname, "%s-%d-out", mISDNport->ifport->interface->name, mISDNport->portnum);
+#ifdef WITH_SS5
+                               if (mISDNport->ss5)
+                                       port = ss5_hunt_line(mISDNport);
+                               else
+#endif
+                               if (mISDNport->ifport->remote) {
+                                       admin = admin_first;
+                                       while(admin) {
+                                               if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
+                                                       break;
+                                               admin = admin->next;
+                                       }
+                                       if (!admin) {
+                                               trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+                                               add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+                                               end_trace();
+                                               continue;
+                                       }
+                                       port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
+                               } else
+                                       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("Failed to create Port instance\n");
                        PDEBUG(DEBUG_EPOINT, "EPOINT(%d) got port %s\n", ea_endpoint->ep_serial, port->p_name);
@@ -1019,7 +1081,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                        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, interface->is_earlyb == IS_YES);
                        if (!portlist) {
                                PERROR("EPOINT(%d) cannot allocate port_list relation\n", ea_endpoint->ep_serial);
                                delete port;
@@ -1039,6 +1101,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                        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);
@@ -1203,56 +1266,69 @@ void EndpointAppPBX::out_setup(int cfnr)
                                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");
+                       /* search interface */
+                       interface = hunt_interface(e_dialinginfo.interfaces[0]?e_dialinginfo.interfaces:NULL);
+                       if (!interface) {
+                               trace_header("INTERFACE (not found)", DIRECTION_NONE);
+                               add_trace("interface", NULL, "%s", ifname);
                                end_trace();
                                goto check_anycall_extern;
                        }
-                       /* 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
+                       /* found interface */
 #ifdef WITH_GSM_BS
-                       if (mISDNport->gsm_bs)
-                               port = new Pgsm_bs(PORT_TYPE_GSM_BS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-                       else
+                       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);
+                       } else
 #endif
 #ifdef WITH_GSM_MS
-                       if (mISDNport->gsm_ms)
-                               port = new Pgsm_ms(PORT_TYPE_GSM_MS_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode);
-                       else
+                       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);
+                       } else
 #endif
-#ifdef WITH_SIP
-                       if (mISDNport->ifport->interface->sip)
-                               port = new Psip(PORT_TYPE_SIP_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, mISDNport->ifport->interface);
-                       else
+#ifdef WITH_GSM_MS
+                       if (interface->sip) {
+                               SPRINT(portname, "%s-%d-out", interface->name, 0);
+                               port = new Psip(PORT_TYPE_SIP_OUT, portname, &port_settings, interface);
+                       } else
 #endif
-                       if (mISDNport->ifport->remote) {
-                               admin = admin_first;
-                               while(admin) {
-                                       if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
-                                               break;
-                                       admin = admin->next;
-                               }
-                               if (!admin) {
-                                       trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
-                                       add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+                       {
+                               /* 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();
-                                       continue;
+                                       goto check_anycall_extern;
                                }
-                               port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
-                       } else
-                               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);
+                               /* 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
+                               if (mISDNport->ifport->remote) {
+                                       admin = admin_first;
+                                       while(admin) {
+                                               if (admin->remote_name[0] && !strcmp(admin->remote_name, mISDNport->ifport->remote_app))
+                                                       break;
+                                               admin = admin->next;
+                                       }
+                                       if (!admin) {
+                                               trace_header("INTERFACE (remote not connected)", DIRECTION_NONE);
+                                               add_trace("application", NULL, "%s", mISDNport->ifport->remote_app);
+                                               end_trace();
+                                               continue;
+                                       }
+                                       port = new Premote(PORT_TYPE_REMOTE_OUT, mISDNport, portname, &port_settings, channel, mISDNport->ifport->channel_force, mode, admin->sock);
+                               } else
+                                       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;
+                       earlyb = (interface->is_earlyb == IS_YES);
                        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])
@@ -1262,7 +1338,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                        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, 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;
@@ -1274,6 +1350,7 @@ void EndpointAppPBX::out_setup(int cfnr)
                        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);
@@ -1506,7 +1583,6 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
        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);
        
@@ -1515,6 +1591,7 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
        memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
        memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
        memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
+       memcpy(&e_rtpinfo, &param->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));
@@ -1522,16 +1599,9 @@ void EndpointAppPBX::port_setup(struct port_list *portlist, int message_type, un
 
 //     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);
        }
 
        /* process extension */
@@ -2007,7 +2077,6 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
        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);
@@ -2035,16 +2104,8 @@ void EndpointAppPBX::port_connect(struct port_list *portlist, int message_type,
        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])
@@ -3196,6 +3257,7 @@ void EndpointAppPBX::join_setup(struct port_list *portlist, int message_type, un
        memcpy(&e_dialinginfo, &param->setup.dialinginfo, sizeof(e_dialinginfo));
        memcpy(&e_redirinfo, &param->setup.redirinfo, sizeof(e_redirinfo));
        memcpy(&e_capainfo, &param->setup.capainfo, sizeof(e_capainfo));
+       memcpy(&e_rtpinfo, &param->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) {
index 552e7ca..a37fc44 100644 (file)
--- a/apppbx.h
+++ b/apppbx.h
@@ -73,8 +73,9 @@ class EndpointAppPBX : public EndpointApp
        struct caller_info      e_callerinfo;           /* information about the caller */
        struct dialing_info     e_dialinginfo;          /* information about dialing */
        struct connect_info     e_connectinfo;          /* information about connected line */
-       struct redir_info       e_redirinfo;            /* info on redirection (to the calling user) */
-       struct capa_info        e_capainfo;             /* info on l3,l2 capacity */
+       struct redir_info       e_redirinfo;            /* info about redirection (to the calling user) */
+       struct capa_info        e_capainfo;             /* info about l3,l2 capacity */
+       struct rtp_info         e_rtpinfo;              /* info about rtp port forwarding and payload type */
        time_t                  e_start, e_stop;        /* time */
        int                     e_origin;               /* origin of call 0=incoming 1=outgoing */
        struct route_ruleset    *e_ruleset;             /* current ruleset pointer (NULL=no ruleset) */
@@ -234,6 +235,7 @@ class EndpointAppPBX : public EndpointApp
        void set_tone(struct port_list *portlist, const char *tone);
        void out_setup(int cfnr);
        struct mISDNport *hunt_port(char *ifname, int *channel);
+       struct interface *hunt_interface(char *ifname);
        char *apply_callerid_display(const char *id, int itype, int ntype, int present, int screen, const char *extension, const char *name);
        void auth(int job, int bit_num);
 
index f89c50c..449c7ec 100644 (file)
 
 
 # A special case for GSM Network interface.
-# Don't remove/change the settings, they will cause undefined behaviour
-# of LCR. It uses the loopback interface as defined in options.conf.
 # You may add 'extension' and 'msn' keywords to turn all your subscribers
 # in you GSM network to internal 'extensions'.
 # The MSN numbers will equal the subscriber number.
 #[GSM]
 #gsm-bs
-#nt
-#layer1hold no
-#layer2hold no
 #tones yes
 #earlyb no
-#channel-in free
-#channel-out any
-#nodtmf
 
 
 # A special case for GSM Mobile Station interface.
 # give "gsm-ms <name of mobile instance>".
-# Don't remove/change the settings, they will cause undefined behaviour
-# of LCR. It uses the loopback interface as defined in options.conf.
 # You may add 'extern' to make this interface the external line by default.
 #[GSM]
 #gsm-ms 1
-#layer1hold no
-#layer2hold no
 #tones no
 #earlyb yes
-#channel-in free
-#channel-out any
-#nodtmf
 ##extern
 
 
 #tones yes
 
 
+# Use Sofia-SIP as SIP point-to-point interface
+#[sip]
+#sip <local ip> <remote ip>
+#sip 10.0.0.12 10.0.0.34
+#earlyb no
+#tones no
+
+
 # Hint: Enter "lcr interface" for quick help on interface options.
 
 
index 3c222d2..6e5ba13 100644 (file)
 #define DEBUG_GSM      0x0120
 #define DEBUG_SS5      0x0140
 #define DEBUG_VBOX     0x0180
+#define DEBUG_SIP      0x10000
 #define DEBUG_EPOINT   0x0200
 #define DEBUG_JOIN     0x0400
 #define DEBUG_CRYPT     0x1000
 #define DEBUG_ROUTE     0x2000
 #define DEBUG_IDLETIME  0x4000
-#define DEBUG_LOG       0x7fff
+#define DEBUG_LOG       0x7fffff
 
 #debug 0x0000
 
index 2a336d8..f0834af 100644 (file)
--- a/dss1.cpp
+++ b/dss1.cpp
@@ -1972,8 +1972,8 @@ void Pdss1::message_setup(unsigned int epoint_id, int message_id, union paramete
        memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
        /* screen outgoing caller id */
-       do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
-       do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
+       do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface->name);
+       do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface->name);
 
        /* only display at connect state: this case happens if endpoint is in connected mode */
        if (p_state==PORT_STATE_CONNECT) {
@@ -2487,7 +2487,7 @@ void Pdss1::message_connect(unsigned int epoint_id, int message_id, union parame
        /* copy connected information */
        memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
        /* screen outgoing caller id */
-       do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
+       do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface->name);
 
        /* only display at connect state */
        if (p_state == PORT_STATE_CONNECT)
diff --git a/gsm.cpp b/gsm.cpp
index e6806c3..3f778b4 100644 (file)
--- a/gsm.cpp
+++ b/gsm.cpp
@@ -34,6 +34,7 @@ static const struct _value_string {
        int msg_type;
        const char *name;
 } mncc_names[] = {
+       { 0,                    "New call ref" },
        { MNCC_SETUP_REQ,       "MNCC_SETUP_REQ" },
        { MNCC_SETUP_IND,       "MNCC_SETUP_IND" },
        { MNCC_SETUP_RSP,       "MNCC_SETUP_RSP" },
@@ -127,26 +128,38 @@ static int delete_event(struct lcr_work *work, void *instance, int index);
 /*
  * constructor
  */
-Pgsm::Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
+Pgsm::Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings)
 {
-       p_callerinfo.itype = (mISDNport->ifport->interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
-       memset(&p_m_g_delete, 0, sizeof(p_m_g_delete));
-       add_work(&p_m_g_delete, delete_event, this, 0);
-       p_m_g_lcr_gsm = NULL;
-       p_m_g_callref = 0;
-       p_m_g_mode = 0;
-       p_m_g_gsm_b_sock = -1;
-       p_m_g_gsm_b_index = -1;
-       p_m_g_gsm_b_active = 0;
-       p_m_g_notify_pending = NULL;
-       p_m_g_decoder = gsm_audio_create();
-       p_m_g_encoder = gsm_audio_create();
-       if (!p_m_g_encoder || !p_m_g_decoder) {
+       p_g_tones = 0;
+       if (interface->is_tones == IS_YES)
+               p_g_tones = 1;
+       p_g_earlyb = 0;
+       if (interface->is_earlyb == IS_YES)
+               p_g_earlyb = 1;
+       p_g_rtp_bridge = 0;
+       if (interface->rtp_bridge)
+               p_g_rtp_bridge = 1;
+       SCPY(p_g_interface_name, interface->name); 
+       p_callerinfo.itype = (interface->extension)?INFO_ITYPE_ISDN_EXTENSION:INFO_ITYPE_ISDN;
+       memset(&p_g_delete, 0, sizeof(p_g_delete));
+       add_work(&p_g_delete, delete_event, this, 0);
+       p_g_lcr_gsm = NULL;
+       p_g_callref = 0;
+       p_g_mode = 0;
+       p_g_gsm_b_sock = -1;
+       p_g_gsm_b_index = -1;
+       p_g_gsm_b_active = 0;
+       p_g_notify_pending = NULL;
+       p_g_setup_pending = NULL;
+       p_g_connect_pending = NULL;
+       p_g_decoder = gsm_audio_create();
+       p_g_encoder = gsm_audio_create();
+       if (!p_g_encoder || !p_g_decoder) {
                PERROR("Failed to create GSM audio codec instance\n");
-               trigger_work(&p_m_g_delete);
+               trigger_work(&p_g_delete);
        }
-       p_m_g_rxpos = 0;
-       p_m_g_tch_connected = 0;
+       p_g_rxpos = 0;
+       p_g_tch_connected = 0;
 
        PDEBUG(DEBUG_GSM, "Created new GSMPort(%s).\n", portname);
 }
@@ -158,131 +171,74 @@ Pgsm::~Pgsm()
 {
        PDEBUG(DEBUG_GSM, "Destroyed GSM process(%s).\n", p_name);
 
-       del_work(&p_m_g_delete);
+       del_work(&p_g_delete);
 
        /* remove queued message */
-       if (p_m_g_notify_pending)
-               message_free(p_m_g_notify_pending);
-
-       /* close audio transfer socket */
-       if (p_m_g_gsm_b_sock > -1)
-               bchannel_close();
+       if (p_g_notify_pending)
+               message_free(p_g_notify_pending);
+       if (p_g_setup_pending)
+               message_free(p_g_setup_pending);
+       if (p_g_connect_pending)
+               message_free(p_g_connect_pending);
 
        /* close codec */
-       if (p_m_g_encoder)
-               gsm_audio_destroy(p_m_g_encoder);
-       if (p_m_g_decoder)
-               gsm_audio_destroy(p_m_g_decoder);
+       if (p_g_encoder)
+               gsm_audio_destroy(p_g_encoder);
+       if (p_g_decoder)
+               gsm_audio_destroy(p_g_decoder);
 }
 
 
-/* close bsc side bchannel */
-void Pgsm::bchannel_close(void)
-{
-       if (p_m_g_gsm_b_sock > -1) {
-               unregister_fd(&p_m_g_gsm_b_fd);
-               close(p_m_g_gsm_b_sock);
-       }
-       p_m_g_gsm_b_sock = -1;
-       p_m_g_gsm_b_index = -1;
-       p_m_g_gsm_b_active = 0;
-}
-
-static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index);
-
-/* open external side bchannel */
-int Pgsm::bchannel_open(int index)
+/* receive encoded frame from gsm */
+void Pgsm::frame_receive(void *arg)
 {
-       int ret;
-       struct sockaddr_mISDN addr;
-       struct mISDNhead act;
+       struct gsm_data_frame *frame = (struct gsm_data_frame *)arg;
+       signed short samples[160];
+       unsigned char data[160];
+       int i;
 
-       if (p_m_g_gsm_b_sock > -1) {
-               PERROR("Socket already created for index %d\n", index);
-               return(-EIO);
-       }
+       if (!p_g_decoder)
+               return;
 
-       /* open socket */
-       ret = p_m_g_gsm_b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
-       if (ret < 0) {
-               PERROR("Failed to open bchannel-socket for index %d\n", index);
-               bchannel_close();
-               return(ret);
-       }
-       memset(&p_m_g_gsm_b_fd, 0, sizeof(p_m_g_gsm_b_fd));
-       p_m_g_gsm_b_fd.fd = p_m_g_gsm_b_sock;
-       register_fd(&p_m_g_gsm_b_fd, LCR_FD_READ, b_handler, this, 0);
-
-
-       /* bind socket to bchannel */
-       addr.family = AF_ISDN;
-       addr.dev = mISDNloop.port;
-       addr.channel = index+1+(index>15);
-       ret = bind(p_m_g_gsm_b_sock, (struct sockaddr *)&addr, sizeof(addr));
-       if (ret < 0) {
-               PERROR("Failed to bind bchannel-socket for index %d\n", index);
-               bchannel_close();
-               return(ret);
-       }
-       /* activate bchannel */
-       PDEBUG(DEBUG_GSM, "Activating GSM side channel index %i.\n", index);
-       act.prim = PH_ACTIVATE_REQ; 
-       act.id = 0;
-       ret = sendto(p_m_g_gsm_b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
-       if (ret < 0) {
-               PERROR("Failed to activate index %d\n", index);
-               bchannel_close();
-               return(ret);
+       if ((frame->data[0]>>4) != 0xd)
+               PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
+       
+       /* decode */
+       gsm_audio_decode(p_g_decoder, frame->data, samples);
+       for (i = 0; i < 160; i++) {
+               data[i] = audio_s16_to_law[samples[i] & 0xffff];
        }
 
-       p_m_g_gsm_b_index = index;
-
-       return(0);
+       /* send to remote*/
+       bridge_tx(data, 160);
 }
 
-/* receive from bchannel */
-void Pgsm::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
+/* send traffic to gsm */
+int Pgsm::bridge_rx(unsigned char *data, int len)
 {
        unsigned char frame[33];
 
        /* encoder init failed */
-       if (!p_m_g_encoder)
-               return;
+       if (!p_g_encoder)
+               return -EINVAL;
 
        /* (currently) not connected, so don't flood tch! */
-       if (!p_m_g_tch_connected)
-               return;
+       if (!p_g_tch_connected)
+               return -EINVAL;
 
        /* write to rx buffer */
        while(len--) {
-               p_m_g_rxdata[p_m_g_rxpos++] = audio_law_to_s32[*data++];
-               if (p_m_g_rxpos == 160) {
-                       p_m_g_rxpos = 0;
+               p_g_rxdata[p_g_rxpos++] = audio_law_to_s32[*data++];
+               if (p_g_rxpos == 160) {
+                       p_g_rxpos = 0;
 
                        /* encode data */
-                       gsm_audio_encode(p_m_g_encoder, p_m_g_rxdata, frame);
+                       gsm_audio_encode(p_g_encoder, p_g_rxdata, frame);
                        frame_send(frame);
                }
        }
-}
-
-/* transmit to bchannel */
-void Pgsm::bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len)
-{
-       unsigned char buf[MISDN_HEADER_LEN+len];
-       struct mISDNhead *hh = (struct mISDNhead *)buf;
-       int ret;
-
-       if (!p_m_g_gsm_b_active)
-               return;
 
-       /* make and send frame */
-       hh->prim = PH_DATA_REQ;
-       hh->id = 0;
-       memcpy(buf+MISDN_HEADER_LEN, data, len);
-       ret = sendto(p_m_g_gsm_b_sock, buf, MISDN_HEADER_LEN+len, 0, NULL, 0);
-       if (ret <= 0)
-               PERROR("Failed to send to socket index %d\n", p_m_g_gsm_b_index);
+       return 0;
 }
 
 void Pgsm::frame_send(void *_frame)
@@ -291,45 +247,29 @@ void Pgsm::frame_send(void *_frame)
        struct gsm_data_frame *frame = (struct gsm_data_frame *)buffer;
        
        frame->msg_type = GSM_TCHF_FRAME;
-       frame->callref = p_m_g_callref;
+       frame->callref = p_g_callref;
        memcpy(frame->data, _frame, 33);
 
-       if (p_m_g_lcr_gsm) {
-               mncc_send(p_m_g_lcr_gsm, frame->msg_type, frame);
-       }
-}
-
-
-void Pgsm::frame_receive(void *arg)
-{
-       struct gsm_data_frame *frame = (struct gsm_data_frame *)arg;
-       signed short samples[160];
-       unsigned char data[160];
-       int i;
-
-       if (!p_m_g_decoder)
-               return;
-
-       if ((frame->data[0]>>4) != 0xd)
-               PERROR("received GSM frame with wrong magig 0x%x\n", frame->data[0]>>4);
-       
-       /* decode */
-       gsm_audio_decode(p_m_g_decoder, frame->data, samples);
-       for (i = 0; i < 160; i++) {
-               data[i] = audio_s16_to_law[samples[i] & 0xffff];
+       if (p_g_lcr_gsm) {
+               mncc_send(p_g_lcr_gsm, frame->msg_type, frame);
        }
-
-       /* send */
-       bchannel_send(PH_DATA_REQ, 0, data, 160);
 }
 
-
 /*
  * create trace
  */
-void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction)
+void gsm_trace_header(const char *interface_name, class Pgsm *port, unsigned int msg_type, int direction)
 {
        char msgtext[64];
+       struct interface *interface = interface_first;
+
+       while (interface) {
+               if (!strcmp(interface->name, interface_name))
+                       break;
+               interface = interface->next;
+       }
+       if (!interface)
+               return;
 
        /* select message and primitive text */
        SCPY(msgtext, mncc_name(msg_type));
@@ -350,8 +290,8 @@ void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned
                SCAT(msgtext, " ----");
 
        /* init trace with given values */
-       start_trace(mISDNport?mISDNport->portnum:-1,
-                   mISDNport?(mISDNport->ifport?mISDNport->ifport->interface:NULL):NULL,
+       start_trace(0,
+                   interface,
                    port?numberrize_callerinfo(port->p_callerinfo.id, port->p_callerinfo.ntype, options.national, options.international):NULL,
                    port?port->p_dialinginfo.id:NULL,
                    direction,
@@ -360,18 +300,12 @@ void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned
                    msgtext);
 }
 
-/* select free bchannel from loopback interface */
-int Pgsm::hunt_bchannel(void)
-{
-       return loop_hunt_bchannel(this, p_m_mISDNport);
-}
-
 /* PROCEEDING INDICATION */
 void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
 {
        struct gsm_mncc *mode;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        if (mncc->fields & MNCC_F_CAUSE) {
                add_trace("cause", "coding", "%d", mncc->cause.coding);
                add_trace("cause", "location", "%", mncc->cause.location);
@@ -380,13 +314,13 @@ void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm
        end_trace();
 
        /* modify lchan to GSM codec V1 */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
-       mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
+       mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
        mode->lchan_mode = 0x01; /* GSM V1 */
        mode->lchan_type = 0x02;
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
+       send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
 
 }
 
@@ -396,7 +330,7 @@ void Pgsm::call_proc_ind(unsigned int msg_type, unsigned int callref, struct gsm
        struct lcr_msg *message;
        struct gsm_mncc *frame;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        end_trace();
 
        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
@@ -404,12 +338,12 @@ void Pgsm::call_proc_ind(unsigned int msg_type, unsigned int callref, struct gsm
 
        new_state(PORT_STATE_OUT_PROCEEDING);
 
-       if (p_m_mISDNport->earlyb && !p_m_g_tch_connected) { /* only if ... */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
-               p_m_g_tch_connected = 1;
+               frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+               p_g_tch_connected = 1;
        }
 }
 
@@ -419,7 +353,7 @@ void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mnc
        struct lcr_msg *message;
        struct gsm_mncc *frame;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        end_trace();
 
        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
@@ -427,12 +361,12 @@ void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mnc
 
        new_state(PORT_STATE_OUT_ALERTING);
 
-       if (p_m_mISDNport->earlyb && !p_m_g_tch_connected) { /* only if ... */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
-               p_m_g_tch_connected = 1;
+               frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+               p_g_tch_connected = 1;
        }
 }
 
@@ -447,10 +381,9 @@ void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mnc
        p_connectinfo.present = INFO_PRESENT_ALLOWED;
        p_connectinfo.screen = INFO_SCREEN_NETWORK;
        p_connectinfo.ntype = INFO_NTYPE_UNKNOWN;
-       p_connectinfo.isdn_port = p_m_portnum;
-       SCPY(p_connectinfo.interface, p_m_mISDNport->ifport->interface->name);
+       SCPY(p_connectinfo.interface, p_g_interface_name);
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        if (p_connectinfo.id[0])
                add_trace("connect", "number", "%s", p_connectinfo.id);
        else if (mncc->imsi[0])
@@ -460,24 +393,34 @@ void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mnc
        end_trace();
 
        /* send resp */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
-       resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
+       resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_g_callref);
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
-
-       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
-       memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
-       message_put(message);
+       send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
 
        new_state(PORT_STATE_CONNECT);
 
-       if (!p_m_g_tch_connected) { /* only if ... */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (!p_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
-               p_m_g_tch_connected = 1;
+               frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+               p_g_tch_connected = 1;
        }
+
+       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
+       memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
+       message->param.connectinfo.rtpinfo.payload_type = 3; /* FIXME: receive payload type from peer */
+
+       if (p_g_rtp_bridge) {
+               struct gsm_mncc_rtp *rtp;
+
+               PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding connect msg\n");
+               p_g_connect_pending = message;
+               rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
+       } else
+               message_put(message);
 }
 
 /* CONNECT ACK INDICATION */
@@ -485,17 +428,17 @@ void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct g
 {
        struct gsm_mncc *frame;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        end_trace();
 
        new_state(PORT_STATE_CONNECT);
 
-       if (!p_m_g_tch_connected) { /* only if ... */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (!p_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
-               p_m_g_tch_connected = 1;
+               frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+               p_g_tch_connected = 1;
        }
 }
 
@@ -506,7 +449,7 @@ void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc
        int cause = 16, location = 0;
        struct gsm_mncc *resp;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        if (mncc->fields & MNCC_F_CAUSE) {
                location = mncc->cause.location;
                cause = mncc->cause.value;
@@ -517,8 +460,8 @@ void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc
        end_trace();
 
        /* send release */
-       resp = create_mncc(MNCC_REL_REQ, p_m_g_callref);
-       gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
+       resp = create_mncc(MNCC_REL_REQ, p_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
 #if 0
        resp->fields |= MNCC_F_CAUSE;
        resp->cause.coding = 3;
@@ -529,7 +472,7 @@ void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc
        add_trace("cause", "value", "%d", resp->cause.value);
 #endif
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
+       send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
 
        /* sending release to endpoint */
        while(p_epointlist) {
@@ -541,7 +484,7 @@ void Pgsm::disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc
                free_epointlist(p_epointlist);
        }
        new_state(PORT_STATE_RELEASE);
-       trigger_work(&p_m_g_delete);
+       trigger_work(&p_g_delete);
 }
 
 /* CC_RELEASE INDICATION */
@@ -550,7 +493,7 @@ void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc
        int location = 0, cause = 16;
        struct lcr_msg *message;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        if (mncc->fields & MNCC_F_CAUSE) {
                location = mncc->cause.location;
                cause = mncc->cause.value;
@@ -570,7 +513,7 @@ void Pgsm::rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc
                free_epointlist(p_epointlist);
        }
        new_state(PORT_STATE_RELEASE);
-       trigger_work(&p_m_g_delete);
+       trigger_work(&p_g_delete);
 }
 
 /* NOTIFY INDICATION */
@@ -578,7 +521,7 @@ void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mn
 {
        struct lcr_msg *message;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        add_trace("notify", NULL, "%d", mncc->notify);
        end_trace();
 
@@ -598,31 +541,93 @@ void Pgsm::message_notify(unsigned int epoint_id, int message_id, union paramete
                notify = param->notifyinfo.notify & 0x7f;
                if (p_state!=PORT_STATE_CONNECT /*&& p_state!=PORT_STATE_IN_PROCEEDING*/ && p_state!=PORT_STATE_IN_ALERTING) {
                        /* queue notification */
-                       if (p_m_g_notify_pending)
-                               message_free(p_m_g_notify_pending);
-                       p_m_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
-                       memcpy(&p_m_g_notify_pending->param, param, sizeof(union parameter));
+                       if (p_g_notify_pending)
+                               message_free(p_g_notify_pending);
+                       p_g_notify_pending = message_create(ACTIVE_EPOINT(p_epointlist), p_serial, EPOINT_TO_PORT, message_id);
+                       memcpy(&p_g_notify_pending->param, param, sizeof(union parameter));
                } else {
                        /* sending notification */
-                       gsm_trace_header(p_m_mISDNport, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
+                       gsm_trace_header(p_g_interface_name, this, MNCC_NOTIFY_REQ, DIRECTION_OUT);
                        add_trace("notify", NULL, "%d", notify);
                        end_trace();
-                       mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
+                       mncc = create_mncc(MNCC_NOTIFY_REQ, p_g_callref);
                        mncc->notify = notify;
-                       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+                       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
                }
        }
 }
 
+/* RTP create indication */
+void Pgsm::rtp_create_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
+
+       /* send queued setup, as we received remote RTP info */
+       if (p_g_setup_pending) {
+               struct lcr_msg *message;
+
+               message = p_g_setup_pending;
+               PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding setup\n", rtp->ip, rtp->port);
+               message->param.setup.rtpinfo.ip = rtp->ip;
+               message->param.setup.rtpinfo.port = rtp->port;
+               message_put(message);
+               p_g_setup_pending = NULL;
+       }
+       if (p_g_connect_pending) {
+               struct gsm_mncc_rtp *nrtp;
+
+               PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) connecting RTP... \n", rtp->ip, rtp->port);
+               nrtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
+               nrtp->ip = p_g_rtp_ip_remote;
+               nrtp->port = p_g_rtp_port_remote;
+               send_and_free_mncc(p_g_lcr_gsm, nrtp->msg_type, nrtp);
+       }
+}
+
+/* RTP connect indication */
+void Pgsm::rtp_connect_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
+{
+       struct lcr_msg *message;
+       struct gsm_mncc_rtp *rtp = (struct gsm_mncc_rtp *) mncc;
+
+       if (p_g_connect_pending) {
+               message = p_g_connect_pending;
+               PDEBUG(DEBUG_GSM, "Got RTP peer info (%08x,%d) forwarding connect\n", rtp->ip, rtp->port);
+               message->param.connectinfo.rtpinfo.ip = rtp->ip;
+               message->param.connectinfo.rtpinfo.port = rtp->port;
+               message_put(message);
+               p_g_connect_pending = NULL;
+       }
+}
+
+/* MESSAGE_PROGRESS */
+void Pgsm::message_progress(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       if (param->progressinfo.progress == 8) {
+               PDEBUG(DEBUG_GSM, "Remote provides tones for us\n");
+               p_g_tones = 1;
+       }
+
+       if (param->progressinfo.rtpinfo.port) {
+               struct gsm_mncc_rtp *rtp;
+
+               PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->progressinfo.rtpinfo.ip, param->progressinfo.rtpinfo.port);
+               rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
+               rtp->ip = param->progressinfo.rtpinfo.ip;
+               rtp->port = param->progressinfo.rtpinfo.port;
+               send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
+       }
+}
+
 /* MESSAGE_ALERTING */
 void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parameter *param)
 {
        struct gsm_mncc *mncc;
 
        /* send alert */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_ALERT_REQ, DIRECTION_OUT);
-       mncc = create_mncc(MNCC_ALERT_REQ, p_m_g_callref);
-       if (p_m_mISDNport->tones) {
+       gsm_trace_header(p_g_interface_name, this, MNCC_ALERT_REQ, DIRECTION_OUT);
+       mncc = create_mncc(MNCC_ALERT_REQ, p_g_callref);
+       if (p_g_tones) {
                mncc->fields |= MNCC_F_PROGRESS;
                mncc->progress.coding = 3; /* GSM */
                mncc->progress.location = 1;
@@ -632,16 +637,16 @@ void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parame
                add_trace("progress", "descr", "%d", mncc->progress.descr);
        }
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_IN_ALERTING);
 
-       if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (p_g_tones && !p_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
-               p_m_g_tch_connected = 1;
+               mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
+               p_g_tch_connected = 1;
        }
 }
 
@@ -653,11 +658,11 @@ void Pgsm::message_connect(unsigned int epoint_id, int message_id, union paramet
        /* copy connected information */
        memcpy(&p_connectinfo, &param->connectinfo, sizeof(p_connectinfo));
        /* screen outgoing caller id */
-       do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_m_mISDNport->ifport->interface);
+       do_screen(1, p_connectinfo.id, sizeof(p_connectinfo.id), &p_connectinfo.ntype, &p_connectinfo.present, p_g_interface_name);
 
        /* send connect */
-       mncc = create_mncc(MNCC_SETUP_RSP, p_m_g_callref);
-       gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_RSP, DIRECTION_OUT);
+       mncc = create_mncc(MNCC_SETUP_RSP, p_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_RSP, DIRECTION_OUT);
        /* caller information */
        mncc->fields |= MNCC_F_CONNECTED;
        mncc->connected.plan = 1;
@@ -706,9 +711,20 @@ void Pgsm::message_connect(unsigned int epoint_id, int message_id, union paramet
                add_trace("connected", "number", "%s", mncc->connected.number);
        }
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_CONNECT_WAITING);
+
+       if (param->connectinfo.rtpinfo.port) {
+               struct gsm_mncc_rtp *rtp;
+
+               PDEBUG(DEBUG_GSM, "CONNECT with RTP peer info, sent to BSC (%08x,%d)\n", param->connectinfo.rtpinfo.ip, param->connectinfo.rtpinfo.port);
+               rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CONNECT, p_g_callref);
+               rtp->ip = param->connectinfo.rtpinfo.ip;
+               rtp->port = param->connectinfo.rtpinfo.port;
+               send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
+       }
+
 }
 
 /* MESSAGE_DISCONNECT */
@@ -717,9 +733,9 @@ void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union para
        struct gsm_mncc *mncc;
 
        /* send disconnect */
-       mncc = create_mncc(MNCC_DISC_REQ, p_m_g_callref);
-       gsm_trace_header(p_m_mISDNport, this, MNCC_DISC_REQ, DIRECTION_OUT);
-       if (p_m_mISDNport->tones) {
+       mncc = create_mncc(MNCC_DISC_REQ, p_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_DISC_REQ, DIRECTION_OUT);
+       if (p_g_tones) {
                mncc->fields |= MNCC_F_PROGRESS;
                mncc->progress.coding = 3; /* GSM */
                mncc->progress.location = 1;
@@ -736,16 +752,16 @@ void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union para
        add_trace("cause", "location", "%d", mncc->cause.location);
        add_trace("cause", "value", "%d", mncc->cause.value);
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_OUT_DISCONNECT);
 
-       if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (p_g_tones && !p_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
-               p_m_g_tch_connected = 1;
+               mncc = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
+               p_g_tch_connected = 1;
        }
 }
 
@@ -756,8 +772,8 @@ void Pgsm::message_release(unsigned int epoint_id, int message_id, union paramet
        struct gsm_mncc *mncc;
 
        /* send release */
-       mncc = create_mncc(MNCC_REL_REQ, p_m_g_callref);
-       gsm_trace_header(p_m_mISDNport, this, MNCC_REL_REQ, DIRECTION_OUT);
+       mncc = create_mncc(MNCC_REL_REQ, p_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_REL_REQ, DIRECTION_OUT);
        mncc->fields |= MNCC_F_CAUSE;
        mncc->cause.coding = 3;
        mncc->cause.location = param->disconnectinfo.location;
@@ -766,10 +782,10 @@ void Pgsm::message_release(unsigned int epoint_id, int message_id, union paramet
        add_trace("cause", "location", "%d", mncc->cause.location);
        add_trace("cause", "value", "%d", mncc->cause.value);
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_RELEASE);
-       trigger_work(&p_m_g_delete);
+       trigger_work(&p_g_delete);
        return;
 }
 
@@ -778,11 +794,14 @@ void Pgsm::message_release(unsigned int epoint_id, int message_id, union paramet
  */
 int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
 {
-       if (PmISDN::message_epoint(epoint_id, message_id, param))
-               return(1);
+       int ret = 0;
+
+       if (Port::message_epoint(epoint_id, message_id, param))
+               return 1;
 
        switch(message_id) {
                case MESSAGE_NOTIFY: /* display and notifications */
+               ret = 1;
                message_notify(epoint_id, message_id, param);
                break;
 
@@ -791,34 +810,43 @@ int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter
 //             break;
 
                case MESSAGE_PROCEEDING: /* message not handles */
+               ret = 1;
+               break;
+
+               case MESSAGE_PROGRESS:
+               ret = 1;
+               message_progress(epoint_id, message_id, param);
                break;
 
                case MESSAGE_ALERTING: /* call of endpoint is ringing */
+               ret = 1;
                if (p_state!=PORT_STATE_IN_PROCEEDING)
                        break;
                message_alerting(epoint_id, message_id, param);
-               if (p_m_g_notify_pending) {
+               if (p_g_notify_pending) {
                        /* send pending notify message during connect */
-                       message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
-                       message_free(p_m_g_notify_pending);
-                       p_m_g_notify_pending = NULL;
+                       message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
+                       message_free(p_g_notify_pending);
+                       p_g_notify_pending = NULL;
                }
                break;
 
                case MESSAGE_CONNECT: /* call of endpoint is connected */
+               ret = 1;
                if (p_state!=PORT_STATE_IN_PROCEEDING
                 && p_state!=PORT_STATE_IN_ALERTING)
                        break;
                message_connect(epoint_id, message_id, param);
-               if (p_m_g_notify_pending) {
+               if (p_g_notify_pending) {
                        /* send pending notify message during connect */
-                       message_notify(ACTIVE_EPOINT(p_epointlist), p_m_g_notify_pending->type, &p_m_g_notify_pending->param);
-                       message_free(p_m_g_notify_pending);
-                       p_m_g_notify_pending = NULL;
+                       message_notify(ACTIVE_EPOINT(p_epointlist), p_g_notify_pending->type, &p_g_notify_pending->param);
+                       message_free(p_g_notify_pending);
+                       p_g_notify_pending = NULL;
                }
                break;
 
                case MESSAGE_DISCONNECT: /* call has been disconnected */
+               ret = 1;
                if (p_state!=PORT_STATE_IN_PROCEEDING
                 && p_state!=PORT_STATE_IN_ALERTING
                 && p_state!=PORT_STATE_OUT_SETUP
@@ -832,6 +860,7 @@ int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter
                break;
 
                case MESSAGE_RELEASE: /* release isdn port */
+               ret = 1;
                if (p_state==PORT_STATE_RELEASE)
                        break;
                message_release(epoint_id, message_id, param);
@@ -839,7 +868,7 @@ int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter
 
        }
 
-       return(0);
+       return ret;
 }
 
 /* deletes only if l3id is release, otherwhise it will be triggered then */
@@ -852,44 +881,6 @@ static int delete_event(struct lcr_work *work, void *instance, int index)
        return 0;
 }
 
-/*
- * handler of bchannel events
- */
-static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index)
-{
-       class Pgsm *gsmport = (class Pgsm *)instance;
-       int ret;
-       unsigned char buffer[2048+MISDN_HEADER_LEN];
-       struct mISDNhead *hh = (struct mISDNhead *)buffer;
-
-       /* handle message from bchannel */
-       if (gsmport->p_m_g_gsm_b_sock > -1) {
-               ret = recv(gsmport->p_m_g_gsm_b_sock, buffer, sizeof(buffer), 0);
-               if (ret >= (int)MISDN_HEADER_LEN) {
-                       switch(hh->prim) {
-                               /* we don't care about confirms, we use rx data to sync tx */
-                               case PH_DATA_CNF:
-                               break;
-                               /* we receive audio data, we respond to it AND we send tones */
-                               case PH_DATA_IND:
-                               gsmport->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
-                               break;
-                               case PH_ACTIVATE_IND:
-                               gsmport->p_m_g_gsm_b_active = 1;
-                               break;
-                               case PH_DEACTIVATE_IND:
-                               gsmport->p_m_g_gsm_b_active = 0;
-                               break;
-                       }
-               } else {
-                       if (ret < 0 && errno != EWOULDBLOCK)
-                               PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
-               }
-       }
-
-       return 0;
-}
-
 int gsm_exit(int rc)
 {
        return(rc);
@@ -985,13 +976,13 @@ static int mncc_fd_close(struct lcr_gsm *lcr_gsm, struct lcr_fd *lfd)
        while(port) {
                if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_GSM) {
                        pgsm = (class Pgsm *)port;
-                       if (pgsm->p_m_g_lcr_gsm == lcr_gsm) {
+                       if (pgsm->p_g_lcr_gsm == lcr_gsm) {
                                message = message_create(pgsm->p_serial, ACTIVE_EPOINT(pgsm->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
                                message->param.disconnectinfo.cause = 27; // temp. unavail.
                                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                                message_put(message);
                                pgsm->new_state(PORT_STATE_RELEASE);
-                               trigger_work(&pgsm->p_m_g_delete);
+                               trigger_work(&pgsm->p_g_delete);
                        }
                }
                port = port->next;
diff --git a/gsm.h b/gsm.h
index 3ecaf0d..254797e 100644 (file)
--- a/gsm.h
+++ b/gsm.h
@@ -15,6 +15,7 @@ enum {
 };
 
 struct lcr_gsm {
+       struct interface *interface;    /* interface this instance is associated to */
        struct lcr_gsm  *gsm_ms_next;   /* list of MS instances, in case of MS */
        char            name[16];       /* name of MS instance, in case of MS */
        int             type;           /* LCR_GSM_TYPE_*/
@@ -27,33 +28,38 @@ struct lcr_gsm {
 };
 
 /* GSM port class */
-class Pgsm : public PmISDN
+class Pgsm : public Port
 {
        public:
-       Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
+       Pgsm(int type, char *portname, struct port_settings *settings, struct interface *interface);
        ~Pgsm();
 
-       struct lcr_gsm *p_m_g_lcr_gsm; /* pointer to network/ms instance */
-       unsigned int p_m_g_callref; /* ref by OpenBSC/Osmocom-BB */
-       struct lcr_work p_m_g_delete; /* queue destruction of GSM port instance */
-       unsigned int p_m_g_mode; /* data/transparent mode */
-       int p_m_g_gsm_b_sock; /* gsm bchannel socket */
-       struct lcr_fd p_m_g_gsm_b_fd; /* event node */
-       int p_m_g_gsm_b_index; /* gsm bchannel socket index to use */
-       int p_m_g_gsm_b_active; /* gsm bchannel socket is activated */
-       struct lcr_msg *p_m_g_notify_pending;   /* queue for NOTIFY if not connected */
-       void *p_m_g_encoder, *p_m_g_decoder;    /* gsm handle */
-       signed short p_m_g_rxdata[160]; /* receive audio buffer */
-       int p_m_g_rxpos; /* position in audio buffer 0..159 */
-       int p_m_g_tch_connected; /* indicates if audio is connected */
+       char p_g_interface_name[64];
+       int p_g_tones; /* set, if tones are to be generated */
+       int p_g_earlyb; /* set, if patterns are available */
+       struct lcr_gsm *p_g_lcr_gsm; /* pointer to network/ms instance */
+       unsigned int p_g_callref; /* ref by OpenBSC/Osmocom-BB */
+       struct lcr_work p_g_delete; /* queue destruction of GSM port instance */
+       unsigned int p_g_mode; /* data/transparent mode */
+       int p_g_gsm_b_sock; /* gsm bchannel socket */
+       struct lcr_fd p_g_gsm_b_fd; /* event node */
+       int p_g_gsm_b_index; /* gsm bchannel socket index to use */
+       int p_g_gsm_b_active; /* gsm bchannel socket is activated */
+       struct lcr_msg *p_g_notify_pending;     /* queue for NOTIFY if not connected */
+       struct lcr_msg *p_g_setup_pending;      /* queue SETUP until RTP is created */
+       struct lcr_msg *p_g_connect_pending;    /* queue CONNECT until RTP is created and connected */
+       void *p_g_encoder, *p_g_decoder;        /* gsm handle */
+       signed short p_g_rxdata[160]; /* receive audio buffer */
+       int p_g_rxpos; /* position in audio buffer 0..159 */
+       int p_g_tch_connected; /* indicates if audio is connected */
 
-       void bchannel_close(void);
-       int bchannel_open(int index);
-       void bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len);
-       void bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len);
+       int p_g_rtp_bridge; /* if we use a bridge */
+       unsigned int p_g_rtp_ip_remote; /* stores ip */
+       unsigned short p_g_rtp_port_remote; /* stores port */
 
        void frame_send(void *_frame);
        void frame_receive(void *_frame);
+       int bridge_rx(unsigned char *data, int len);
 
        int hunt_bchannel(void);
        void call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *gsm);
@@ -64,7 +70,10 @@ class Pgsm : public PmISDN
        void disc_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
        void rel_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
        void notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
+       void rtp_create_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
+       void rtp_connect_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
        void message_notify(unsigned int epoint_id, int message_id, union parameter *param);
+       void message_progress(unsigned int epoint_id, int message_id, union parameter *param);
        void message_alerting(unsigned int epoint_id, int message_id, union parameter *param);
        void message_connect(unsigned int epoint_id, int message_id, union parameter *param);
        void message_disconnect(unsigned int epoint_id, int message_id, union parameter *param);
@@ -74,7 +83,7 @@ class Pgsm : public PmISDN
 
 struct gsm_mncc *create_mncc(int msg_type, unsigned int callref);
 int send_and_free_mncc(struct lcr_gsm *lcr_gsm, unsigned int msg_type, void *data);
-void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction);
+void gsm_trace_header(const char *interface_name, class Pgsm *port, unsigned int msg_type, int direction);
 int gsm_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_exit(int rc);
 int gsm_init(void);
index d281bc9..902065b 100644 (file)
@@ -45,11 +45,11 @@ void generate_dtmf(void)
 /*
  * constructor
  */
-Pgsm_bs::Pgsm_bs(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Pgsm(type, mISDNport, portname, settings, channel, exclusive, mode)
+Pgsm_bs::Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
 {
-       p_m_g_lcr_gsm = gsm_bs;
-       p_m_g_dtmf = NULL;
-       p_m_g_dtmf_index = 0;
+       p_g_lcr_gsm = gsm_bs;
+       p_g_dtmf = NULL;
+       p_g_dtmf_index = 0;
 
        PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname);
 }
@@ -65,74 +65,74 @@ Pgsm_bs::~Pgsm_bs()
 /* DTMF INDICATION */
 void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
 {
-//     struct lcr_msg *message;
+       struct lcr_msg *message;
        struct gsm_mncc *resp;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        add_trace("keypad", NULL, "%c", mncc->keypad);
        end_trace();
        SPRINT(p_dialinginfo.id, "%c", mncc->keypad);
        p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
 
        /* send resp */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
+       gsm_trace_header(p_g_interface_name, this, MNCC_START_DTMF_RSP, DIRECTION_OUT);
        add_trace("keypad", NULL, "%c", mncc->keypad);
        end_trace();
-       resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
+       resp = create_mncc(MNCC_START_DTMF_RSP, p_g_callref);
        resp->fields |= MNCC_F_KEYPAD;
        resp->keypad = mncc->keypad;
-       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
-
-#if 0
-       /* send dialing information */
-       message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION);
-       memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info));
-       message_put(message);
-#endif
+       send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
 
-       /* generate DTMF tones */
-       switch (mncc->keypad) {
-               case '1': p_m_g_dtmf = dtmf_samples[0]; break;
-               case '2': p_m_g_dtmf = dtmf_samples[1]; break;
-               case '3': p_m_g_dtmf = dtmf_samples[2]; break;
-               case 'a':
-               case 'A': p_m_g_dtmf = dtmf_samples[3]; break;
-               case '4': p_m_g_dtmf = dtmf_samples[4]; break;
-               case '5': p_m_g_dtmf = dtmf_samples[5]; break;
-               case '6': p_m_g_dtmf = dtmf_samples[6]; break;
-               case 'b':
-               case 'B': p_m_g_dtmf = dtmf_samples[7]; break;
-               case '7': p_m_g_dtmf = dtmf_samples[8]; break;
-               case '8': p_m_g_dtmf = dtmf_samples[9]; break;
-               case '9': p_m_g_dtmf = dtmf_samples[10]; break;
-               case 'c':
-               case 'C': p_m_g_dtmf = dtmf_samples[11]; break;
-               case '*': p_m_g_dtmf = dtmf_samples[12]; break;
-               case '0': p_m_g_dtmf = dtmf_samples[13]; break;
-               case '#': p_m_g_dtmf = dtmf_samples[14]; break;
-               case 'd':
-               case 'D': p_m_g_dtmf = dtmf_samples[15]; break;
+       if (p_g_rtp_bridge) {
+               /* send dtmf information, because we bridge RTP directly */
+               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
+               message->param.dtmf = mncc->keypad;
+               message_put(message);
+       } else {
+               /* generate DTMF tones, since we do audio forwarding inside LCR */
+               switch (mncc->keypad) {
+                       case '1': p_g_dtmf = dtmf_samples[0]; break;
+                       case '2': p_g_dtmf = dtmf_samples[1]; break;
+                       case '3': p_g_dtmf = dtmf_samples[2]; break;
+                       case 'a':
+                       case 'A': p_g_dtmf = dtmf_samples[3]; break;
+                       case '4': p_g_dtmf = dtmf_samples[4]; break;
+                       case '5': p_g_dtmf = dtmf_samples[5]; break;
+                       case '6': p_g_dtmf = dtmf_samples[6]; break;
+                       case 'b':
+                       case 'B': p_g_dtmf = dtmf_samples[7]; break;
+                       case '7': p_g_dtmf = dtmf_samples[8]; break;
+                       case '8': p_g_dtmf = dtmf_samples[9]; break;
+                       case '9': p_g_dtmf = dtmf_samples[10]; break;
+                       case 'c':
+                       case 'C': p_g_dtmf = dtmf_samples[11]; break;
+                       case '*': p_g_dtmf = dtmf_samples[12]; break;
+                       case '0': p_g_dtmf = dtmf_samples[13]; break;
+                       case '#': p_g_dtmf = dtmf_samples[14]; break;
+                       case 'd':
+                       case 'D': p_g_dtmf = dtmf_samples[15]; break;
+               }
+               p_g_dtmf_index = 0;
        }
-       p_m_g_dtmf_index = 0;
 }
 void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
 {
        struct gsm_mncc *resp;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        add_trace("keypad", NULL, "%c", mncc->keypad);
        end_trace();
 
        /* send resp */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
+       gsm_trace_header(p_g_interface_name, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT);
        add_trace("keypad", NULL, "%c", mncc->keypad);
        end_trace();
-       resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
+       resp = create_mncc(MNCC_STOP_DTMF_RSP, p_g_callref);
        resp->keypad = mncc->keypad;
-       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
+       send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
        
        /* stop DTMF */
-       p_m_g_dtmf = NULL;
+       p_g_dtmf = NULL;
 }
 
 /* HOLD INDICATION */
@@ -141,7 +141,7 @@ void Pgsm_bs::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_m
        struct lcr_msg *message;
        struct gsm_mncc *resp, *frame;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        end_trace();
 
        /* notify the hold of call */
@@ -151,18 +151,18 @@ void Pgsm_bs::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_m
        message_put(message);
 
        /* acknowledge hold */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
+       gsm_trace_header(p_g_interface_name, this, MNCC_HOLD_CNF, DIRECTION_OUT);
        end_trace();
-       resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
-       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
+       resp = create_mncc(MNCC_HOLD_CNF, p_g_callref);
+       send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
 
        /* disable audio */
-       if (p_m_g_tch_connected) { /* it should be true */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_DROP, DIRECTION_OUT);
+       if (p_g_tch_connected) { /* it should be true */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_DROP, DIRECTION_OUT);
                end_trace();
-               frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
-               p_m_g_tch_connected = 0;
+               frame = create_mncc(MNCC_FRAME_DROP, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+               p_g_tch_connected = 0;
        }
 }
 
@@ -173,7 +173,7 @@ void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_m
        struct lcr_msg *message;
        struct gsm_mncc *resp, *frame;
 
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        end_trace();
 
        /* notify the retrieve of call */
@@ -183,18 +183,18 @@ void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_m
        message_put(message);
 
        /* acknowledge retr */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
+       gsm_trace_header(p_g_interface_name, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
        end_trace();
-       resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
-       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
+       resp = create_mncc(MNCC_RETRIEVE_CNF, p_g_callref);
+       send_and_free_mncc(p_g_lcr_gsm, resp->msg_type, resp);
 
        /* enable audio */
-       if (!p_m_g_tch_connected) { /* it should be true */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (!p_g_tch_connected) { /* it should be true */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
-               p_m_g_tch_connected = 1;
+               frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+               p_g_tch_connected = 1;
        }
 }
 
@@ -204,21 +204,19 @@ void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_m
 /* SETUP INDICATION */
 void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
 {
-       int ret;
        class Endpoint *epoint;
        struct lcr_msg *message;
-       int channel;
        struct gsm_mncc *mode, *proceeding, *frame;
 
        /* process given callref */
-       l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_IN);
        add_trace("callref", "new", "0x%x", callref);
-       if (p_m_g_callref) {
+       if (p_g_callref) {
                /* release in case the ID is already in use */
                add_trace("error", NULL, "callref already in use");
                end_trace();
                mncc = create_mncc(MNCC_REJ_REQ, callref);
-               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
+               gsm_trace_header(p_g_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
                mncc->fields |= MNCC_F_CAUSE;
                mncc->cause.coding = 3;
                mncc->cause.location = 1;
@@ -228,33 +226,14 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
                add_trace("cause", "value", "%d", mncc->cause.value);
                add_trace("reason", NULL, "callref already in use");
                end_trace();
-               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+               send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
+               trigger_work(&p_g_delete);
                return;
        }
-       p_m_g_callref = callref;
+       p_g_callref = callref;
        end_trace();
 
-       /* if blocked, release call with MT_RELEASE_COMPLETE */
-       if (p_m_mISDNport->ifport->block) {
-               mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
-               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
-               mncc->fields |= MNCC_F_CAUSE;
-               mncc->cause.coding = 3;
-               mncc->cause.location = 1;
-               mncc->cause.value = 27;
-               add_trace("cause", "coding", "%d", mncc->cause.coding);
-               add_trace("cause", "location", "%d", mncc->cause.location);
-               add_trace("cause", "value", "%d", mncc->cause.value);
-               add_trace("reason", NULL, "port is blocked");
-               end_trace();
-               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
-               return;
-       }
-
        /* caller info */
        if (mncc->clir.inv)
                p_callerinfo.present = INFO_PRESENT_RESTRICTED;
@@ -267,8 +246,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        SCPY(p_callerinfo.imsi, mncc->imsi);
        p_callerinfo.screen = INFO_SCREEN_NETWORK;
        p_callerinfo.ntype = INFO_NTYPE_UNKNOWN;
-       p_callerinfo.isdn_port = p_m_portnum;
-       SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+       SCPY(p_callerinfo.interface, p_g_interface_name);
 
        /* dialing information */
        SCAT(p_dialinginfo.id, mncc->called.number);
@@ -297,41 +275,12 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        p_capainfo.bearer_info1 = (options.law=='a')?3:2;
        p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT;
        p_capainfo.source_mode = B_MODE_TRANSPARENT;
-       p_m_g_mode = p_capainfo.source_mode;
+       p_g_mode = p_capainfo.source_mode;
 
        /* useruser */
 
-       /* hunt channel */
-       ret = channel = hunt_bchannel();
-       if (ret < 0)
-               goto no_channel;
-
-       /* open channel */
-       ret = seize_bchannel(channel, 1);
-       if (ret < 0) {
-               no_channel:
-               mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
-               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
-               mncc->fields |= MNCC_F_CAUSE;
-               mncc->cause.coding = 3;
-               mncc->cause.location = 1;
-               mncc->cause.value = 34;
-               add_trace("cause", "coding", "%d", mncc->cause.coding);
-               add_trace("cause", "location", "%d", mncc->cause.location);
-               add_trace("cause", "value", "%d", mncc->cause.value);
-               add_trace("reason", NULL, "no channel");
-               end_trace();
-               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
-               return;
-       }
-       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-       if (bchannel_open(p_m_b_index))
-               goto no_channel;
-
        /* what infos did we got ... */
-       gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, msg_type, DIRECTION_IN);
        if (p_callerinfo.id[0])
                add_trace("calling", "number", "%s", p_callerinfo.id);
        else
@@ -350,18 +299,18 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        epointlist_new(epoint->ep_serial);
 
        /* modify lchan to GSM codec V1 */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
-       mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
+       mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
        mode->lchan_mode = 0x01; /* GSM V1 */
        mode->lchan_type = 0x02;
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
+       send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
 
        /* send call proceeding */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
-       proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref);
-       if (p_m_mISDNport->tones) {
+       gsm_trace_header(p_g_interface_name, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
+       proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_g_callref);
+       if (p_g_tones) {
                proceeding->fields |= MNCC_F_PROGRESS;
                proceeding->progress.coding = 3; /* GSM */
                proceeding->progress.location = 1;
@@ -371,21 +320,20 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
                add_trace("progress", "descr", "%d", proceeding->progress.descr);
        }
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, proceeding->msg_type, proceeding);
+       send_and_free_mncc(p_g_lcr_gsm, proceeding->msg_type, proceeding);
 
        new_state(PORT_STATE_IN_PROCEEDING);
 
-       if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (p_g_tones && !p_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
-               p_m_g_tch_connected = 1;
+               frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+               p_g_tch_connected = 1;
        }
 
        /* send setup message to endpoit */
        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
-       message->param.setup.isdn_port = p_m_portnum;
        message->param.setup.port_type = p_type;
 //     message->param.setup.dtmf = 0;
        memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
@@ -394,7 +342,18 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info);
        message->param.setup.useruser.len = strlen(mncc->useruser.info);
        message->param.setup.useruser.protocol = mncc->useruser.proto;
-       message_put(message);
+       message->param.setup.rtpinfo.payload_type = 3; /* FIXME: receive payload type from peer */
+
+       if (p_g_rtp_bridge) {
+               struct gsm_mncc_rtp *rtp;
+
+               PDEBUG(DEBUG_GSM, "Request RTP peer info, before forwarding setup\n");
+               p_g_setup_pending = message;
+               rtp = (struct gsm_mncc_rtp *) create_mncc(MNCC_RTP_CREATE, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, rtp->msg_type, rtp);
+       } else
+               message_put(message);
+
 }
 
 /*
@@ -402,12 +361,13 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
  */
 int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
 {
+       struct interface *interface = lcr_gsm->interface;
        struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
        unsigned int callref = mncc->callref;
        class Port *port;
        class Pgsm_bs *pgsm_bs = NULL;
        char name[64];
-       struct mISDNport *mISDNport;
+//     struct mISDNport *mISDNport;
 
        /* Special messages */
        switch(msg_type) {
@@ -419,7 +379,7 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
        while(port) {
                if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) {
                        pgsm_bs = (class Pgsm_bs *)port;
-                       if (pgsm_bs->p_m_g_callref == callref) {
+                       if (pgsm_bs->p_g_callref == callref) {
                                break;
                        }
                }
@@ -429,19 +389,28 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
        if (msg_type == GSM_TCHF_FRAME) {
                if (port) {
                        /* inject DTMF, if enabled */
-                       if (pgsm_bs->p_m_g_dtmf) {
+                       if (pgsm_bs->p_g_dtmf) {
                                unsigned char data[160];
                                int i;
 
                                for (i = 0; i < 160; i++) {
-                                       data[i] = pgsm_bs->p_m_g_dtmf[pgsm_bs->p_m_g_dtmf_index++];
-                                       if (pgsm_bs->p_m_g_dtmf_index == 8000)
-                                               pgsm_bs->p_m_g_dtmf_index = 0;
+                                       data[i] = pgsm_bs->p_g_dtmf[pgsm_bs->p_g_dtmf_index++];
+                                       if (pgsm_bs->p_g_dtmf_index == 8000)
+                                               pgsm_bs->p_g_dtmf_index = 0;
                                }
                                /* send */
-                               pgsm_bs->bchannel_send(PH_DATA_REQ, 0, data, 160);
+                               pgsm_bs->bridge_tx(data, 160);
                        } else
                                pgsm_bs->frame_receive(arg);
+                       /* if we do not bridge we need to inject audio, if available */
+                       if (!pgsm_bs->p_bridge) {
+                               unsigned char data[160];
+                               int i;
+
+                               i = pgsm_bs->read_audio(data, 160);
+                               if (i)
+                                       pgsm_bs->bridge_rx(data, i);
+                       }
                }
                return 0;
        }
@@ -449,6 +418,7 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
        if (!port) {
                if (msg_type != MNCC_SETUP_IND)
                        return(0);
+#if 0
                /* find gsm port */
                mISDNport = mISDNport_first;
                while(mISDNport) {
@@ -472,10 +442,10 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
                        send_and_free_mncc(lcr_gsm, rej->msg_type, rej);
                        return 0;
                }
+#endif
                /* creating port object, transparent until setup with hdlc */
-               SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
-               if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
-
+               SPRINT(name, "%s-%d-in", interface->name, 0);
+               if (!(pgsm_bs = new Pgsm_bs(PORT_TYPE_GSM_BS_IN, name, NULL, interface)))
                        FATAL("Cannot create Port instance.\n");
        }
 
@@ -484,6 +454,14 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
                pgsm_bs->setup_ind(msg_type, callref, mncc);
                break;
 
+               case MNCC_RTP_CREATE:
+               pgsm_bs->rtp_create_ind(msg_type, callref, mncc);
+               break;
+
+               case MNCC_RTP_CONNECT:
+               pgsm_bs->rtp_connect_ind(msg_type, callref, mncc);
+               break;
+
                case MNCC_START_DTMF_IND:
                pgsm_bs->start_dtmf_ind(msg_type, callref, mncc);
                break;
@@ -540,10 +518,8 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
 void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
 {
        struct lcr_msg *message;
-       int ret;
        struct epoint_list *epointlist;
        struct gsm_mncc *mncc;
-       int channel;
 
        /* copy setup infos to port */
        memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
@@ -552,8 +528,8 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
 
        /* no GSM MNCC connection */
-       if (p_m_g_lcr_gsm->mncc_lfd.fd < 0) {
-               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+       if (p_g_lcr_gsm->mncc_lfd.fd < 0) {
+               gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
                add_trace("failure", NULL, "No MNCC connection.");
                end_trace();
                message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
@@ -561,13 +537,13 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
+               trigger_work(&p_g_delete);
                return;
        }
 
        /* no number */
        if (!p_dialinginfo.id[0]) {
-               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+               gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
                add_trace("failure", NULL, "No dialed subscriber given.");
                end_trace();
                message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
@@ -575,50 +551,13 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
-               return;
-       }
-       
-       /* release if port is blocked */
-       if (p_m_mISDNport->ifport->block) {
-               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
-               add_trace("failure", NULL, "Port blocked.");
-               end_trace();
-               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-               message->param.disconnectinfo.cause = 27; // temp. unavail.
-               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-               message_put(message);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
+               trigger_work(&p_g_delete);
                return;
        }
 
-       /* hunt channel */
-       ret = channel = hunt_bchannel();
-       if (ret < 0)
-               goto no_channel;
-       /* open channel */
-       ret = seize_bchannel(channel, 1);
-       if (ret < 0) {
-               no_channel:
-               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
-               add_trace("failure", NULL, "No internal audio channel available.");
-               end_trace();
-               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);
-               trigger_work(&p_m_g_delete);
-               return;
-       }
-       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-       if (bchannel_open(p_m_b_index))
-               goto no_channel;
-
 //             SCPY(&p_m_tones_dir, param->setup.ext.tones_dir);
        /* screen outgoing caller id */
-       do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
+       do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_g_interface_name);
 
        /* attach only if not already */
        epointlist = p_epointlist;
@@ -631,13 +570,13 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame
                epointlist_new(epoint_id);
 
        /* creating l3id */
-       l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
-       p_m_g_callref = new_callref++;
-       add_trace("callref", "new", "0x%x", p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_OUT);
+       p_g_callref = new_callref++;
+       add_trace("callref", "new", "0x%x", p_g_callref);
        end_trace();
 
-       gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
-       mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+       mncc = create_mncc(MNCC_SETUP_REQ, p_g_callref);
        /* caller information */
        mncc->fields |= MNCC_F_CALLING;
        mncc->calling.plan = 1;
@@ -749,7 +688,7 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame
        //todo
 
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_OUT_SETUP);
 
@@ -757,6 +696,14 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame
        message_put(message);
 
        new_state(PORT_STATE_OUT_PROCEEDING);
+
+       /* RTP bridge */
+       if (param->setup.rtpinfo.port) {
+               p_g_rtp_bridge = 1;
+               p_g_rtp_ip_remote = param->setup.rtpinfo.ip;
+               p_g_rtp_port_remote = param->setup.rtpinfo.port;
+       } else
+               p_g_rtp_bridge = 0;
 }
 
 /*
@@ -799,11 +746,12 @@ int gsm_bs_exit(int rc)
        return(rc);
 }
 
-int gsm_bs_init(void)
+int gsm_bs_init(struct interface *interface)
 {
        /* create gsm instance */
        gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
 
+       gsm_bs->interface = interface;
        gsm_bs->type = LCR_GSM_TYPE_NETWORK;
        gsm_bs->sun.sun_family = AF_UNIX;
        SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
index a57b7c7..81e1f13 100644 (file)
--- a/gsm_bs.h
+++ b/gsm_bs.h
@@ -3,11 +3,11 @@
 class Pgsm_bs : public Pgsm
 {
        public:
-       Pgsm_bs(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
+       Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface);
        ~Pgsm_bs();
 
-       unsigned char *p_m_g_dtmf; /* DTMF tone generation (MS only) */
-       int p_m_g_dtmf_index; /* DTMF tone generation index */
+       unsigned char *p_g_dtmf; /* DTMF tone generation (MS only) */
+       int p_g_dtmf_index; /* DTMF tone generation index */
 
        void setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
        void start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
@@ -20,6 +20,6 @@ class Pgsm_bs : public Pgsm
 
 int gsm_bs_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_bs_exit(int rc);
-int gsm_bs_init(void);
+int gsm_bs_init(struct interface *interface);
 
 int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg);
index b966ad8..dbd3351 100644 (file)
@@ -26,28 +26,28 @@ static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index);
 /*
  * constructor
  */
-Pgsm_ms::Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Pgsm(type, mISDNport, portname, settings, channel, exclusive, mode)
+Pgsm_ms::Pgsm_ms(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface)
 {
        struct lcr_gsm *gsm_ms = gsm_ms_first;
-       char *ms_name = mISDNport->ifport->gsm_ms_name;
 
-       p_m_g_lcr_gsm = NULL;
+       p_g_lcr_gsm = NULL;
+       SCPY(p_g_ms_name, interface->gsm_ms_name);
 
        while (gsm_ms) {
-               if (gsm_ms->type == LCR_GSM_TYPE_MS && !strcmp(gsm_ms->name, ms_name)) {
-                       p_m_g_lcr_gsm = gsm_ms;
+               if (gsm_ms->type == LCR_GSM_TYPE_MS && !strcmp(gsm_ms->name, p_g_ms_name)) {
+                       p_g_lcr_gsm = gsm_ms;
                        break;
                }
                gsm_ms = gsm_ms->gsm_ms_next;
        }
 
-       p_m_g_dtmf_state = DTMF_ST_IDLE;
-       p_m_g_dtmf_index = 0;
-       p_m_g_dtmf[0] = '\0';
-       memset(&p_m_g_dtmf_timer, 0, sizeof(p_m_g_dtmf_timer));
-       add_timer(&p_m_g_dtmf_timer, dtmf_timeout, this, 0);
+       p_g_dtmf_state = DTMF_ST_IDLE;
+       p_g_dtmf_index = 0;
+       p_g_dtmf[0] = '\0';
+       memset(&p_g_dtmf_timer, 0, sizeof(p_g_dtmf_timer));
+       add_timer(&p_g_dtmf_timer, dtmf_timeout, this, 0);
 
-       PDEBUG(DEBUG_GSM, "Created new GSMMSPort(%s %s).\n", portname, ms_name);
+       PDEBUG(DEBUG_GSM, "Created new GSMMSPort(%s %s).\n", portname, p_g_ms_name);
 }
 
 /*
@@ -56,7 +56,7 @@ Pgsm_ms::Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct p
 Pgsm_ms::~Pgsm_ms()
 {
        PDEBUG(DEBUG_GSM, "Destroyed GSM MS process(%s).\n", p_name);
-       del_timer(&p_m_g_dtmf_timer);
+       del_timer(&p_g_dtmf_timer);
 }
 
 /*
@@ -65,21 +65,19 @@ Pgsm_ms::~Pgsm_ms()
 /* SETUP INDICATION */
 void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc)
 {
-       int ret;
        class Endpoint *epoint;
        struct lcr_msg *message;
-       int channel;
        struct gsm_mncc *mode, *proceeding, *frame;
 
        /* process given callref */
-       l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_IN);
        add_trace("callref", "new", "0x%x", callref);
-       if (p_m_g_callref) {
+       if (p_g_callref) {
                /* release in case the ID is already in use */
                add_trace("error", NULL, "callref already in use");
                end_trace();
                mncc = create_mncc(MNCC_REJ_REQ, callref);
-               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
+               gsm_trace_header(p_g_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT);
                mncc->fields |= MNCC_F_CAUSE;
                mncc->cause.coding = 3;
                mncc->cause.location = 1;
@@ -89,34 +87,15 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
                add_trace("cause", "value", "%d", mncc->cause.value);
                add_trace("reason", NULL, "callref already in use");
                end_trace();
-               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+               send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
+               trigger_work(&p_g_delete);
                return;
        }
-       p_m_g_callref = callref;
+       p_g_callref = callref;
        end_trace();
 
-       /* if blocked, release call with MT_RELEASE_COMPLETE */
-       if (p_m_mISDNport->ifport->block) {
-               mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
-               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
-               mncc->fields |= MNCC_F_CAUSE;
-               mncc->cause.coding = 3;
-               mncc->cause.location = 1;
-               mncc->cause.value = 27;
-               add_trace("cause", "coding", "%d", mncc->cause.coding);
-               add_trace("cause", "location", "%d", mncc->cause.location);
-               add_trace("cause", "value", "%d", mncc->cause.value);
-               add_trace("reason", NULL, "port is blocked");
-               end_trace();
-               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
-               return;
-       }
-
-       gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_IND, DIRECTION_IN);
+       gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_IND, DIRECTION_IN);
        /* caller information */
        p_callerinfo.ntype = INFO_NTYPE_NOTPRESENT;
        if (mncc->fields & MNCC_F_CALLING) {
@@ -169,8 +148,7 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
                add_trace("calling", "screen", "%d", mncc->calling.screen);
                add_trace("calling", "number", "%s", mncc->calling.number);
        }
-       p_callerinfo.isdn_port = p_m_portnum;
-       SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+       SCPY(p_callerinfo.interface, p_g_interface_name);
        /* dialing information */
        if (mncc->fields & MNCC_F_CALLED) {
                SCAT(p_dialinginfo.id, mncc->called.number);
@@ -244,7 +222,6 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
                add_trace("redir", "present", "%d", mncc->redirecting.present);
                add_trace("redir", "screen", "%d", mncc->redirecting.screen);
                add_trace("redir", "number", "%s", mncc->redirecting.number);
-               p_redirinfo.isdn_port = p_m_portnum;
        }
        /* bearer capability */
        if (mncc->fields & MNCC_F_BEARER_CAP) {
@@ -282,35 +259,6 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
 
        end_trace();
 
-       /* hunt channel */
-       ret = channel = hunt_bchannel();
-       if (ret < 0)
-               goto no_channel;
-
-       /* open channel */
-       ret = seize_bchannel(channel, 1);
-       if (ret < 0) {
-               no_channel:
-               mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref);
-               gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT);
-               mncc->fields |= MNCC_F_CAUSE;
-               mncc->cause.coding = 3;
-               mncc->cause.location = 1;
-               mncc->cause.value = 34;
-               add_trace("cause", "coding", "%d", mncc->cause.coding);
-               add_trace("cause", "location", "%d", mncc->cause.location);
-               add_trace("cause", "value", "%d", mncc->cause.value);
-               add_trace("reason", NULL, "no channel");
-               end_trace();
-               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
-               return;
-       }
-       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-       if (bchannel_open(p_m_b_index))
-               goto no_channel;
-
        /* create endpoint */
        if (p_epointlist)
                FATAL("Incoming call but already got an endpoint.\n");
@@ -321,37 +269,36 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        epointlist_new(epoint->ep_serial);
 
        /* modify lchan to GSM codec V1 */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
-       mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT);
+       mode = create_mncc(MNCC_LCHAN_MODIFY, p_g_callref);
        mode->lchan_mode = 0x01; /* GSM V1 */
        mode->lchan_type = 0x02;
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
+       send_and_free_mncc(p_g_lcr_gsm, mode->msg_type, mode);
 
        /* send call proceeding */
-       gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_CONF_REQ, DIRECTION_OUT);
-       proceeding = create_mncc(MNCC_CALL_CONF_REQ, p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_CALL_CONF_REQ, DIRECTION_OUT);
+       proceeding = create_mncc(MNCC_CALL_CONF_REQ, p_g_callref);
        // FIXME: bearer
        /* DTMF supported */
        proceeding->fields |= MNCC_F_CCCAP;
        proceeding->cccap.dtmf = 1;
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, proceeding->msg_type, proceeding);
+       send_and_free_mncc(p_g_lcr_gsm, proceeding->msg_type, proceeding);
 
        new_state(PORT_STATE_IN_PROCEEDING);
 
-       if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */
-               gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
+       if (p_g_tones && !p_g_tch_connected) { /* only if ... */
+               gsm_trace_header(p_g_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
-               frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
-               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
-               p_m_g_tch_connected = 1;
+               frame = create_mncc(MNCC_FRAME_RECV, p_g_callref);
+               send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame);
+               p_g_tch_connected = 1;
        }
 
        /* send setup message to endpoit */
        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
-       message->param.setup.isdn_port = p_m_portnum;
        message->param.setup.port_type = p_type;
 //     message->param.setup.dtmf = 0;
        memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
@@ -368,12 +315,13 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
  */
 int message_ms(struct lcr_gsm *gsm_ms, int msg_type, void *arg)
 {
+       struct interface *interface = gsm_ms->interface;
        struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
        unsigned int callref = mncc->callref;
        class Port *port;
        class Pgsm_ms *pgsm_ms = NULL;
        char name[64];
-       struct mISDNport *mISDNport;
+//     struct mISDNport *mISDNport;
 
        /* Special messages */
        switch (msg_type) {
@@ -385,7 +333,7 @@ int message_ms(struct lcr_gsm *gsm_ms, int msg_type, void *arg)
        while(port) {
                if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) {
                        pgsm_ms = (class Pgsm_ms *)port;
-                       if (pgsm_ms->p_m_g_callref == callref) {
+                       if (pgsm_ms->p_g_callref == callref) {
                                break;
                        }
                }
@@ -401,6 +349,7 @@ int message_ms(struct lcr_gsm *gsm_ms, int msg_type, void *arg)
        if (!port) {
                if (msg_type != MNCC_SETUP_IND)
                        return(0);
+#if 0
                /* find gsm ms port */
                mISDNport = mISDNport_first;
                while(mISDNport) {
@@ -424,10 +373,10 @@ int message_ms(struct lcr_gsm *gsm_ms, int msg_type, void *arg)
                        send_and_free_mncc(gsm_ms, rej->msg_type, rej);
                        return 0;
                }
+#endif
                /* creating port object, transparent until setup with hdlc */
-               SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum);
-               if (!(pgsm_ms = new Pgsm_ms(PORT_TYPE_GSM_MS_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT)))
-
+               SPRINT(name, "%s-%d-in", interface->name, 0);
+               if (!(pgsm_ms = new Pgsm_ms(PORT_TYPE_GSM_MS_IN, name, NULL, interface)))
                        FATAL("Cannot create Port instance.\n");
        }
 
@@ -482,10 +431,8 @@ int message_ms(struct lcr_gsm *gsm_ms, int msg_type, void *arg)
 void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
 {
        struct lcr_msg *message;
-       int ret;
        struct epoint_list *epointlist;
        struct gsm_mncc *mncc;
-       int channel;
 
        /* copy setup infos to port */
        memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
@@ -494,22 +441,22 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
 
        /* no instance */
-       if (!p_m_g_lcr_gsm || p_m_g_lcr_gsm->mncc_lfd.fd < 0) {
-               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
-               add_trace("failure", NULL, "MS %s instance is unavailable", p_m_mISDNport->ifport->gsm_ms_name);
+       if (!p_g_lcr_gsm || p_g_lcr_gsm->mncc_lfd.fd < 0) {
+               gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+               add_trace("failure", NULL, "MS %s instance is unavailable", p_g_ms_name);
                end_trace();
                message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                message->param.disconnectinfo.cause = 41;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
+               trigger_work(&p_g_delete);
                return;
        }
        
        /* no number */
        if (!p_dialinginfo.id[0]) {
-               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+               gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
                add_trace("failure", NULL, "No dialed subscriber given.");
                end_trace();
                message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
@@ -517,46 +464,9 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
+               trigger_work(&p_g_delete);
                return;
        }
-       
-       /* release if port is blocked */
-       if (p_m_mISDNport->ifport->block) {
-               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
-               add_trace("failure", NULL, "Port blocked.");
-               end_trace();
-               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-               message->param.disconnectinfo.cause = 27; // temp. unavail.
-               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-               message_put(message);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_g_delete);
-               return;
-       }
-
-       /* hunt channel */
-       ret = channel = hunt_bchannel();
-       if (ret < 0)
-               goto no_channel;
-       /* open channel */
-       ret = seize_bchannel(channel, 1);
-       if (ret < 0) {
-               no_channel:
-               gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
-               add_trace("failure", NULL, "No internal audio channel available.");
-               end_trace();
-               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);
-               trigger_work(&p_m_g_delete);
-               return;
-       }
-       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-       if (bchannel_open(p_m_b_index))
-               goto no_channel;
 
        /* attach only if not already */
        epointlist = p_epointlist;
@@ -569,13 +479,13 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame
                epointlist_new(epoint_id);
 
        /* creating l3id */
-       l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT);
-       p_m_g_callref = new_callref++;
-       add_trace("callref", "new", "0x%x", p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, 0, DIRECTION_OUT);
+       p_g_callref = new_callref++;
+       add_trace("callref", "new", "0x%x", p_g_callref);
        end_trace();
 
-       gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
-       mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref);
+       gsm_trace_header(p_g_interface_name, this, MNCC_SETUP_REQ, DIRECTION_OUT);
+       mncc = create_mncc(MNCC_SETUP_REQ, p_g_callref);
        if (!strncasecmp(p_dialinginfo.id, "emerg", 5)) {
                mncc->emergency = 1;
        } else {
@@ -631,7 +541,7 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame
        }
 
        end_trace();
-       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
+       send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_OUT_SETUP);
 
@@ -639,49 +549,51 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame
        message_put(message);
 
        new_state(PORT_STATE_OUT_PROCEEDING);
+
+       p_g_rtp_bridge = 0;
 }
 
 void Pgsm_ms::dtmf_statemachine(struct gsm_mncc *mncc)
 {
        struct gsm_mncc *dtmf;
 
-       switch (p_m_g_dtmf_state) {
+       switch (p_g_dtmf_state) {
        case DTMF_ST_SPACE:
        case DTMF_ST_IDLE:
                /* end of string */
-               if (!p_m_g_dtmf[p_m_g_dtmf_index]) {
+               if (!p_g_dtmf[p_g_dtmf_index]) {
                        PDEBUG(DEBUG_GSM, "done with DTMF\n");
-                       p_m_g_dtmf_state = DTMF_ST_IDLE;
+                       p_g_dtmf_state = DTMF_ST_IDLE;
                        return;
                }
-               gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_REQ, DIRECTION_OUT);
-               dtmf = create_mncc(MNCC_START_DTMF_REQ, p_m_g_callref);
-               dtmf->keypad = p_m_g_dtmf[p_m_g_dtmf_index++];
-               p_m_g_dtmf_state = DTMF_ST_START;
+               gsm_trace_header(p_g_interface_name, this, MNCC_START_DTMF_REQ, DIRECTION_OUT);
+               dtmf = create_mncc(MNCC_START_DTMF_REQ, p_g_callref);
+               dtmf->keypad = p_g_dtmf[p_g_dtmf_index++];
+               p_g_dtmf_state = DTMF_ST_START;
                PDEBUG(DEBUG_GSM, "start DTMF (keypad %c)\n",
                        dtmf->keypad);
                end_trace();
-               send_and_free_mncc(p_m_g_lcr_gsm, dtmf->msg_type, dtmf);
+               send_and_free_mncc(p_g_lcr_gsm, dtmf->msg_type, dtmf);
                return;
        case DTMF_ST_START:
                if (mncc->msg_type != MNCC_START_DTMF_RSP) {
                        PDEBUG(DEBUG_GSM, "DTMF was rejected\n");
                        return;
                }
-               schedule_timer(&p_m_g_dtmf_timer, 0, 70 * 1000);
-               p_m_g_dtmf_state = DTMF_ST_MARK;
+               schedule_timer(&p_g_dtmf_timer, 0, 70 * 1000);
+               p_g_dtmf_state = DTMF_ST_MARK;
                PDEBUG(DEBUG_GSM, "DTMF is on\n");
                break;
        case DTMF_ST_MARK:
-               gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_REQ, DIRECTION_OUT);
-               dtmf = create_mncc(MNCC_STOP_DTMF_REQ, p_m_g_callref);
-               p_m_g_dtmf_state = DTMF_ST_STOP;
+               gsm_trace_header(p_g_interface_name, this, MNCC_STOP_DTMF_REQ, DIRECTION_OUT);
+               dtmf = create_mncc(MNCC_STOP_DTMF_REQ, p_g_callref);
+               p_g_dtmf_state = DTMF_ST_STOP;
                end_trace();
-               send_and_free_mncc(p_m_g_lcr_gsm, dtmf->msg_type, dtmf);
+               send_and_free_mncc(p_g_lcr_gsm, dtmf->msg_type, dtmf);
                return;
        case DTMF_ST_STOP:
-               schedule_timer(&p_m_g_dtmf_timer, 0, 120 * 1000);
-               p_m_g_dtmf_state = DTMF_ST_SPACE;
+               schedule_timer(&p_g_dtmf_timer, 0, 120 * 1000);
+               p_g_dtmf_state = DTMF_ST_SPACE;
                PDEBUG(DEBUG_GSM, "DTMF is off\n");
                break;
        }
@@ -708,12 +620,12 @@ void Pgsm_ms::message_dtmf(unsigned int epoint_id, int message_id, union paramet
                return;
 
        /* schedule */
-       if (p_m_g_dtmf_state == DTMF_ST_IDLE) {
-               p_m_g_dtmf_index = 0;
-               p_m_g_dtmf[0] = '\0';
+       if (p_g_dtmf_state == DTMF_ST_IDLE) {
+               p_g_dtmf_index = 0;
+               p_g_dtmf[0] = '\0';
        }
-       SCCAT(p_m_g_dtmf, digit);
-       if (p_m_g_dtmf_state == DTMF_ST_IDLE)
+       SCCAT(p_g_dtmf, digit);
+       if (p_g_dtmf_state == DTMF_ST_IDLE)
                dtmf_statemachine(NULL);
 }
 
@@ -731,12 +643,12 @@ void Pgsm_ms::message_information(unsigned int epoint_id, int message_id, union
                        continue;
 
                /* schedule */
-               if (p_m_g_dtmf_state == DTMF_ST_IDLE) {
-                       p_m_g_dtmf_index = 0;
-                       p_m_g_dtmf[0] = '\0';
+               if (p_g_dtmf_state == DTMF_ST_IDLE) {
+                       p_g_dtmf_index = 0;
+                       p_g_dtmf[0] = '\0';
                }
-               SCCAT(p_m_g_dtmf, digit);
-               if (p_m_g_dtmf_state == DTMF_ST_IDLE)
+               SCCAT(p_g_dtmf, digit);
+               if (p_g_dtmf_state == DTMF_ST_IDLE)
                        dtmf_statemachine(NULL);
        }
 }
@@ -794,7 +706,7 @@ int gsm_ms_init(void)
 }
 
 /* add a new GSM mobile instance */
-int gsm_ms_new(const char *name)
+int gsm_ms_new(struct interface *interface)
 {
        struct lcr_gsm *gsm_ms = gsm_ms_first, **gsm_ms_p = &gsm_ms_first;
 
@@ -803,15 +715,16 @@ int gsm_ms_new(const char *name)
                gsm_ms = gsm_ms->gsm_ms_next;
        }
 
-       PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is created\n", name);
+       PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is created\n", interface->gsm_ms_name);
 
        /* create gsm instance */
        gsm_ms = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
 
+       gsm_ms->interface = interface;
        gsm_ms->type = LCR_GSM_TYPE_MS;
-       SCPY(gsm_ms->name, name);
+       SCPY(gsm_ms->name, interface->gsm_ms_name);
        gsm_ms->sun.sun_family = AF_UNIX;
-       SPRINT(gsm_ms->sun.sun_path, "/tmp/ms_mncc_%s", name);
+       SPRINT(gsm_ms->sun.sun_path, "/tmp/ms_mncc_%s", gsm_ms->name);
 
        memset(&gsm_ms->socket_retry, 0, sizeof(gsm_ms->socket_retry));
        add_timer(&gsm_ms->socket_retry, mncc_socket_retry_cb, gsm_ms, 0);
@@ -851,10 +764,10 @@ int gsm_ms_delete(const char *name)
        while(port) {
                if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) {
                        pgsm_ms = (class Pgsm_ms *)port;
-                       if (pgsm_ms->p_m_g_lcr_gsm == gsm_ms && pgsm_ms->p_m_g_callref) {
+                       if (pgsm_ms->p_g_lcr_gsm == gsm_ms && pgsm_ms->p_g_callref) {
                                struct gsm_mncc *rej;
 
-                               rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_m_g_callref);
+                               rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_g_callref);
                                rej->fields |= MNCC_F_CAUSE;
                                rej->cause.coding = 3;
                                rej->cause.location = 1;
@@ -866,7 +779,7 @@ int gsm_ms_delete(const char *name)
                                end_trace();
                                send_and_free_mncc(gsm_ms, rej->msg_type, rej);
                                pgsm_ms->new_state(PORT_STATE_RELEASE);
-                               trigger_work(&pgsm_ms->p_m_g_delete);
+                               trigger_work(&pgsm_ms->p_g_delete);
                        }
                }
        }
index 70ea825..82202f5 100644 (file)
--- a/gsm_ms.h
+++ b/gsm_ms.h
@@ -3,13 +3,14 @@
 class Pgsm_ms : public Pgsm
 {
        public:
-       Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
+       Pgsm_ms(int type, char *portname, struct port_settings *settings, struct interface *interface);
        ~Pgsm_ms();
 
-       int p_m_g_dtmf_state;
-       int p_m_g_dtmf_index;
-       char p_m_g_dtmf[128];
-       struct lcr_timer p_m_g_dtmf_timer;
+       char p_g_ms_name[32];
+       int p_g_dtmf_state;
+       int p_g_dtmf_index;
+       char p_g_dtmf[128];
+       struct lcr_timer p_g_dtmf_timer;
        void dtmf_statemachine(struct gsm_mncc *mncc);
 
        void setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc);
@@ -22,7 +23,7 @@ class Pgsm_ms : public Pgsm
 int gsm_ms_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_ms_exit(int rc);
 int gsm_ms_init(void);
-int gsm_ms_new(const char *name);
+int gsm_ms_new(struct interface *interface);
 int gsm_ms_delete(const char *name);
 int message_ms(struct lcr_gsm *lcr_gsm, int msg_type, void *arg);
 
index 264f4f2..60e058f 100644 (file)
@@ -894,31 +894,19 @@ static int inter_gsm_bs(struct interface *interface, char *filename, int line, c
        SPRINT(interface_error, "Error in %s (line %d): GSM BS side not compiled in.\n", filename, line);
        return(-1);
 #else
-       struct interface_port *ifport;
        struct interface *searchif;
 
        searchif = interface_newlist;
        while(searchif) {
-               ifport = searchif->ifport;
-               while(ifport) {
-                       if (ifport->gsm_bs) {
-                               SPRINT(interface_error, "Error in %s (line %d): port '%s' already uses gsm BS side.\n", filename, line, ifport->portname);
-                               return(-1);
-                       }
-                       ifport = ifport->next;
+               if (searchif->gsm_bs) {
+                       SPRINT(interface_error, "Error in %s (line %d): interface '%s' already uses gsm BS side.\n", filename, line, searchif->name);
+                       return(-1);
                }
                searchif = searchif->next;
        }
 
-       /* set portname */
-       if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
-               return(-1);
-
        /* goto end of chain again to set gsmflag */
-       ifport = interface->ifport;
-       while(ifport->next)
-               ifport = ifport->next;
-       ifport->gsm_bs = 1;
+       interface->gsm_bs = 1;
 
        return(0);
 #endif
@@ -929,37 +917,23 @@ static int inter_gsm_ms(struct interface *interface, char *filename, int line, c
        SPRINT(interface_error, "Error in %s (line %d): GSM MS side not compiled in.\n", filename, line);
        return(-1);
 #else
-       struct interface_port *ifport, *searchifport;
        struct interface *searchif;
 
-       /* set portname */
-       if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
-               return(-1);
-
-       /* goto end of chain again to set gsmflag and socket */
-       ifport = interface->ifport;
-       while(ifport->next)
-               ifport = ifport->next;
-       ifport->gsm_ms = 1;
+       interface->gsm_ms = 1;
 
        /* copy values */
        if (!value || !value[0]) {
                SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
                return(-1);
        }
-       SCPY(ifport->gsm_ms_name, value);
+       SCPY(interface->gsm_ms_name, value);
 
        /* check if name is used multiple times */
        searchif = interface_newlist;
        while(searchif) {
-               searchifport = searchif->ifport;
-               while(searchifport) {
-                       if (searchifport != ifport 
-                        && !strcmp(searchifport->gsm_ms_name, ifport->gsm_ms_name)) {
-                               SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_name);
-                               return(-1);
-                       }
-                       searchifport = searchifport->next;
+               if (!strcmp(searchif->gsm_ms_name, interface->gsm_ms_name)) {
+                       SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, interface->gsm_ms_name, searchif->gsm_ms_name);
+                       return(-1);
                }
                searchif = searchif->next;
        }
@@ -975,10 +949,6 @@ static int inter_sip(struct interface *interface, char *filename, int line, char
 #else
        char *p;
 
-       /* set portname */
-       if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
-               return(-1);
-
        interface->sip = 1;
 
        /* copy values */
@@ -997,6 +967,12 @@ static int inter_sip(struct interface *interface, char *filename, int line, char
        return(0);
 #endif
 }
+static int inter_rtp_bridge(struct interface *interface, char *filename, int line, char *parameter, char *value)
+{
+       interface->rtp_bridge = 1;
+
+       return(0);
+}
 static int inter_nonotify(struct interface *interface, char *filename, int line, char *parameter, char *value)
 {
        struct interface_port *ifport;
@@ -1247,6 +1223,9 @@ struct interface_param interface_param[] = {
        {"sip", &inter_sip, "<local IP> <remote IP>",
        "Sets up SIP interface that represents one SIP endpoint.\n"
        "Give SIP configuration file."},
+       {"rtp-bridge", &inter_rtp_bridge, "",
+       "Sets up SIP interface that represents one SIP endpoint.\n"
+       "Give SIP configuration file."},
        {"nonotify", &inter_nonotify, "",
        "Prevents sending notify messages to this interface. A call placed on hold will\n"
        "Not affect the remote end (phone or telcom switch).\n"
@@ -1524,28 +1503,65 @@ static void set_defaults(struct interface_port *ifport)
 void relink_interfaces(void)
 {
        struct mISDNport *mISDNport;
-       struct interface *interface;
+       struct interface *interface, *temp;
        struct interface_port *ifport;
+       int found;
 
-       /* unlink all mISDNports */
-       mISDNport = mISDNport_first;
-       while(mISDNport) {
-               if (mISDNport->ifport) {
-                       ifport = mISDNport->ifport;
+       interface = interface_first;
+       while(interface) {
+               found = 0;
+               temp = interface_newlist;
+               while(temp) {
+                       if (!strcmp(temp->name, interface->name))
+                               found = 1;
+                       temp = temp->next;
+               }
+               if (!found) {
 #ifdef WITH_GSM_MS
-                       if (ifport->gsm_ms)
-                               gsm_ms_delete(ifport->gsm_ms_name);
+                       if (interface->gsm_ms)
+                               gsm_ms_delete(interface->gsm_ms_name);
 #endif
 #ifdef WITH_GSM_BS
-                       if (ifport->gsm_bs)
+                       if (interface->gsm_bs)
                                gsm_bs_exit(0);
 #endif
 #ifdef WITH_SIP
-#warning FIXME: get out of mISDNport
-                       if (ifport->interface->sip)
-                               sip_exit_inst(mISDNport->ifport->interface);
+                       if (interface->sip)
+                               sip_exit_inst(interface);
+#endif
+               }
+               interface = interface->next;
+       }
+
+       interface = interface_newlist;
+       while(interface) {
+               found = 0;
+               temp = interface_first;
+               while(temp) {
+                       if (!strcmp(temp->name, interface->name))
+                               found = 1;
+                       temp = temp->next;
+               }
+               if (!found) {
+#ifdef WITH_GSM_MS
+                       if (interface->gsm_ms)
+                               gsm_ms_new(interface);
+#endif
+#ifdef WITH_GSM_BS
+                       if (interface->gsm_bs)
+                               gsm_bs_init(interface);
+#endif
+#ifdef WITH_SIP
+                       if (interface->sip)
+                               sip_init_inst(interface);
 #endif
                }
+               interface = interface->next;
+       }
+
+       /* unlink all mISDNports */
+       mISDNport = mISDNport_first;
+       while(mISDNport) {
                mISDNport->ifport = NULL;
                mISDNport = mISDNport->next;
        }
@@ -1625,19 +1641,6 @@ void load_port(struct interface_port *ifport)
                set_defaults(ifport);
                /* load static port instances */
                mISDNport_static(mISDNport);
-#ifdef WITH_GSM_MS
-               if (ifport->gsm_ms)
-                       gsm_ms_new(ifport->gsm_ms_name);
-#endif
-#ifdef WITH_GSM_BS
-               if (ifport->gsm_bs)
-                       gsm_bs_init();
-#endif
-#ifdef WITH_SIP
-               if (ifport->interface->sip)
-                       if (sip_init_inst(ifport->interface))
-                               ifport->block = 2; /* not available */
-#endif
        } else {
                ifport->block = 2; /* not available */
        }
@@ -1675,12 +1678,21 @@ void doc_interface(void)
 /* screen caller id
  * out==0: incoming caller id, out==1: outgoing caller id
  */
-void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface)
+void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name)
 {
        char                    *msn1;
        struct interface_msn    *ifmsn;
        struct interface_screen *ifscreen;
        char suffix[64];
+       struct interface *interface = interface_first;
+
+       while (interface) {
+               if (!strcmp(interface->name, interface_name))
+                       break;
+               interface = interface->next;
+       }
+       if (!interface)
+               return;
 
        /* screen incoming caller id */
        if (!out) {
index d9462ed..ea9cbad 100644 (file)
@@ -51,13 +51,6 @@ struct interface_port {
        int                     tespecial; /* special TE-mode behavior */
        int                     l1hold; /* hold layer 1 (1=on, 0=off) */
        int                     l2hold; /* hold layer 2 (1=force, -1=disable, 0=default) */
-#ifdef WITH_GSM_BS
-       int                     gsm_bs; /* interface is an GSM BS interface */
-#endif
-#ifdef WITH_GSM_MS
-       int                     gsm_ms; /* interface is an GSM MS interface */
-       char                    gsm_ms_name[32]; /* name of ms */
-#endif
        unsigned int            ss5; /* set, if SS5 signalling enabled, also holds feature bits */
        int                     remote; /* interface is a remote app interface */
        char                    remote_app[32]; /* name of remote application */
@@ -111,12 +104,20 @@ struct interface {
        char                    pipeline[256]; /* filter pipeline */
        unsigned char           bf_key[56]; /* filter blowfish */
        int                     bf_len; /* filter length of blowfish */
+#ifdef WITH_GSM_BS
+       int                     gsm_bs; /* interface is an GSM BS interface */
+#endif
+#ifdef WITH_GSM_MS
+       int                     gsm_ms; /* interface is an GSM MS interface */
+       char                    gsm_ms_name[32]; /* name of ms */
+#endif
 #ifdef WITH_SIP
        int                     sip; /* interface is a SIP interface */
        char                    sip_local_ip[16];
        char                    sip_remote_ip[16];
        void                    *sip_inst; /* sip instance */
 #endif
+       int                     rtp_bridge; /* bridge RTP directly (for calls comming from interface) */
 };
 
 struct interface_param {
@@ -137,5 +138,5 @@ void free_interfaces(struct interface *interface_start);
 void relink_interfaces(void);
 void load_port(struct interface_port *ifport);
 void doc_interface(void);
-void do_screen(int out, char *id, int idsize, int *type, int *present, struct interface *interface);
+void do_screen(int out, char *id, int idsize, int *type, int *present, const char *interface_name);
 
index 2483a9b..f8a1ac8 100644 (file)
@@ -621,7 +621,10 @@ const char *admin_state(int sock, char *argv[])
                        /* show interface summary */
                        move(++line>1?line:1, 0);
                        color(white);
-                       if (m[i].u.i.block >= 2) {
+                       if (m[i].u.i.portnum == -100) {
+                               SPRINT(buffer, "%s %s", m[i].u.i.interface_name, (m[i].u.i.extension)?" exten":"");
+                               addstr(buffer);
+                       } else if (m[i].u.i.block >= 2) {
                                if (m[i].u.i.portnum < 0)
                                        SPRINT(buffer, "%s (port ?: %s)%s", m[i].u.i.interface_name, m[i].u.i.portname, (m[i].u.i.extension)?" exten":"");
                                else
index 002f83f..6392a4c 100644 (file)
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -2001,7 +2001,6 @@ static int b_sock_callback(struct lcr_fd *fd, unsigned int what, void *instance,
 static int b_timer_timeout(struct lcr_timer *timer, void *instance, int i)
 {
        struct mISDNport *mISDNport = (struct mISDNport *)instance;
-puts("fires");
 
        bchannel_event(mISDNport, i, B_EVENT_TIMEOUT);
 
@@ -2103,15 +2102,6 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
        unsigned int protocol, prop;
 
        loop = 0;
-#ifdef WITH_GSM_BS
-       loop |= ifport->gsm_bs;
-#endif
-#ifdef WITH_GSM_MS
-       loop |= ifport->gsm_ms;
-#endif
-#ifdef WITH_SIP
-       loop |= ifport->interface->sip;
-#endif
 //printf("%s == %s\n", ifport->portname, options.loopback_int);
        if (!strcmp(ifport->portname, options.loopback_lcr))
                loop = 1;
@@ -2260,12 +2250,6 @@ struct mISDNport *mISDNport_open(struct interface_port *ifport)
                mISDNport->l1link = -1;
                mISDNport->l2link = -1;
        }
-#ifdef WITH_GSM_BS
-       mISDNport->gsm_bs = ifport->gsm_bs;
-#endif
-#ifdef WITH_GSM_MS
-       mISDNport->gsm_ms = ifport->gsm_ms;
-#endif
        mISDNport->isloopback = loop;
        pmemuse++;
        *mISDNportp = mISDNport;
diff --git a/mISDN.h b/mISDN.h
index c310023..e3e59a4 100644 (file)
--- a/mISDN.h
+++ b/mISDN.h
@@ -64,13 +64,6 @@ struct mISDNport {
        int locally; /* local causes are sent as local causes not remote */
        int los, ais, rdi, slip_rx, slip_tx;
 
-       /* gsm */
-#ifdef WITH_GSM_BS
-       int gsm_bs; /* this is the (only) GSM BS interface */
-#endif
-#ifdef WITH_GSM_MS
-       int gsm_ms; /* this is an GSM MS interface */
-#endif
        int lcr_sock; /* socket of loopback on LCR side */
        int isloopback; /* will be set on open, in case it is a loopback if */
 
index 4cfc5b1..6330654 100644 (file)
--- a/message.h
+++ b/message.h
@@ -148,6 +148,13 @@ enum {
        B_MODE_HDLC,            /* hdlc data mode */
 };
 
+/* rtp-info structure */
+struct rtp_info {
+       int payload_type;
+       unsigned int ip;
+       unsigned short port;
+};
+
 /* call-info structure CALLER */
 struct caller_info {
        char id[32];                    /* id of caller (user number) */
@@ -191,6 +198,7 @@ struct connect_info {
        int screen;                     /* who provided the number */
        char display[84];               /* display information */
        char imsi[16];                  /* IMSI for gsm terminated calls */
+       struct rtp_info rtpinfo;        /* info about RTP peer */
 };
 
 /* call-info structure DISCONNECT */
@@ -240,6 +248,7 @@ struct notify_info {
 struct progress_info {
        int progress;                   /* progress indicator */
        int location;                   /* progress location */
+       struct rtp_info rtpinfo;        /* info about RTP peer */
 };
 
 /* call-info structure FACILITY */
@@ -266,7 +275,8 @@ struct message_setup {
        struct redir_info redirinfo;            /* info on redirection (to the calling user) */
        struct capa_info capainfo;              /* info on l2,l3 capability */
        struct useruser_info useruser;          /* user-user */
-//     struct progress_info progress;          /* info on call progress */
+       struct progress_info progress;          /* info on call progress */
+       struct rtp_info rtpinfo;                /* info about RTP peer */
        char context[128];                      /* asterisk context */
 };
 
diff --git a/mncc.h b/mncc.h
index e5f8216..04b3241 100644 (file)
--- a/mncc.h
+++ b/mncc.h
@@ -52,6 +52,9 @@
 #define MNCC_FRAME_RECV                0x0201
 #define MNCC_FRAME_DROP                0x0202
 #define MNCC_LCHAN_MODIFY      0x0203
+#define MNCC_RTP_CREATE                0x0204
+#define MNCC_RTP_CONNECT       0x0205
+#define MNCC_RTP_FREE          0x0206
 
 #define GSM_TCHF_FRAME         0x0300
 #define GSM_TCHF_FRAME_EFR     0x0301
@@ -185,3 +188,11 @@ struct gsm_data_frame {
        unsigned char   data[0];
 };
 
+struct gsm_mncc_rtp {
+       uint32_t        msg_type;
+       uint32_t        callref;
+       uint32_t        ip;
+       uint16_t        port;
+};
+
+
index 74f8aac..4afca9c 100644 (file)
--- a/port.cpp
+++ b/port.cpp
@@ -149,8 +149,6 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
 {
        class Port *temp, **tempp;
 
-       PDEBUG(DEBUG_PORT, "new port of type 0x%x, name '%s'\n", type, portname);
-
        /* initialize object */
        if (settings)
                memcpy(&p_settings, settings, sizeof(struct port_settings));
@@ -195,6 +193,8 @@ Port::Port(int type, const char *portname, struct port_settings *settings)
        *tempp = this;
 
        classuse++;
+
+       PDEBUG(DEBUG_PORT, "new port (%d) of type 0x%x, name '%s'\n", p_serial, type, portname);
 }
 
 
@@ -206,7 +206,7 @@ Port::~Port(void)
        class Port *temp, **tempp;
        struct lcr_msg *message;
 
-       PDEBUG(DEBUG_PORT, "removing port of type 0x%x, name '%s'\n", p_type, p_name);
+       PDEBUG(DEBUG_PORT, "removing port (%d) of type 0x%x, name '%s'\n", p_serial, p_type, p_name);
 
        if (p_bridge) {
                PDEBUG(DEBUG_PORT, "Removing us from bridge %u\n", p_bridge->bridge_id);
@@ -301,7 +301,7 @@ void Port::set_tone(const char *dir, const char *name)
        if (name == NULL)
                name = "";
 
-       if (!dir && !dir[0])
+       if (!dir || !dir[0])
                dir = options.tones_dir; /* just in case we have no PmISDN instance */
 
        /* no counter, no eof, normal speed */
diff --git a/port.h b/port.h
index 066ace7..d09ba0c 100644 (file)
--- a/port.h
+++ b/port.h
 #define PORT_CLASS_DSS1                0x1100
 #define PORT_CLASS_DSS1_NT     0x1110
 #define PORT_CLASS_DSS1_TE     0x1120
-#define PORT_CLASS_GSM         0x1200
-#define PORT_CLASS_GSM_BS      0x1210
-#define PORT_CLASS_GSM_MS      0x1220
 #define PORT_CLASS_SS5         0x1300
 #define PORT_CLASS_REMOTE      0x1400
-#define PORT_CLASS_SIP         0x1500
+#define PORT_CLASS_SIP         0x2000
+#define PORT_CLASS_GSM         0x3000
+#define PORT_CLASS_GSM_BS      0x3100
+#define PORT_CLASS_GSM_MS      0x3200
 #define PORT_CLASS_MASK                0xf000
 #define PORT_CLASS_mISDN_MASK  0xff00
 #define PORT_CLASS_DSS1_MASK   0xfff0
-#define PORT_CLASS_GSM_MASK    0xfff0
+#define PORT_CLASS_GSM_MASK    0xff00
 #define PORT_CLASS_DIR_MASK    0x000f
 #define PORT_CLASS_DIR_IN      0x0001
 #define PORT_CLASS_DIR_OUT     0x0002
 #define        PORT_TYPE_DSS1_TE_IN    0x1121
 #define        PORT_TYPE_DSS1_TE_OUT   0x1122
        /* gsm */
-#define        PORT_TYPE_GSM_BS_IN     0x1211
-#define        PORT_TYPE_GSM_BS_OUT    0x1212
-#define        PORT_TYPE_GSM_MS_IN     0x1221
-#define        PORT_TYPE_GSM_MS_OUT    0x1222
+#define        PORT_TYPE_GSM_BS_IN     0x3101
+#define        PORT_TYPE_GSM_BS_OUT    0x3102
+#define        PORT_TYPE_GSM_MS_IN     0x3201
+#define        PORT_TYPE_GSM_MS_OUT    0x3202
        /* ss5 */
 #define        PORT_TYPE_SS5_IN        0x1311
 #define        PORT_TYPE_SS5_OUT       0x1312
 #define        PORT_TYPE_REMOTE_IN     0x1411
 #define        PORT_TYPE_REMOTE_OUT    0x1412
        /* SIP */
-#define        PORT_TYPE_SIP_IN        0x1511
-#define        PORT_TYPE_SIP_OUT       0x1512
+#define        PORT_TYPE_SIP_IN        0x2001
+#define        PORT_TYPE_SIP_OUT       0x2002
        /* answering machine */
-#define        PORT_TYPE_VBOX_OUT      0x3111
+#define        PORT_TYPE_VBOX_OUT      0xf111
 
 
 enum { /* states of call */
diff --git a/sip.cpp b/sip.cpp
index 40c5572..e39f19c 100644 (file)
--- a/sip.cpp
+++ b/sip.cpp
@@ -21,7 +21,9 @@ unsigned char flip[256];
 su_home_t      sip_home[1];
 
 struct sip_inst {
-       struct interface        *interface;
+       char                    interface_name[64];
+       char                    local_ip[16];
+       char                    remote_ip[16];
        su_root_t               *root;
        nua_t                   *nua;
 };
@@ -31,28 +33,32 @@ static int delete_event(struct lcr_work *work, void *instance, int index);
 /*
  * initialize SIP port
  */
-Psip::Psip(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode, struct interface *interface) : PmISDN(type, mISDNport, portname, settings, channel, exclusive, mode)
+Psip::Psip(int type, char *portname, struct port_settings *settings, struct interface *interface) : Port(type, portname, settings)
 {
-       p_m_s_sip_inst = interface->sip_inst;
-       memset(&p_m_s_delete, 0, sizeof(p_m_s_delete));
-       add_work(&p_m_s_delete, delete_event, this, 0);
-       p_m_s_handle = 0;
-       p_m_s_magic = 0;
-       memset(&p_m_s_rtp_fd, 0, sizeof(p_m_s_rtp_fd));
-       memset(&p_m_s_rtcp_fd, 0, sizeof(p_m_s_rtcp_fd));
-       memset(&p_m_s_rtp_sin_local, 0, sizeof(p_m_s_rtp_sin_local));
-       memset(&p_m_s_rtcp_sin_local, 0, sizeof(p_m_s_rtcp_sin_local));
-       memset(&p_m_s_rtp_sin_remote, 0, sizeof(p_m_s_rtp_sin_remote));
-       memset(&p_m_s_rtcp_sin_remote, 0, sizeof(p_m_s_rtcp_sin_remote));
-       p_m_s_rtp_ip_local = 0;
-       p_m_s_rtp_ip_remote = 0;
-       p_m_s_rtp_port_local = 0;
-       p_m_s_rtp_port_remote = 0;
-       p_m_s_b_sock = -1;
-       p_m_s_b_index = -1;
-       p_m_s_b_active = 0;
-       p_m_s_rxpos = 0;
-       p_m_s_rtp_tx_action = 0;
+       p_s_rtp_bridge = 0;
+       if (interface->rtp_bridge)
+               p_s_rtp_bridge = 1;
+       p_s_sip_inst = interface->sip_inst;
+       memset(&p_s_delete, 0, sizeof(p_s_delete));
+       add_work(&p_s_delete, delete_event, this, 0);
+       p_s_handle = 0;
+       p_s_magic = 0;
+       memset(&p_s_rtp_fd, 0, sizeof(p_s_rtp_fd));
+       memset(&p_s_rtcp_fd, 0, sizeof(p_s_rtcp_fd));
+       memset(&p_s_rtp_sin_local, 0, sizeof(p_s_rtp_sin_local));
+       memset(&p_s_rtcp_sin_local, 0, sizeof(p_s_rtcp_sin_local));
+       memset(&p_s_rtp_sin_remote, 0, sizeof(p_s_rtp_sin_remote));
+       memset(&p_s_rtcp_sin_remote, 0, sizeof(p_s_rtcp_sin_remote));
+       p_s_rtp_payload_type = 0;
+       p_s_rtp_ip_local = 0;
+       p_s_rtp_ip_remote = 0;
+       p_s_rtp_port_local = 0;
+       p_s_rtp_port_remote = 0;
+       p_s_b_sock = -1;
+       p_s_b_index = -1;
+       p_s_b_active = 0;
+       p_s_rxpos = 0;
+       p_s_rtp_tx_action = 0;
 
        PDEBUG(DEBUG_SIP, "Created new Psip(%s).\n", portname);
 }
@@ -65,15 +71,26 @@ Psip::~Psip()
 {
        PDEBUG(DEBUG_SIP, "Destroyed SIP process(%s).\n", p_name);
 
-       del_work(&p_m_s_delete);
-
-       /* close audio transfer socket */
-       if (p_m_s_b_sock > -1)
-               bchannel_close();
+       del_work(&p_s_delete);
 
        rtp_close();
 }
 
+const char *payload_type2name(uint8_t payload_type) {
+       switch (payload_type) {
+       case 0:
+               return "PCMU";
+       case 8:
+               return "PCMA";
+       case 3:
+       case 96:
+       case 97:
+       case 98:
+               return "GSM";
+       }
+
+       return "UKN";
+}
 
 static void sip_trace_header(class Psip *sip, const char *message, int direction)
 {
@@ -136,6 +153,8 @@ static int rtp_decode(class Psip *psip, unsigned char *data, int len)
        uint8_t *payload;
        int payload_len;
        int x_len;
+       unsigned char *from, *to;
+       int n;
 
        if (len < 12) {
                PDEBUG(DEBUG_SIP, "received RTP frame too short (len = %d)\n", len);
@@ -222,7 +241,12 @@ static int rtp_decode(class Psip *psip, unsigned char *data, int len)
                return 0;
        }
 
-       psip->bchannel_send(PH_DATA_REQ, 0, payload, payload_len);
+       n = payload_len;
+       from = payload;
+       to = payload;
+       while(n--)
+               *to++ = flip[*from++];
+       psip->bridge_tx(payload, payload_len);
 
        return 0;
 }
@@ -319,27 +343,27 @@ int Psip::rtp_open(void)
                rtp_close();
                return -EIO;
        }
-       p_m_s_rtp_fd.fd = rc;
-       register_fd(&p_m_s_rtp_fd, LCR_FD_READ, rtp_sock_callback, this, 0);
+       p_s_rtp_fd.fd = rc;
+       register_fd(&p_s_rtp_fd, LCR_FD_READ, rtp_sock_callback, this, 0);
 
        rc = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (!rc) {
                rtp_close();
                return -EIO;
        }
-       p_m_s_rtcp_fd.fd = rc;
-       register_fd(&p_m_s_rtcp_fd, LCR_FD_READ, rtcp_sock_callback, this, 0);
+       p_s_rtcp_fd.fd = rc;
+       register_fd(&p_s_rtcp_fd, LCR_FD_READ, rtcp_sock_callback, this, 0);
 
        /* bind socket */
        ip = htonl(INADDR_ANY);
        ia.s_addr = ip;
        for (next_udp_port = next_udp_port % 0xffff;
             next_udp_port < 0xffff; next_udp_port += 2) {
-               rc = rtp_sub_socket_bind(p_m_s_rtp_fd.fd, &p_m_s_rtp_sin_local, ip, next_udp_port);
+               rc = rtp_sub_socket_bind(p_s_rtp_fd.fd, &p_s_rtp_sin_local, ip, next_udp_port);
                if (rc != 0)
                        continue;
 
-               rc = rtp_sub_socket_bind(p_m_s_rtcp_fd.fd, &p_m_s_rtcp_sin_local, ip, next_udp_port+1);
+               rc = rtp_sub_socket_bind(p_s_rtcp_fd.fd, &p_s_rtcp_sin_local, ip, next_udp_port+1);
                if (rc == 0)
                        break;
        }
@@ -348,12 +372,12 @@ int Psip::rtp_open(void)
                rtp_close();
                return rc;
        }
-       p_m_s_rtp_port_local = next_udp_port;
-       p_m_s_rtp_ip_local = ntohl(p_m_s_rtp_sin_local.sin_addr.s_addr);
-       PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_m_s_rtp_ip_local, p_m_s_rtp_port_local);
-       PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_m_s_rtp_ip_remote, p_m_s_rtp_port_remote);
+       p_s_rtp_port_local = next_udp_port;
+       p_s_rtp_ip_local = ntohl(p_s_rtp_sin_local.sin_addr.s_addr);
+       PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_s_rtp_ip_local, p_s_rtp_port_local);
+       PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_s_rtp_ip_remote, p_s_rtp_port_remote);
 
-       return p_m_s_rtp_port_local;
+       return p_s_rtp_port_local;
 }
 
 int Psip::rtp_connect(void)
@@ -361,39 +385,39 @@ int Psip::rtp_connect(void)
        int rc;
        struct in_addr ia;
 
-       ia.s_addr = htonl(p_m_s_rtp_ip_remote);
-       PDEBUG(DEBUG_SIP, "rtp_connect(ip=%s, port=%u)\n", inet_ntoa(ia), p_m_s_rtp_port_remote);
+       ia.s_addr = htonl(p_s_rtp_ip_remote);
+       PDEBUG(DEBUG_SIP, "rtp_connect(ip=%s, port=%u)\n", inet_ntoa(ia), p_s_rtp_port_remote);
 
-       rc = rtp_sub_socket_connect(p_m_s_rtp_fd.fd, &p_m_s_rtp_sin_local, &p_m_s_rtp_sin_remote, p_m_s_rtp_ip_remote, p_m_s_rtp_port_remote);
+       rc = rtp_sub_socket_connect(p_s_rtp_fd.fd, &p_s_rtp_sin_local, &p_s_rtp_sin_remote, p_s_rtp_ip_remote, p_s_rtp_port_remote);
        if (rc < 0)
                return rc;
 
-       rc = rtp_sub_socket_connect(p_m_s_rtcp_fd.fd, &p_m_s_rtcp_sin_local, &p_m_s_rtcp_sin_remote, p_m_s_rtp_ip_remote, p_m_s_rtp_port_remote + 1);
+       rc = rtp_sub_socket_connect(p_s_rtcp_fd.fd, &p_s_rtcp_sin_local, &p_s_rtcp_sin_remote, p_s_rtp_ip_remote, p_s_rtp_port_remote + 1);
        if (rc < 0)
                return rc;
 
-       p_m_s_rtp_ip_local = ntohl(p_m_s_rtp_sin_local.sin_addr.s_addr);
-       PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_m_s_rtp_ip_local, p_m_s_rtp_port_local);
-       PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_m_s_rtp_ip_remote, p_m_s_rtp_port_remote);
-       p_m_s_rtp_is_connected = 1;
+       p_s_rtp_ip_local = ntohl(p_s_rtp_sin_local.sin_addr.s_addr);
+       PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_s_rtp_ip_local, p_s_rtp_port_local);
+       PDEBUG(DEBUG_SIP, "remote ip %08x port %d\n", p_s_rtp_ip_remote, p_s_rtp_port_remote);
+       p_s_rtp_is_connected = 1;
 
        return 0;
 }
 void Psip::rtp_close(void)
 {
-       if (p_m_s_rtp_fd.fd > 0) {
-               unregister_fd(&p_m_s_rtp_fd);
-               close(p_m_s_rtp_fd.fd);
-               p_m_s_rtp_fd.fd = 0;
+       if (p_s_rtp_fd.fd > 0) {
+               unregister_fd(&p_s_rtp_fd);
+               close(p_s_rtp_fd.fd);
+               p_s_rtp_fd.fd = 0;
        }
-       if (p_m_s_rtcp_fd.fd > 0) {
-               unregister_fd(&p_m_s_rtcp_fd);
-               close(p_m_s_rtcp_fd.fd);
-               p_m_s_rtcp_fd.fd = 0;
+       if (p_s_rtcp_fd.fd > 0) {
+               unregister_fd(&p_s_rtcp_fd);
+               close(p_s_rtcp_fd.fd);
+               p_s_rtcp_fd.fd = 0;
        }
-       if (p_m_s_rtp_is_connected) {
+       if (p_s_rtp_is_connected) {
                PDEBUG(DEBUG_SIP, "rtp closed\n");
-               p_m_s_rtp_is_connected = 0;
+               p_s_rtp_is_connected = 0;
        }
 }
 
@@ -413,25 +437,25 @@ void tv_difference(struct timeval *diff, const struct timeval *from,
 }
 
 /* encode and send a rtp frame */
-int Psip::rtp_send_frame(unsigned char *data, unsigned int len, int payload_type)
+int Psip::rtp_send_frame(unsigned char *data, unsigned int len, uint8_t payload_type)
 {
        struct rtp_hdr *rtph;
        int payload_len;
        int duration; /* in samples */
        unsigned char buffer[256];
 
-       if (!p_m_s_rtp_is_connected) {
+       if (!p_s_rtp_is_connected) {
                /* drop silently */
                return 0;
        }
 
-       if (!p_m_s_rtp_tx_action) {
+       if (!p_s_rtp_tx_action) {
                /* initialize sequences */
-               p_m_s_rtp_tx_action = 1;
-               p_m_s_rtp_tx_ssrc = rand();
-               p_m_s_rtp_tx_sequence = random();
-               p_m_s_rtp_tx_timestamp = random();
-               memset(&p_m_s_rtp_tx_last_tv, 0, sizeof(p_m_s_rtp_tx_last_tv));
+               p_s_rtp_tx_action = 1;
+               p_s_rtp_tx_ssrc = rand();
+               p_s_rtp_tx_sequence = random();
+               p_s_rtp_tx_timestamp = random();
+               memset(&p_s_rtp_tx_last_tv, 0, sizeof(p_s_rtp_tx_last_tv));
        }
 
        switch (payload_type) {
@@ -459,8 +483,8 @@ int Psip::rtp_send_frame(unsigned char *data, unsigned int len, int payload_type
                long int usec_diff, frame_diff;
 
                gettimeofday(&tv, NULL);
-               tv_difference(&tv_diff, &p_m_s_rtp_tx_last_tv, &tv);
-               p_m_s_rtp_tx_last_tv = tv;
+               tv_difference(&tv_diff, &p_s_rtp_tx_last_tv, &tv);
+               p_s_rtp_tx_last_tv = tv;
 
                usec_diff = tv_diff.tv_sec * 1000000 + tv_diff.tv_usec;
                frame_diff = (usec_diff / 20000);
@@ -469,8 +493,8 @@ int Psip::rtp_send_frame(unsigned char *data, unsigned int len, int payload_type
                        long int frame_diff_excess = frame_diff - 1;
 
                        PDEBUG(DEBUG_SIP, "Correcting frame difference of %ld frames\n", frame_diff_excess);
-                       p_m_s_rtp_tx_sequence += frame_diff_excess;
-                       p_m_s_rtp_tx_timestamp += frame_diff_excess * duration;
+                       p_s_rtp_tx_sequence += frame_diff_excess;
+                       p_s_rtp_tx_timestamp += frame_diff_excess * duration;
                }
        }
 #endif
@@ -482,14 +506,14 @@ int Psip::rtp_send_frame(unsigned char *data, unsigned int len, int payload_type
        rtph->csrc_count = 0;
        rtph->marker = 0;
        rtph->payload_type = payload_type;
-       rtph->sequence = htons(p_m_s_rtp_tx_sequence++);
-       rtph->timestamp = htonl(p_m_s_rtp_tx_timestamp);
-       p_m_s_rtp_tx_timestamp += duration;
-       rtph->ssrc = htonl(p_m_s_rtp_tx_ssrc);
+       rtph->sequence = htons(p_s_rtp_tx_sequence++);
+       rtph->timestamp = htonl(p_s_rtp_tx_timestamp);
+       p_s_rtp_tx_timestamp += duration;
+       rtph->ssrc = htonl(p_s_rtp_tx_ssrc);
        memcpy(buffer + sizeof(struct rtp_hdr), data, payload_len);
 
-       if (p_m_s_rtp_fd.fd > 0) {
-               len = write(p_m_s_rtp_fd.fd, &buffer, sizeof(struct rtp_hdr) + payload_len);
+       if (p_s_rtp_fd.fd > 0) {
+               len = write(p_s_rtp_fd.fd, &buffer, sizeof(struct rtp_hdr) + payload_len);
                if (len != sizeof(struct rtp_hdr) + payload_len) {
                        PDEBUG(DEBUG_SIP, "write result=%d\n", len);
 //                     rtp_close();
@@ -501,147 +525,17 @@ int Psip::rtp_send_frame(unsigned char *data, unsigned int len, int payload_type
        return 0;
 }
 
-/*
- * bchannel handling
- */
-
-/* select free bchannel from loopback interface */
-int Psip::hunt_bchannel(void)
-{
-       return loop_hunt_bchannel(this, p_m_mISDNport);
-}
-
-/* close SIP side bchannel */
-void Psip::bchannel_close(void)
-{
-       if (p_m_s_b_sock > -1) {
-               unregister_fd(&p_m_s_b_fd);
-               close(p_m_s_b_sock);
-       }
-       p_m_s_b_sock = -1;
-       p_m_s_b_index = -1;
-       p_m_s_b_active = 0;
-}
-
-static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index);
-
-/* open external side bchannel */
-int Psip::bchannel_open(int index)
-{
-       int ret;
-       struct sockaddr_mISDN addr;
-       struct mISDNhead act;
-
-       if (p_m_s_b_sock > -1) {
-               PERROR("Socket already created for index %d\n", index);
-               return(-EIO);
-       }
-
-       /* open socket */
-       ret = p_m_s_b_sock = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
-       if (ret < 0) {
-               PERROR("Failed to open bchannel-socket for index %d\n", index);
-               bchannel_close();
-               return(ret);
-       }
-       memset(&p_m_s_b_fd, 0, sizeof(p_m_s_b_fd));
-       p_m_s_b_fd.fd = p_m_s_b_sock;
-       register_fd(&p_m_s_b_fd, LCR_FD_READ, b_handler, this, 0);
-
-
-       /* bind socket to bchannel */
-       addr.family = AF_ISDN;
-       addr.dev = mISDNloop.port;
-       addr.channel = index+1+(index>15);
-       ret = bind(p_m_s_b_sock, (struct sockaddr *)&addr, sizeof(addr));
-       if (ret < 0) {
-               PERROR("Failed to bind bchannel-socket for index %d\n", index);
-               bchannel_close();
-               return(ret);
-       }
-       /* activate bchannel */
-       PDEBUG(DEBUG_SIP, "Activating SIP side channel index %i.\n", index);
-       act.prim = PH_ACTIVATE_REQ; 
-       act.id = 0;
-       ret = sendto(p_m_s_b_sock, &act, MISDN_HEADER_LEN, 0, NULL, 0);
-       if (ret < 0) {
-               PERROR("Failed to activate index %d\n", index);
-               bchannel_close();
-               return(ret);
-       }
-
-       p_m_s_b_index = index;
-
-       return(0);
-}
-
-/* receive from bchannel */
-void Psip::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len)
+/* receive from remote */
+int Psip::bridge_rx(unsigned char *data, int len)
 {
        /* write to rx buffer */
        while(len--) {
-               p_m_s_rxdata[p_m_s_rxpos++] = flip[*data++];
-               if (p_m_s_rxpos == 160) {
-                       p_m_s_rxpos = 0;
+               p_s_rxdata[p_s_rxpos++] = flip[*data++];
+               if (p_s_rxpos == 160) {
+                       p_s_rxpos = 0;
 
                        /* transmit data via rtp */
-                       rtp_send_frame(p_m_s_rxdata, 160, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW);
-               }
-       }
-}
-
-/* transmit to bchannel */
-void Psip::bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len)
-{
-       unsigned char buf[MISDN_HEADER_LEN+len];
-       struct mISDNhead *hh = (struct mISDNhead *)buf;
-       unsigned char *to = buf + MISDN_HEADER_LEN;
-       int n = len;
-       int ret;
-
-       if (!p_m_s_b_active)
-               return;
-
-       /* make and send frame */
-       hh->prim = prim;
-       hh->id = 0;
-       while(n--)
-               *to++ = flip[*data++];
-       ret = sendto(p_m_s_b_sock, buf, MISDN_HEADER_LEN+len, 0, NULL, 0);
-       if (ret <= 0)
-               PERROR("Failed to send to socket index %d\n", p_m_s_b_index);
-}
-
-/* handle socket input */
-static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int index)
-{
-       class Psip *psip = (class Psip *)instance;
-       int ret;
-       unsigned char buffer[2048+MISDN_HEADER_LEN];
-       struct mISDNhead *hh = (struct mISDNhead *)buffer;
-
-       /* handle message from bchannel */
-       if (psip->p_m_s_b_sock > -1) {
-               ret = recv(psip->p_m_s_b_sock, buffer, sizeof(buffer), 0);
-               if (ret >= (int)MISDN_HEADER_LEN) {
-                       switch(hh->prim) {
-                               /* we don't care about confirms, we use rx data to sync tx */
-                               case PH_DATA_CNF:
-                               break;
-                               /* we receive audio data, we respond to it AND we send tones */
-                               case PH_DATA_IND:
-                               psip->bchannel_receive(hh, buffer+MISDN_HEADER_LEN, ret-MISDN_HEADER_LEN);
-                               break;
-                               case PH_ACTIVATE_IND:
-                               psip->p_m_s_b_active = 1;
-                               break;
-                               case PH_DEACTIVATE_IND:
-                               psip->p_m_s_b_active = 0;
-                               break;
-                       }
-               } else {
-                       if (ret < 0 && errno != EWOULDBLOCK)
-                               PERROR("Read from GSM port, index %d failed with return code %d\n", ret);
+                       rtp_send_frame(p_s_rxdata, 160, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW);
                }
        }
 
@@ -827,22 +721,36 @@ int Psip::message_connect(unsigned int epoint_id, int message_id, union paramete
        struct in_addr ia;
        struct lcr_msg *message;
 
-       if (rtp_connect() < 0) {
-               nua_cancel(p_m_s_handle, TAG_END());
-               nua_handle_destroy(p_m_s_handle);
-               p_m_s_handle = NULL;
-               sip_trace_header(this, "CANCEL", DIRECTION_OUT);
-               add_trace("reason", NULL, "failed to connect RTP/RTCP sockts");
-               end_trace();
-               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-               message->param.disconnectinfo.cause = 41;
-               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-               message_put(message);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_s_delete);
-               return 0;
+       if (param->connectinfo.rtpinfo.port) {
+               PDEBUG(DEBUG_SIP, "RTP info given by remote, forward that\n");
+               p_s_rtp_bridge = 1;
+               p_s_rtp_payload_type = param->connectinfo.rtpinfo.payload_type;
+               p_s_rtp_ip_local = param->connectinfo.rtpinfo.ip;
+               p_s_rtp_port_local = param->connectinfo.rtpinfo.port;
+               PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_s_rtp_ip_local, p_s_rtp_port_local);
+               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_payload_type = (options.law=='a') ? RTP_PT_ALAW : RTP_PT_ULAW;
+               /* open local RTP peer (if not bridging) */
+               if (rtp_connect() < 0) {
+                       nua_cancel(p_s_handle, TAG_END());
+                       nua_handle_destroy(p_s_handle);
+                       p_s_handle = NULL;
+                       sip_trace_header(this, "CANCEL", DIRECTION_OUT);
+                       add_trace("reason", NULL, "failed to connect RTP/RTCP sockts");
+                       end_trace();
+                       message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+                       message->param.disconnectinfo.cause = 41;
+                       message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+                       message_put(message);
+                       new_state(PORT_STATE_RELEASE);
+                       trigger_work(&p_s_delete);
+                       return 0;
+               }
        }
-       ia.s_addr = htonl(p_m_s_rtp_ip_local);
+
+       ia.s_addr = htonl(p_s_rtp_ip_local);
 
        SPRINT(sdp_str,
                "v=0\n"
@@ -852,10 +760,10 @@ int Psip::message_connect(unsigned int epoint_id, int message_id, union paramete
                "t=0 0\n"
                "m=audio %d RTP/AVP %d\n"
                "a=rtpmap:%d %s/8000\n"
-               , inet_ntoa(ia), inet_ntoa(ia), p_m_s_rtp_port_local, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW, (options.law=='a')?"PCMA":"PCMU");
+               , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, p_s_rtp_payload_type, p_s_rtp_payload_type, payload_type2name(p_s_rtp_payload_type));
        PDEBUG(DEBUG_SIP, "Using SDP response: %s\n", sdp_str);
 
-       nua_respond(p_m_s_handle, SIP_200_OK,
+       nua_respond(p_s_handle, SIP_200_OK,
                NUTAG_MEDIA_ENABLE(0),
                SIPTAG_CONTENT_TYPE_STR("application/sdp"),
                SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
@@ -890,7 +798,7 @@ int Psip::message_release(unsigned int epoint_id, int message_id, union paramete
                if (cause_str[0])
                        add_trace("cause", "value", "%d", cause);
                end_trace();
-               nua_cancel(p_m_s_handle, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
+               nua_cancel(p_s_handle, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
                break;
        case PORT_STATE_IN_SETUP:
        case PORT_STATE_IN_PROCEEDING:
@@ -902,10 +810,10 @@ int Psip::message_release(unsigned int epoint_id, int message_id, union paramete
                        add_trace("cause", "value", "%d", cause);
                add_trace("respond", "value", "%d %s", status, status_text);
                end_trace();
-               nua_respond(p_m_s_handle, status, status_text, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
-               nua_handle_destroy(p_m_s_handle);
-               p_m_s_handle = NULL;
-               trigger_work(&p_m_s_delete);
+               nua_respond(p_s_handle, status, status_text, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
+               nua_handle_destroy(p_s_handle);
+               p_s_handle = NULL;
+               trigger_work(&p_s_delete);
                break;
        default:
                PDEBUG(DEBUG_SIP, "RELEASE/DISCONNECT will perform nua_bye\n");
@@ -913,7 +821,7 @@ int Psip::message_release(unsigned int epoint_id, int message_id, union paramete
                if (cause_str[0])
                        add_trace("cause", "value", "%d", cause);
                end_trace();
-               nua_bye(p_m_s_handle, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
+               nua_bye(p_s_handle, TAG_IF(cause_str[0], SIPTAG_REASON_STR(cause_str)), TAG_END());
        }
 
        if (message_id == MESSAGE_DISCONNECT) {
@@ -934,78 +842,48 @@ int Psip::message_release(unsigned int epoint_id, int message_id, union paramete
 
 int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter *param)
 {
-       struct sip_inst *inst = (struct sip_inst *) p_m_s_sip_inst;
+       struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
        char from[128];
        char to[128];
-       const char *local = inst->interface->sip_local_ip;
-       const char *remote = inst->interface->sip_remote_ip;
+       const char *local = inst->local_ip;
+       const char *remote = inst->remote_ip;
        char sdp_str[256];
        struct in_addr ia;
        struct epoint_list *epointlist;
        sip_cseq_t *cseq = NULL;
-       int ret;
-       int channel;
 
        PDEBUG(DEBUG_SIP, "Doing Setup (inst %p)\n", inst);
 
-       /* release if port is blocked */
-       if (p_m_mISDNport->ifport->block) {
-               struct lcr_msg *message;
-
-               sip_trace_header(this, "INVITE", DIRECTION_OUT);
-               add_trace("failure", NULL, "Port blocked.");
-               end_trace();
-               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-               message->param.disconnectinfo.cause = 27; // temp. unavail.
-               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-               message_put(message);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_s_delete);
-               return 0;
-       }
-
-       /* hunt channel */
-       ret = channel = hunt_bchannel();
-       if (ret < 0)
-               goto no_channel;
-       /* open channel */
-       ret = seize_bchannel(channel, 1);
-       if (ret < 0) {
-               struct lcr_msg *message;
-
-               no_channel:
-               sip_trace_header(this, "INVITE", DIRECTION_OUT);
-               add_trace("failure", NULL, "No internal audio channel available.");
-               end_trace();
-               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);
-               trigger_work(&p_m_s_delete);
-               return 0;
-       }
-       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-       if (bchannel_open(p_m_b_index))
-               goto no_channel;
-
        memcpy(&p_dialinginfo, &param->setup.dialinginfo, sizeof(p_dialinginfo));
        memcpy(&p_callerinfo, &param->setup.callerinfo, sizeof(p_callerinfo));
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
 
-       /* connect to remote RTP */
-       if (rtp_open() < 0) {
-               struct lcr_msg *message;
-
-               PERROR("Failed to open RTP sockets\n");
-               /* send release message to endpoit */
-               message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-               message->param.disconnectinfo.cause = 41;
-               message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-               message_put(message);
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_s_delete);
-               return 0;
+       if (param->setup.rtpinfo.port) {
+               PDEBUG(DEBUG_SIP, "RTP info given by remote, forward that\n");
+               p_s_rtp_bridge = 1;
+               p_s_rtp_payload_type = param->setup.rtpinfo.payload_type;
+               p_s_rtp_ip_local = param->setup.rtpinfo.ip;
+               p_s_rtp_port_local = param->setup.rtpinfo.port;
+               PDEBUG(DEBUG_SIP, "local ip %08x port %d\n", p_s_rtp_ip_local, p_s_rtp_port_local);
+               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_payload_type = (options.law=='a') ? RTP_PT_ALAW : RTP_PT_ULAW;
+
+               /* open local RTP peer (if not bridging) */
+               if (rtp_open() < 0) {
+                       struct lcr_msg *message;
+
+                       PERROR("Failed to open RTP sockets\n");
+                       /* send release message to endpoit */
+                       message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
+                       message->param.disconnectinfo.cause = 41;
+                       message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
+                       message_put(message);
+                       new_state(PORT_STATE_RELEASE);
+                       trigger_work(&p_s_delete);
+                       return 0;
+               }
        }
        SPRINT(from, "sip:%s@%s", param->setup.callerinfo.id, local);
        SPRINT(to, "sip:%s@%s", param->setup.dialinginfo.id, remote);
@@ -1013,11 +891,11 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
        sip_trace_header(this, "INVITE", DIRECTION_OUT);
        add_trace("from", "uri", "%s", from);
        add_trace("to", "uri", "%s", to);
-       add_trace("rtp", "port", "%d,%d", p_m_s_rtp_port_local, p_m_s_rtp_port_local + 1);
+       add_trace("rtp", "port", "%d,%d", p_s_rtp_port_local, p_s_rtp_port_local + 1);
        end_trace();
 
-       p_m_s_handle = nua_handle(inst->nua, NULL, TAG_END());
-       if (!p_m_s_handle) {
+       p_s_handle = nua_handle(inst->nua, NULL, TAG_END());
+       if (!p_s_handle) {
                struct lcr_msg *message;
 
                PERROR("Failed to create handle\n");
@@ -1027,17 +905,20 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_s_delete);
+               trigger_work(&p_s_delete);
                return 0;
        }
        /* apply handle */
        sip_trace_header(this, "NEW handle", DIRECTION_IN);
-       add_trace("handle", "new", "0x%x", p_m_s_handle);
+       add_trace("handle", "new", "0x%x", p_s_handle);
        end_trace();
 
-       inet_pton(AF_INET, local, &p_m_s_rtp_ip_local);
-       p_m_s_rtp_ip_local = ntohl(p_m_s_rtp_ip_local);
-       ia.s_addr = htonl(p_m_s_rtp_ip_local);
+       if (!p_s_rtp_ip_local) {
+               PDEBUG(DEBUG_SIP, "RTP local IP not known, so we use our local SIP ip %s\n", local);
+               inet_pton(AF_INET, local, &p_s_rtp_ip_local);
+               p_s_rtp_ip_local = ntohl(p_s_rtp_ip_local);
+       }
+       ia.s_addr = htonl(p_s_rtp_ip_local);
        SPRINT(sdp_str,
                "v=0\n"
                "o=LCR-Sofia-SIP 0 0 IN IP4 %s\n"
@@ -1046,12 +927,12 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
                "t=0 0\n"
                "m=audio %d RTP/AVP %d\n"
                "a=rtpmap:%d %s/8000\n"
-               , inet_ntoa(ia), inet_ntoa(ia), p_m_s_rtp_port_local, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW, (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW, (options.law=='a')?"PCMA":"PCMU");
+               , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, p_s_rtp_payload_type, p_s_rtp_payload_type, payload_type2name(p_s_rtp_payload_type));
        PDEBUG(DEBUG_SIP, "Using SDP for invite: %s\n", sdp_str);
 
 //     cseq = sip_cseq_create(sip_home, 123, SIP_METHOD_INVITE);
 
-       nua_invite(p_m_s_handle,
+       nua_invite(p_s_handle,
                TAG_IF(from[0], SIPTAG_FROM_STR(from)),
                TAG_IF(to[0], SIPTAG_TO_STR(to)),
                TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
@@ -1073,11 +954,82 @@ int Psip::message_setup(unsigned int epoint_id, int message_id, union parameter
        return 0;
 }
        
+int Psip::message_notify(unsigned int epoint_id, int message_id, union parameter *param)
+{
+//     char sdp_str[256];
+//     struct in_addr ia;
+
+       switch (param->notifyinfo.notify) {
+       case INFO_NOTIFY_REMOTE_HOLD:
+#if 0
+               SPRINT(sdp_str,
+                       "v=0\n"
+                       "o=LCR-Sofia-SIP 0 0 IN IP4 0.0.0.0\n"
+                       "s=SIP Call\n"
+                       "c=IN IP4 0.0.0.0\n"
+                       "t=0 0\n"
+                       );
+               PDEBUG(DEBUG_SIP, "Using SDP for hold: %s\n", sdp_str);
+               nua_info(p_s_handle,
+//                     TAG_IF(from[0], SIPTAG_FROM_STR(from)),
+//                     TAG_IF(to[0], SIPTAG_TO_STR(to)),
+//                     TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
+                       NUTAG_MEDIA_ENABLE(0),
+                       SIPTAG_CONTENT_TYPE_STR("application/sdp"),
+                       SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
+#endif
+               break;
+       case INFO_NOTIFY_REMOTE_RETRIEVAL:
+#if 0
+               ia.s_addr = htonl(p_s_rtp_ip_local);
+               SPRINT(sdp_str,
+                       "v=0\n"
+                       "o=LCR-Sofia-SIP 0 0 IN IP4 %s\n"
+                       "s=SIP Call\n"
+                       "c=IN IP4 %s\n"
+                       "t=0 0\n"
+                       "m=audio %d RTP/AVP %d\n"
+                       "a=rtpmap:%d %s/8000\n"
+                       , inet_ntoa(ia), inet_ntoa(ia), p_s_rtp_port_local, p_s_rtp_payload_type, p_s_rtp_payload_type, payload_type2name(p_s_rtp_payload_type));
+               PDEBUG(DEBUG_SIP, "Using SDP for rertieve: %s\n", sdp_str);
+               nua_info(p_s_handle,
+//                     TAG_IF(from[0], SIPTAG_FROM_STR(from)),
+//                     TAG_IF(to[0], SIPTAG_TO_STR(to)),
+//                     TAG_IF(cseq, SIPTAG_CSEQ(cseq)),
+                       NUTAG_MEDIA_ENABLE(0),
+                       SIPTAG_CONTENT_TYPE_STR("application/sdp"),
+                       SIPTAG_PAYLOAD_STR(sdp_str), TAG_END());
+#endif
+               break;
+       }
+
+       return 0;
+}
+
+int Psip::message_dtmf(unsigned int epoint_id, int message_id, union parameter *param)
+{
+       char dtmf_str[64];
+       
+       /* prepare DTMF info payload */
+       SPRINT(dtmf_str,
+               "Signal=%c\n"
+               "Duration=160\n"
+               , param->dtmf);
+
+       /* start invite to handle DTMF */
+       nua_info(p_s_handle,
+               NUTAG_MEDIA_ENABLE(0),
+               SIPTAG_CONTENT_TYPE_STR("application/dtmf-relay"),
+               SIPTAG_PAYLOAD_STR(dtmf_str), TAG_END());
+       
+       return 0;
+}
+
 int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter *param)
 {
        class Endpoint *epoint;
 
-       if (PmISDN::message_epoint(epoint_id, message_id, param))
+       if (Port::message_epoint(epoint_id, message_id, param))
                return 1;
 
        epoint = find_epoint_id(epoint_id);
@@ -1091,7 +1043,7 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
                if (p_state != PORT_STATE_IN_SETUP
                 && p_state != PORT_STATE_IN_PROCEEDING)
                        return 0;
-               nua_respond(p_m_s_handle, SIP_180_RINGING, TAG_END());
+               nua_respond(p_s_handle, SIP_180_RINGING, TAG_END());
                sip_trace_header(this, "RESPOND", DIRECTION_OUT);
                add_trace("respond", "value", "180 Ringing");
                end_trace();
@@ -1115,6 +1067,14 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
                message_setup(epoint_id, message_id, param);
                return 1;
 
+               case MESSAGE_DTMF: /* DTMF info to be transmitted via INFO transaction */
+               if (p_state == PORT_STATE_CONNECT)
+                       message_dtmf(epoint_id, message_id, param);
+               case MESSAGE_NOTIFY: /* notification about remote hold/retrieve */
+               if (p_state == PORT_STATE_CONNECT)
+                       message_notify(epoint_id, message_id, param);
+               return(1);
+
                default:
                PDEBUG(DEBUG_SIP, "PORT(%s) SP port with (caller id %s) received an unsupported message: %d\n", p_name, p_callerinfo.id, message_id);
        }
@@ -1122,7 +1082,7 @@ int Psip::message_epoint(unsigned int epoint_id, int message_id, union parameter
        return 0;
 }
 
-int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port)
+int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port, uint8_t payload_type)
 {
        int codec_supported = 0;
 
@@ -1162,7 +1122,7 @@ int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port)
                        conn = m->m_connections;
                        PDEBUG(DEBUG_SIP, "CONN: address:'%s'\n", conn->c_address);
                        inet_pton(AF_INET, conn->c_address, ip);
-                       *ip = ntohl(p_m_s_rtp_ip_remote);
+                       *ip = ntohl(p_s_rtp_ip_remote);
                } else {
                        char *p = sip->sip_payload->pl_data;
                        char addr[16];
@@ -1179,11 +1139,11 @@ int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port)
                        if ((p = strchr(addr, '\r'))) *p = '\0';
                        PDEBUG(DEBUG_SIP, "CONN: address:'%s'\n", addr);
                        inet_pton(AF_INET, addr, ip);
-                       *ip = ntohl(p_m_s_rtp_ip_remote);
+                       *ip = ntohl(p_s_rtp_ip_remote);
                }
                for (map = m->m_rtpmaps; map; map = map->rm_next) {
-                       PDEBUG(DEBUG_SIP, "RTPMAP: coding:'%s' rate='%d'\n", map->rm_encoding, map->rm_rate);
-                       if (!strcmp(map->rm_encoding, (options.law=='a')?"PCMA":"PCMU") && map->rm_rate == 8000) {
+                       PDEBUG(DEBUG_SIP, "RTPMAP: coding:'%s' rate='%d' pt='%d'\n", map->rm_encoding, map->rm_rate, map->rm_pt);
+                       if (map->rm_pt == payload_type) {
                                PDEBUG(DEBUG_SIP, "supported codec found\n");
                                codec_supported = 1;
                                goto done_codec;
@@ -1202,11 +1162,12 @@ int Psip::parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port)
 
 void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
 {
+       struct sip_inst *inst = (struct sip_inst *) p_s_sip_inst;
        const char *from = "", *to = "";
        int ret;
        class Endpoint *epoint;
        struct lcr_msg *message;
-       int channel;
+       uint8_t payload_type;
 
        if (sip->sip_from && sip->sip_from->a_url)
                from = sip->sip_from->a_url->url_user;
@@ -1214,14 +1175,18 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                to = sip->sip_to->a_url->url_user;
        PDEBUG(DEBUG_SIP, "invite received (%s->%s)\n", from, to);
 
-       ret = parse_sdp(sip, &p_m_s_rtp_ip_remote, &p_m_s_rtp_port_remote);
+       if (p_s_rtp_bridge)
+               payload_type = 3; // FIXME: use list and forward list to remote side
+       else
+               payload_type = (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW;
+       ret = parse_sdp(sip, &p_s_rtp_ip_remote, &p_s_rtp_port_remote, payload_type);
        if (ret) {
                if (ret == 400)
                        nua_respond(nh, SIP_400_BAD_REQUEST, TAG_END());
                else
                        nua_respond(nh, SIP_415_UNSUPPORTED_MEDIA, TAG_END());
                nua_handle_destroy(nh);
-               p_m_s_handle = NULL;
+               p_s_handle = NULL;
                sip_trace_header(this, "RESPOND", DIRECTION_OUT);
                if (ret == 400)
                        add_trace("respond", "value", "415 Unsupported Media");
@@ -1230,45 +1195,32 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                add_trace("reason", NULL, "offered codec does not match");
                end_trace();
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_s_delete);
+               trigger_work(&p_s_delete);
                return;
        }
 
-       /* connect to remote RTP */
-       if (rtp_open() < 0) {
+       /* open local RTP peer (if not bridging) */
+       if (!p_s_rtp_bridge && rtp_open() < 0) {
                nua_respond(nh, SIP_500_INTERNAL_SERVER_ERROR, TAG_END());
                nua_handle_destroy(nh);
-               p_m_s_handle = NULL;
+               p_s_handle = NULL;
                sip_trace_header(this, "RESPOND", DIRECTION_OUT);
                add_trace("respond", "value", "500 Internal Server Error");
                add_trace("reason", NULL, "failed to open RTP/RTCP sockts");
                end_trace();
                new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_s_delete);
+               trigger_work(&p_s_delete);
                return;
        }
 
        /* apply handle */
        sip_trace_header(this, "NEW handle", DIRECTION_IN);
        add_trace("handle", "new", "0x%x", nh);
-       p_m_s_handle = nh;
+       p_s_handle = nh;
        end_trace();
 
-       /* if blocked, release call */
-       if (p_m_mISDNport->ifport->block) {
-               nua_respond(nh, SIP_503_SERVICE_UNAVAILABLE, TAG_END());
-               nua_handle_destroy(nh);
-               p_m_s_handle = NULL;
-               sip_trace_header(this, "RESPOND", DIRECTION_OUT);
-               add_trace("respond", "value", "503 Service Unavailable");
-               add_trace("reason", NULL, "port is blocked");
-               end_trace();
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_s_delete);
-               return;
-       }
        sip_trace_header(this, "INVITE", DIRECTION_IN);
-       add_trace("RTP", "port", "%d", p_m_s_rtp_port_remote);
+       add_trace("RTP", "port", "%d", p_s_rtp_port_remote);
        /* caller information */
        if (!from[0]) {
                p_callerinfo.present = INFO_PRESENT_NOTAVAIL;
@@ -1282,8 +1234,7 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                SCPY(p_callerinfo.id, from);
                add_trace("calling", "number", "%s", from);
        }
-       p_callerinfo.isdn_port = p_m_portnum;
-       SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name);
+       SCPY(p_callerinfo.interface, inst->interface_name);
        /* dialing information */
        if (to[0]) {
                p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN;
@@ -1302,30 +1253,6 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
 
        end_trace();
 
-       /* hunt channel */
-       ret = channel = hunt_bchannel();
-       if (ret < 0)
-               goto no_channel;
-
-       /* open channel */
-       ret = seize_bchannel(channel, 1);
-       if (ret < 0) {
-               no_channel:
-               nua_respond(nh, SIP_480_TEMPORARILY_UNAVAILABLE, TAG_END());
-               nua_handle_destroy(nh);
-               p_m_s_handle = NULL;
-               sip_trace_header(this, "RESPOND", DIRECTION_OUT);
-               add_trace("respond", "value", "480 Temporarily Unavailable");
-               add_trace("reason", NULL, "no channel");
-               end_trace();
-               new_state(PORT_STATE_RELEASE);
-               trigger_work(&p_m_s_delete);
-               return;
-       }
-       bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE);
-       if (bchannel_open(p_m_b_index))
-               goto no_channel;
-
        /* create endpoint */
        if (p_epointlist)
                FATAL("Incoming call but already got an endpoint.\n");
@@ -1345,7 +1272,6 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
 
        /* send setup message to endpoit */
        message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP);
-       message->param.setup.isdn_port = p_m_portnum;
        message->param.setup.port_type = p_type;
 //     message->param.setup.dtmf = 0;
        memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info));
@@ -1354,6 +1280,12 @@ void Psip::i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
 //     SCPY((char *)message->param.setup.useruser.data, useruser.info);
 //     message->param.setup.useruser.len = strlen(mncc->useruser.info);
 //     message->param.setup.useruser.protocol = mncc->useruser.proto;
+       if (p_s_rtp_bridge) {
+               PDEBUG(DEBUG_SIP, "sending setup with RTP info\n");
+               message->param.setup.rtpinfo.payload_type = payload_type;
+               message->param.setup.rtpinfo.ip = p_s_rtp_ip_remote;
+               message->param.setup.rtpinfo.port = p_s_rtp_port_remote;
+       }
        message_put(message);
 }
 
@@ -1377,7 +1309,7 @@ void Psip::i_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic,
        add_trace("respond", "value", "200 OK");
        end_trace();
 //     nua_handle_destroy(nh);
-       p_m_s_handle = NULL;
+       p_s_handle = NULL;
 
        rtp_close();
 
@@ -1391,7 +1323,7 @@ void Psip::i_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic,
                free_epointlist(p_epointlist);
        }
        new_state(PORT_STATE_RELEASE);
-       trigger_work(&p_m_s_delete);
+       trigger_work(&p_s_delete);
 }
 
 void Psip::i_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
@@ -1404,7 +1336,7 @@ void Psip::i_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        end_trace();
 
        nua_handle_destroy(nh);
-       p_m_s_handle = NULL;
+       p_s_handle = NULL;
 
        rtp_close();
 
@@ -1418,7 +1350,7 @@ void Psip::i_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                free_epointlist(p_epointlist);
        }
        new_state(PORT_STATE_RELEASE);
-       trigger_work(&p_m_s_delete);
+       trigger_work(&p_s_delete);
 }
 
 void Psip::r_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
@@ -1426,11 +1358,11 @@ void Psip::r_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic,
        PDEBUG(DEBUG_SIP, "bye response received\n");
 
        nua_handle_destroy(nh);
-       p_m_s_handle = NULL;
+       p_s_handle = NULL;
 
        rtp_close();
 
-       trigger_work(&p_m_s_delete);
+       trigger_work(&p_s_delete);
 }
 
 void Psip::r_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
@@ -1438,11 +1370,11 @@ void Psip::r_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        PDEBUG(DEBUG_SIP, "cancel response received\n");
 
        nua_handle_destroy(nh);
-       p_m_s_handle = NULL;
+       p_s_handle = NULL;
 
        rtp_close();
 
-       trigger_work(&p_m_s_delete);
+       trigger_work(&p_s_delete);
 }
 
 void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tagss[])
@@ -1456,33 +1388,16 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
        add_trace("respond", "value", "%d", status);
        end_trace();
 
-       /* process 1xx */
-       switch (status) {
-       case 100:
-               PDEBUG(DEBUG_SIP, "do proceeding\n");
-               new_state(PORT_STATE_OUT_PROCEEDING);
-               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
-               message_put(message);
-               return;
-       case 180:
-               PDEBUG(DEBUG_SIP, "do alerting\n");
-               new_state(PORT_STATE_OUT_ALERTING);
-               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
-               message_put(message);
-               return;
-       default:
-               if (status < 100 || status > 199)
-                       break;
-               PDEBUG(DEBUG_SIP, "skipping 1xx message\n");
-
-               return;
-       }
-
-       /* process 2xx */
-       if (status >= 200 && status <= 299) {
+       /* connect audio */
+       if (status == 183 || (status >= 200 && status <= 299)) {
                int ret;
+               uint8_t payload_type;
 
-               ret = parse_sdp(sip, &p_m_s_rtp_ip_remote, &p_m_s_rtp_port_remote);
+               if (p_s_rtp_bridge)
+                       payload_type = p_s_rtp_payload_type;
+               else
+                       payload_type = (options.law=='a')?RTP_PT_ALAW:RTP_PT_ULAW;
+               ret = parse_sdp(sip, &p_s_rtp_ip_remote, &p_s_rtp_port_remote, payload_type);
                if (ret) {
                        if (ret == 400)
                                nua_cancel(nh, TAG_END());
@@ -1496,8 +1411,8 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                        goto release_with_cause;
                }
 
-               /* connect to remote RTP */
-               if (rtp_connect() < 0) {
+               /* connect to remote RTP (if not bridging) */
+               if (!p_s_rtp_bridge && rtp_connect() < 0) {
                        nua_cancel(nh, TAG_END());
                        sip_trace_header(this, "CANCEL", DIRECTION_OUT);
                        add_trace("reason", NULL, "failed to open RTP/RTCP sockts");
@@ -1506,16 +1421,56 @@ void Psip::r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *mag
                        location = LOCATION_PRIVATE_LOCAL;
                        goto release_with_cause;
                }
+       }
+
+       /* process 1xx */
+       switch (status) {
+       case 100:
+               PDEBUG(DEBUG_SIP, "do proceeding\n");
+               new_state(PORT_STATE_OUT_PROCEEDING);
+               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING);
+               message_put(message);
+               return;
+       case 180:
+               PDEBUG(DEBUG_SIP, "do alerting\n");
+               new_state(PORT_STATE_OUT_ALERTING);
+               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_ALERTING);
+               message_put(message);
+               return;
+       case 183:
+               PDEBUG(DEBUG_SIP, "do progress\n");
+               message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROGRESS);
+               message->param.progressinfo.progress = 8;
+               message->param.progressinfo.location = 10;
+               if (p_s_rtp_bridge) {
+                       message->param.progressinfo.rtpinfo.payload_type = p_s_rtp_payload_type;
+                       message->param.progressinfo.rtpinfo.ip = p_s_rtp_ip_remote;
+                       message->param.progressinfo.rtpinfo.port = p_s_rtp_port_remote;
+               }
+               message_put(message);
+               return;
+       default:
+               if (status < 100 || status > 199)
+                       break;
+               PDEBUG(DEBUG_SIP, "skipping 1xx message\n");
 
+               return;
+       }
+
+       /* process 2xx */
+       if (status >= 200 && status <= 299) {
                PDEBUG(DEBUG_SIP, "do connect\n");
                nua_ack(nh, TAG_END());
                new_state(PORT_STATE_CONNECT);
                message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
+               if (p_s_rtp_bridge) {
+                       message->param.connectinfo.rtpinfo.payload_type = p_s_rtp_payload_type;
+                       message->param.connectinfo.rtpinfo.ip = p_s_rtp_ip_remote;
+                       message->param.connectinfo.rtpinfo.port = p_s_rtp_port_remote;
+               }
                message_put(message);
-
                return;
        }
-
        cause = status2cause(status);
        location = LOCATION_BEYOND;
 
@@ -1536,7 +1491,7 @@ release_with_cause:
 
        rtp_close();
 
-       trigger_work(&p_m_s_delete);
+       trigger_work(&p_s_delete);
 }
 
 static void sip_callback(nua_event_t event, int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[])
@@ -1553,16 +1508,27 @@ static void sip_callback(nua_event_t event, int status, char const *phrase, nua_
        if (event == nua_i_invite)
        {
                char name[64];
+               struct interface *interface = interface_first;
+
                /* create call instance */
-               SPRINT(name, "%s-%d-in", inst->interface->name, 0);
-               if (!(psip = new Psip(PORT_TYPE_SIP_IN, (inst->interface->ifport) ? inst->interface->ifport->mISDNport : NULL, name, NULL, 0, 0, B_MODE_TRANSPARENT, inst->interface)))
+               SPRINT(name, "%s-%d-in", inst->interface_name, 0);
+               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 (!(psip = new Psip(PORT_TYPE_SIP_IN, name, NULL, interface)))
                        FATAL("Cannot create Port instance.\n");
        } else {
                port = port_first;
                while(port) {
                        if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_SIP) {
                                psip = (class Psip *)port;
-                               if (psip->p_m_s_handle == nh) {
+                               if (psip->p_s_handle == nh) {
                                        break;
                                }
                        }
@@ -1631,8 +1597,8 @@ void Psip::rtp_shutdown(void)
        sip_trace_header(this, "RTP terminated", DIRECTION_IN);
        end_trace();
 
-       nua_handle_destroy(p_m_s_handle);
-       p_m_s_handle = NULL;
+       nua_handle_destroy(p_s_handle);
+       p_s_handle = NULL;
 
        while(p_epointlist) {
                /* send setup message to endpoit */
@@ -1644,7 +1610,7 @@ void Psip::rtp_shutdown(void)
                free_epointlist(p_epointlist);
        }
        new_state(PORT_STATE_RELEASE);
-       trigger_work(&p_m_s_delete);
+       trigger_work(&p_s_delete);
 }
 
 int sip_init_inst(struct interface *interface)
@@ -1652,7 +1618,9 @@ int sip_init_inst(struct interface *interface)
        struct sip_inst *inst = (struct sip_inst *) MALLOC(sizeof(*inst));
 
        interface->sip_inst = inst;
-       inst->interface = interface;
+       SCPY(inst->interface_name, interface->name);
+       SCPY(inst->local_ip, interface->sip_local_ip);
+       SCPY(inst->remote_ip, interface->sip_remote_ip);
 
        /* init root object */
        inst->root = su_root_create(inst);
diff --git a/sip.h b/sip.h
index 1bc06f7..2cfc62d 100644 (file)
--- a/sip.h
+++ b/sip.h
 #include <sofia-sip/nua.h>
 
 /* SIP port class */
-class Psip : public PmISDN
+class Psip : public Port
 {
        public:
-       Psip(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode, struct interface *interface);
+       Psip(int type, char *portname, struct port_settings *settings, struct interface *interface);
        ~Psip();
        int message_epoint(unsigned int epoint_id, int message, union parameter *param);
        int message_connect(unsigned int epoint_id, int message, union parameter *param);
        int message_release(unsigned int epoint_id, int message, union parameter *param);
        int message_setup(unsigned int epoint_id, int message, union parameter *param);
+       int message_notify(unsigned int epoint_id, int message, union parameter *param);
+       int message_dtmf(unsigned int epoint_id, int message, union parameter *param);
        void i_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
        void i_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
        void i_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
        void r_bye(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
        void r_cancel(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
        void r_invite(int status, char const *phrase, nua_t *nua, nua_magic_t *magic, nua_handle_t *nh, nua_hmagic_t *hmagic, sip_t const *sip, tagi_t tags[]);
-       void *p_m_s_sip_inst;
-       struct lcr_work p_m_s_delete;
-       nua_handle_t *p_m_s_handle;
-       nua_magic_t *p_m_s_magic;
-       unsigned short p_m_s_rtp_port_local;
-       unsigned short p_m_s_rtp_port_remote;
-       unsigned int p_m_s_rtp_ip_local;
-       unsigned int p_m_s_rtp_ip_remote;
-       struct sockaddr_in p_m_s_rtp_sin_local;
-       struct sockaddr_in p_m_s_rtp_sin_remote;
-       struct sockaddr_in p_m_s_rtcp_sin_local;
-       struct sockaddr_in p_m_s_rtcp_sin_remote;
-       struct lcr_fd p_m_s_rtp_fd;
-       struct lcr_fd p_m_s_rtcp_fd;
-       int p_m_s_rtp_is_connected; /* if RTP session is connected, so we may send frames */
-       int p_m_s_rtp_tx_action;
-       uint16_t p_m_s_rtp_tx_sequence;
-       uint32_t p_m_s_rtp_tx_timestamp;
-       uint32_t p_m_s_rtp_tx_ssrc;
-       struct timeval p_m_s_rtp_tx_last_tv;
+       void *p_s_sip_inst;
+       struct lcr_work p_s_delete;
+       nua_handle_t *p_s_handle;
+       nua_magic_t *p_s_magic;
+       int p_s_rtp_bridge; /* bridge RTP instead of having a local RTP peer */
+       uint8_t p_s_rtp_payload_type;
+       unsigned short p_s_rtp_port_local;
+       unsigned short p_s_rtp_port_remote;
+       unsigned int p_s_rtp_ip_local;
+       unsigned int p_s_rtp_ip_remote;
+       struct sockaddr_in p_s_rtp_sin_local;
+       struct sockaddr_in p_s_rtp_sin_remote;
+       struct sockaddr_in p_s_rtcp_sin_local;
+       struct sockaddr_in p_s_rtcp_sin_remote;
+       struct lcr_fd p_s_rtp_fd;
+       struct lcr_fd p_s_rtcp_fd;
+       int p_s_rtp_is_connected; /* if RTP session is connected, so we may send frames */
+       int p_s_rtp_tx_action;
+       uint16_t p_s_rtp_tx_sequence;
+       uint32_t p_s_rtp_tx_timestamp;
+       uint32_t p_s_rtp_tx_ssrc;
+       struct timeval p_s_rtp_tx_last_tv;
        int rtp_open(void);
        int rtp_connect(void);
        void rtp_close(void);
-       int rtp_send_frame(unsigned char *data, unsigned int len, int payload_type);
-       int p_m_s_b_sock; /* SIP bchannel socket */
-       struct lcr_fd p_m_s_b_fd; /* event node */
-       int p_m_s_b_index; /* SIP bchannel socket index to use */
-       int p_m_s_b_active; /* SIP bchannel socket is activated */
-       unsigned char p_m_s_rxdata[160]; /* receive audio buffer */
-       int p_m_s_rxpos; /* position in audio buffer 0..159 */
-       int hunt_bchannel(void);
-       void bchannel_close(void);
-       int bchannel_open(int);
-       void bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len);
-       void bchannel_send(unsigned int prim, unsigned int id, unsigned char *data, int len);
-       int parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port);
+       int rtp_send_frame(unsigned char *data, unsigned int len, uint8_t payload_type);
+       int p_s_b_sock; /* SIP bchannel socket */
+       struct lcr_fd p_s_b_fd; /* event node */
+       int p_s_b_index; /* SIP bchannel socket index to use */
+       int p_s_b_active; /* SIP bchannel socket is activated */
+       unsigned char p_s_rxdata[160]; /* receive audio buffer */
+       int p_s_rxpos; /* position in audio buffer 0..159 */
+       int bridge_rx(unsigned char *data, int len);
+       int parse_sdp(sip_t const *sip, unsigned int *ip, unsigned short *port, uint8_t payload_type);
        void rtp_shutdown(void);
 };
 
index 9a774b6..2fba2eb 100644 (file)
@@ -844,6 +844,8 @@ int admin_state(struct admin_queue **responsep)
        interface = interface_first;
        while(interface) {
                ifport = interface->ifport;
+               if (!ifport)
+                       i++;
                while(ifport) {
                        i++;
                        ifport = ifport->next;
@@ -905,6 +907,18 @@ int admin_state(struct admin_queue **responsep)
        num = 0;
        while(interface) {
                ifport = interface->ifport;
+               if (!ifport) {
+                       /* message */
+                       response->am[num].message = ADMIN_RESPONSE_S_INTERFACE;
+                       /* interface */
+                       SCPY(response->am[num].u.i.interface_name, interface->name);
+                       /* portnum */
+                       response->am[num].u.i.portnum = -100; /* indicate: no ifport */
+                       /* iftype */
+                       response->am[num].u.i.extension = interface->extension;
+                       /* block */
+                       num++;
+               }
                while(ifport) {
                        /* message */
                        response->am[num].message = ADMIN_RESPONSE_S_INTERFACE;
diff --git a/ss5.cpp b/ss5.cpp
index 09f97eb..a12f936 100644 (file)
--- a/ss5.cpp
+++ b/ss5.cpp
@@ -1740,8 +1740,8 @@ void Pss5::message_setup(unsigned int epoint_id, int message_id, union parameter
        memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
        /* screen outgoing caller id */
-       do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface);
-       do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface);
+       do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface->name);
+       do_screen(1, p_callerinfo.id2, sizeof(p_callerinfo.id2), &p_callerinfo.ntype2, &p_callerinfo.present2, p_m_mISDNport->ifport->interface->name);
 
        /* parse dial string  */
        dash = 0; /* dash must be used next time */