Support of GSM uses socket interface for both network and mobile
authorAndreas Eversberg <jolly@eversberg.eu>
Fri, 2 Sep 2011 09:08:56 +0000 (11:08 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Fri, 2 Sep 2011 09:08:56 +0000 (11:08 +0200)
There is no linking of any osmocomBB source code required. In order
to use osmocomBB or OpenBSC, just enable the interface, as described
in defaults/interface.conf. At osmocomBB/mobile or at OpenBSC, just
use the option "-m" to enable the socket interface.

Enable GSM at LCR with "./configure --with-gsm-ms --with-gsm-bs".

15 files changed:
Makefile.am
configure.ac
default/openbsc.cfg [deleted file]
default/options.conf
gsm.cpp
gsm.h
gsm_bs.cpp
gsm_bs.h
gsm_ms.cpp
gsm_ms.h
interface.c
main.c
mncc.h [new file with mode: 0644]
options.c
options.h

index 0da7bb0..61ddb8c 100644 (file)
@@ -62,7 +62,7 @@ endif
 
 if ENABLE_GSM_BS
 
 
 if ENABLE_GSM_BS
 
-GSM_INCLUDE += -DWITH_GSM_BS -I./openbsc/include -I./libosmocore/include -I./openbsc
+GSM_INCLUDE += -DWITH_GSM_BS
 
 GSM_SOURCE += gsm_bs.cpp
 
 
 GSM_SOURCE += gsm_bs.cpp
 
@@ -70,16 +70,9 @@ endif
 
 if ENABLE_GSM_MS
 
 
 if ENABLE_GSM_MS
 
-GSM_INCLUDE += -DPACKAGE_VERSION=0 -DWITH_GSM_MS -I./layer23/include -I./libosmocore/include
+GSM_INCLUDE += -DWITH_GSM_MS
 
 
-GSM_SOURCE += gsm_ms.cpp layer23/src/mobile/app_mobile.c
-
-GSM_LIB += ./layer23/src/mobile/libmobile.a \
-       ./layer23/src/common/liblayer23.a \
-       ./libosmocore/build-host/src/.libs/libosmocore.a \
-       ./libosmocore/build-host/src/vty/.libs/libosmovty.a \
-       ./libosmocore/build-host/src/codec/.libs/libosmocodec.a \
-       ./libosmocore/build-host/src/gsm/.libs/libosmogsm.a
+GSM_SOURCE += gsm_ms.cpp
 
 endif
 
 
 endif
 
@@ -162,11 +155,6 @@ install-data-hook:
        @if test -a $(CONFIGdir)/routing.conf ; then \
                echo "NOTE: routing.conf already exists, not changed." ; else \
                cp -v default/routing.conf $(CONFIGdir) ; fi
        @if test -a $(CONFIGdir)/routing.conf ; then \
                echo "NOTE: routing.conf already exists, not changed." ; else \
                cp -v default/routing.conf $(CONFIGdir) ; fi
-if ENABLE_GSM
-       @if test -a $(CONFIGdir)/openbsc.cfg ; then \
-               echo "NOTE: openbsc.cfg already exists, not changed." ; else \
-               cp -v default/openbsc.cfg $(CONFIGdir) ; fi
-endif
        @if test -a $(CONFIGdir)/numbering_int.conf ; then \
                echo "NOTE: numbering_int.conf is obsolete, please use routing." ; fi
        @if test -a $(CONFIGdir)/numbering_ext.conf ; then \
        @if test -a $(CONFIGdir)/numbering_int.conf ; then \
                echo "NOTE: numbering_int.conf is obsolete, please use routing." ; fi
        @if test -a $(CONFIGdir)/numbering_ext.conf ; then \
index cf41b2c..4452371 100644 (file)
@@ -158,45 +158,21 @@ AS_IF([test "x$with_ssl" != xno],
 # check for gsm-bs
 AC_ARG_WITH([gsm-bs],
        [AS_HELP_STRING([--with-gsm-bs],
 # check for gsm-bs
 AC_ARG_WITH([gsm-bs],
        [AS_HELP_STRING([--with-gsm-bs],
-                       [compile with OpenBSC support @<:@default=check@:>@])
+                       [compile with OpenBSC support @<:@default=no@:>@])
        ],
        [],
        [with_gsm_bs="check"])
 
        ],
        [],
        [with_gsm_bs="check"])
 
-AS_IF([test "x$with_gsm_bs" != xno],
-      [AC_MSG_CHECKING(openbsc/include/openbsc/gsm_data.h)
-       if test -e openbsc/include/openbsc/gsm_data.h; then
-               with_gsm_bs="yes"
-               AC_MSG_RESULT(yes)
-       elif test "x$with_gsm_bs" != xcheck ; then
-               AC_MSG_FAILURE([--with-gsm-bs was given, but openbsc/include/openbsc/gsm_data.h was not found! Please link OpenBSC and libosmocore source directory to LCR source directory: ln -s path_to_openbsc/openbsc/ openbsc ; ln -s patch_to_libosmocore libosmocore])
-       else
-               AC_MSG_RESULT(no)
-       fi
-      ])
-
 AM_CONDITIONAL(ENABLE_GSM_BS, test "x$with_gsm_bs" == "xyes" )
 
 # check for gsm-ms
 AC_ARG_WITH([gsm-ms],
        [AS_HELP_STRING([--with-gsm-ms],
 AM_CONDITIONAL(ENABLE_GSM_BS, test "x$with_gsm_bs" == "xyes" )
 
 # check for gsm-ms
 AC_ARG_WITH([gsm-ms],
        [AS_HELP_STRING([--with-gsm-ms],
-                       [compile with Osmocom-bb support @<:@default=check@:>@])
+                       [compile with Osmocom-bb support @<:@default=no@:>@])
        ],
        [],
        [with_gsm_ms="check"])
 
        ],
        [],
        [with_gsm_ms="check"])
 
-AS_IF([test "x$with_gsm_ms" != xno],
-      [AC_MSG_CHECKING(layer23/include/osmocom/bb/common/osmocom_data.h)
-       if test -e layer23/include/osmocom/bb/common/osmocom_data.h; then
-               with_gsm_ms="yes"
-               AC_MSG_RESULT(yes)
-       elif test "x$with_gsm_ms" != xcheck ; then
-               AC_MSG_FAILURE([--with-gsm-ms was given, but layer23/include/osmocom/bb/common/osmocom_data.h was not found! Please link Osmocom-BB and libosmocore source directory to LCR source directory: ln -s path_to_osmocom-bb/src/host/layer23/ layer23 ; ln -s path_to_libosmocore libosmocore])
-       else
-               AC_MSG_RESULT(no)
-       fi
-      ])
-
 AM_CONDITIONAL(ENABLE_GSM_MS, test "x$with_gsm_ms" == "xyes" )
 
 AM_CONDITIONAL(ENABLE_GSM, test "x$with_gsm_bs" == "xyes" -o "x$with_gsm_ms" == "xyes")
 AM_CONDITIONAL(ENABLE_GSM_MS, test "x$with_gsm_ms" == "xyes" )
 
 AM_CONDITIONAL(ENABLE_GSM, test "x$with_gsm_bs" == "xyes" -o "x$with_gsm_ms" == "xyes")
diff --git a/default/openbsc.cfg b/default/openbsc.cfg
deleted file mode 100644 (file)
index 05ec4c0..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-!
-! OpenBSC configuration saved from vty
-!   !
-password foo
-!
-line vty
- no login
-!
-network
-! select county code and network code. 1 equals test network
- network country code 1
- mobile network code 1
-! name the network
- short name OpenBSC
- long name OpenBSC
-! define first bts (counted from 0)
- bts 0
-  type bs11
-  band GSM900
-  location_area_code 1
-  training_sequence_code 7
-  base_station_id_code 63
-  oml e1 line 0 timeslot 1 sub-slot full
-  oml e1 tei 25
-! define tranceiver for this bts (counted from 0)
-  trx 0
-! frequency number from 1 to 124 (GSM900)
-   arfcn 121
-   max_power_red 0
-! all line numbers (0 in this case) must match your mISDN port
-   rsl e1 line 0 timeslot 1 sub-slot full
-   rsl e1 tei 1
-    timeslot 0
-     phys_chan_config CCCH+SDCCH4
-     e1 line 0 timeslot 1 sub-slot full
-    timeslot 1
-     phys_chan_config SDCCH8
-     e1 line 0 timeslot 2 sub-slot 1
-    timeslot 2
-     phys_chan_config TCH/F
-     e1 line 0 timeslot 2 sub-slot 2
-    timeslot 3
-     phys_chan_config TCH/F
-     e1 line 0 timeslot 2 sub-slot 3
-    timeslot 4
-     phys_chan_config TCH/F
-     e1 line 0 timeslot 3 sub-slot 0
-    timeslot 5
-     phys_chan_config TCH/F
-     e1 line 0 timeslot 3 sub-slot 1
-    timeslot 6
-     phys_chan_config TCH/F
-     e1 line 0 timeslot 3 sub-slot 2
-    timeslot 7
-     phys_chan_config TCH/F
-     e1 line 0 timeslot 3 sub-slot 3
-! uncomment this for second TRX, if enabled on BS11
-!  trx 1
-!   arfcn 123
-!   max_power_red 0
-!   rsl e1 line 0 timeslot 1 sub-slot full
-!   rsl e1 tei 2
-!    timeslot 0
-!     phys_chan_config TCH/F
-!     e1 line 0 timeslot 4 sub-slot 0
-!    timeslot 1
-!     phys_chan_config TCH/F
-!     e1 line 0 timeslot 4 sub-slot 1
-!    timeslot 2
-!     phys_chan_config TCH/F
-!     e1 line 0 timeslot 4 sub-slot 2
-!    timeslot 3
-!     phys_chan_config TCH/F
-!     e1 line 0 timeslot 4 sub-slot 3
-!    timeslot 4
-!     phys_chan_config TCH/F
-!     e1 line 0 timeslot 5 sub-slot 0
-!    timeslot 5
-!     phys_chan_config TCH/F
-!     e1 line 0 timeslot 5 sub-slot 1
-!    timeslot 6
-!     phys_chan_config TCH/F
-!     e1 line 0 timeslot 5 sub-slot 2
-!    timeslot 7
-!     phys_chan_config TCH/F
-!     e1 line 0 timeslot 5 sub-slot 3
-! enable this for second BS11 on mISDN port 1
-! bts 1
-!  type bs11
-!  band GSM900
-!  location_area_code 2
-!  training_sequence_code 7
-!  base_station_id_code 63
-!  oml e1 line 1 timeslot 6 sub-slot full
-!  oml e1 tei 25
-!  trx 0
-!   arfcn 122
-!   max_power_red 0
-!   rsl e1 line 1 timeslot 6 sub-slot full
-!   rsl e1 tei 1
-!    timeslot 0
-!     phys_chan_config CCCH+SDCCH4
-!     e1 line 1 timeslot 7 sub-slot 0
-!    timeslot 1
-!     phys_chan_config SDCCH8
-!     e1 line 1 timeslot 7 sub-slot 1
-!    timeslot 2
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 7 sub-slot 2
-!    timeslot 3
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 7 sub-slot 3
-!    timeslot 4
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 8 sub-slot 0
-!    timeslot 5
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 8 sub-slot 1
-!    timeslot 6
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 8 sub-slot 2
-!    timeslot 7
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 8 sub-slot 3
-!  trx 1
-!   arfcn 124
-!   max_power_red 0
-!   rsl e1 line 1 timeslot 6 sub-slot full
-!   rsl e1 tei 2
-!    timeslot 0
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 9 sub-slot 0
-!    timeslot 1
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 9 sub-slot 1
-!    timeslot 2
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 9 sub-slot 2
-!    timeslot 3
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 9 sub-slot 3
-!    timeslot 4
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 10 sub-slot 0
-!    timeslot 5
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 10 sub-slot 1
-!    timeslot 6
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 10 sub-slot 2
-!    timeslot 7
-!     phys_chan_config TCH/F
-!     e1 line 1 timeslot 10 sub-slot 3
-
-
index d1f4d6b..3c222d2 100644 (file)
 # So: change to asterisk, if you have asterisk run in group "asterisk" e.g.
 #socketgroup asterisk
 
 # So: change to asterisk, if you have asterisk run in group "asterisk" e.g.
 #socketgroup asterisk
 
-# Enable GSM network capability.
-# This option turns LCR into a GSM network.
-# For more refer to LCR home page and the OpenBSC page.
-#
-# !!! DANGER !!!
-# Running a GSM network may disturb other networks and may be prossecuted by
-# law of your country.
-# Running a GSM network may prevent mobile users from making EMERGENCY CALLS.
-# Be sure to allow emergency calls to be routed to emergency facilities.
-#
-#gsm
-
 # Enable polling in main loop.
 # This feature is temporarily for test purpose. Don't enable it
 #polling
 # Enable polling in main loop.
 # This feature is temporarily for test purpose. Don't enable it
 #polling
diff --git a/gsm.cpp b/gsm.cpp
index 14f534c..9236ed2 100644 (file)
--- a/gsm.cpp
+++ b/gsm.cpp
@@ -4,12 +4,14 @@
 **                                                                           **
 **---------------------------------------------------------------------------**
 ** Copyright: Andreas Eversberg                                              **
 **                                                                           **
 **---------------------------------------------------------------------------**
 ** Copyright: Andreas Eversberg                                              **
+**            MNCC-Interface: Harald Welte                                  **
 **                                                                           **
 ** mISDN gsm                                                                 **
 **                                                                           **
 \*****************************************************************************/ 
 
 #include "main.h"
 **                                                                           **
 ** mISDN gsm                                                                 **
 **                                                                           **
 \*****************************************************************************/ 
 
 #include "main.h"
+#include "mncc.h"
 
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
 
 #ifndef _GNU_SOURCE
 #define _GNU_SOURCE
@@ -19,8 +21,11 @@ extern "C" {
 }
 
 #include <mISDN/mISDNcompat.h>
 }
 
 #include <mISDN/mISDNcompat.h>
+#include <assert.h>
 
 
-struct lcr_gsm *gsm = NULL;
+#define SOCKET_RETRY_TIMER     5
+
+//struct lcr_gsm *gsm = NULL;
 
 int new_callref = 1;
 
 
 int new_callref = 1;
 
@@ -29,147 +34,53 @@ static const struct _value_string {
        int msg_type;
        const char *name;
 } mncc_names[] = {
        int msg_type;
        const char *name;
 } mncc_names[] = {
-#if defined(MNCC_SETUP_REQ)
        { MNCC_SETUP_REQ,       "MNCC_SETUP_REQ" },
        { MNCC_SETUP_REQ,       "MNCC_SETUP_REQ" },
-#endif
-#if defined(MNCC_SETUP_IND)
        { MNCC_SETUP_IND,       "MNCC_SETUP_IND" },
        { MNCC_SETUP_IND,       "MNCC_SETUP_IND" },
-#endif
-#if defined(MNCC_SETUP_RSP)
        { MNCC_SETUP_RSP,       "MNCC_SETUP_RSP" },
        { MNCC_SETUP_RSP,       "MNCC_SETUP_RSP" },
-#endif
-#if defined(MNCC_SETUP_CNF)
        { MNCC_SETUP_CNF,       "MNCC_SETUP_CNF" },
        { MNCC_SETUP_CNF,       "MNCC_SETUP_CNF" },
-#endif
-#if defined(MNCC_SETUP_COMPL_REQ)
        { MNCC_SETUP_COMPL_REQ, "MNCC_SETUP_COMPL_REQ" },
        { MNCC_SETUP_COMPL_REQ, "MNCC_SETUP_COMPL_REQ" },
-#endif
-#if defined(MNCC_SETUP_COMPL_IND)
        { MNCC_SETUP_COMPL_IND, "MNCC_SETUP_COMPL_IND" },
        { MNCC_SETUP_COMPL_IND, "MNCC_SETUP_COMPL_IND" },
-#endif
-#if defined(MNCC_CALL_CONF_IND)
        { MNCC_CALL_CONF_IND,   "MNCC_CALL_CONF_IND" },
        { MNCC_CALL_CONF_IND,   "MNCC_CALL_CONF_IND" },
-#endif
-#if defined(MNCC_CALL_PROC_REQ)
        { MNCC_CALL_PROC_REQ,   "MNCC_CALL_PROC_REQ" },
        { MNCC_CALL_PROC_REQ,   "MNCC_CALL_PROC_REQ" },
-#endif
-#if defined(MNCC_PROGRESS_REQ)
        { MNCC_PROGRESS_REQ,    "MNCC_PROGRESS_REQ" },
        { MNCC_PROGRESS_REQ,    "MNCC_PROGRESS_REQ" },
-#endif
-#if defined(MNCC_ALERT_REQ)
        { MNCC_ALERT_REQ,       "MNCC_ALERT_REQ" },
        { MNCC_ALERT_REQ,       "MNCC_ALERT_REQ" },
-#endif
-#if defined(MNCC_ALERT_IND)
        { MNCC_ALERT_IND,       "MNCC_ALERT_IND" },
        { MNCC_ALERT_IND,       "MNCC_ALERT_IND" },
-#endif
-#if defined(MNCC_NOTIFY_REQ)
        { MNCC_NOTIFY_REQ,      "MNCC_NOTIFY_REQ" },
        { MNCC_NOTIFY_REQ,      "MNCC_NOTIFY_REQ" },
-#endif
-#if defined(MNCC_NOTIFY_IND)
        { MNCC_NOTIFY_IND,      "MNCC_NOTIFY_IND" },
        { MNCC_NOTIFY_IND,      "MNCC_NOTIFY_IND" },
-#endif
-#if defined(MNCC_DISC_REQ)
        { MNCC_DISC_REQ,        "MNCC_DISC_REQ" },
        { MNCC_DISC_REQ,        "MNCC_DISC_REQ" },
-#endif
-#if defined(MNCC_DISC_IND)
        { MNCC_DISC_IND,        "MNCC_DISC_IND" },
        { MNCC_DISC_IND,        "MNCC_DISC_IND" },
-#endif
-#if defined(MNCC_REL_REQ)
        { MNCC_REL_REQ,         "MNCC_REL_REQ" },
        { MNCC_REL_REQ,         "MNCC_REL_REQ" },
-#endif
-#if defined(MNCC_REL_IND)
        { MNCC_REL_IND,         "MNCC_REL_IND" },
        { MNCC_REL_IND,         "MNCC_REL_IND" },
-#endif
-#if defined(MNCC_REL_CNF)
        { MNCC_REL_CNF,         "MNCC_REL_CNF" },
        { MNCC_REL_CNF,         "MNCC_REL_CNF" },
-#endif
-#if defined(MNCC_FACILITY_REQ)
        { MNCC_FACILITY_REQ,    "MNCC_FACILITY_REQ" },
        { MNCC_FACILITY_REQ,    "MNCC_FACILITY_REQ" },
-#endif
-#if defined(MNCC_FACILITY_IND)
        { MNCC_FACILITY_IND,    "MNCC_FACILITY_IND" },
        { MNCC_FACILITY_IND,    "MNCC_FACILITY_IND" },
-#endif
-#if defined(MNCC_START_DTMF_IND)
        { MNCC_START_DTMF_IND,  "MNCC_START_DTMF_IND" },
        { MNCC_START_DTMF_IND,  "MNCC_START_DTMF_IND" },
-#endif
-#if defined(MNCC_START_DTMF_RSP)
        { MNCC_START_DTMF_RSP,  "MNCC_START_DTMF_RSP" },
        { MNCC_START_DTMF_RSP,  "MNCC_START_DTMF_RSP" },
-#endif
-#if defined(MNCC_START_DTMF_REJ)
        { MNCC_START_DTMF_REJ,  "MNCC_START_DTMF_REJ" },
        { MNCC_START_DTMF_REJ,  "MNCC_START_DTMF_REJ" },
-#endif
-#if defined(MNCC_STOP_DTMF_IND)
        { MNCC_STOP_DTMF_IND,   "MNCC_STOP_DTMF_IND" },
        { MNCC_STOP_DTMF_IND,   "MNCC_STOP_DTMF_IND" },
-#endif
-#if defined(MNCC_STOP_DTMF_RSP)
        { MNCC_STOP_DTMF_RSP,   "MNCC_STOP_DTMF_RSP" },
        { MNCC_STOP_DTMF_RSP,   "MNCC_STOP_DTMF_RSP" },
-#endif
-#if defined(MNCC_MODIFY_REQ)
        { MNCC_MODIFY_REQ,      "MNCC_MODIFY_REQ" },
        { MNCC_MODIFY_REQ,      "MNCC_MODIFY_REQ" },
-#endif
-#if defined(MNCC_MODIFY_IND)
        { MNCC_MODIFY_IND,      "MNCC_MODIFY_IND" },
        { MNCC_MODIFY_IND,      "MNCC_MODIFY_IND" },
-#endif
-#if defined(MNCC_MODIFY_RSP)
        { MNCC_MODIFY_RSP,      "MNCC_MODIFY_RSP" },
        { MNCC_MODIFY_RSP,      "MNCC_MODIFY_RSP" },
-#endif
-#if defined(MNCC_MODIFY_CNF)
        { MNCC_MODIFY_CNF,      "MNCC_MODIFY_CNF" },
        { MNCC_MODIFY_CNF,      "MNCC_MODIFY_CNF" },
-#endif
-#if defined(MNCC_MODIFY_REJ)
        { MNCC_MODIFY_REJ,      "MNCC_MODIFY_REJ" },
        { MNCC_MODIFY_REJ,      "MNCC_MODIFY_REJ" },
-#endif
-#if defined(MNCC_HOLD_IND)
        { MNCC_HOLD_IND,        "MNCC_HOLD_IND" },
        { MNCC_HOLD_IND,        "MNCC_HOLD_IND" },
-#endif
-#if defined(MNCC_HOLD_CNF)
        { MNCC_HOLD_CNF,        "MNCC_HOLD_CNF" },
        { MNCC_HOLD_CNF,        "MNCC_HOLD_CNF" },
-#endif
-#if defined(MNCC_HOLD_REJ)
        { MNCC_HOLD_REJ,        "MNCC_HOLD_REJ" },
        { MNCC_HOLD_REJ,        "MNCC_HOLD_REJ" },
-#endif
-#if defined(MNCC_RETRIEVE_IND)
        { MNCC_RETRIEVE_IND,    "MNCC_RETRIEVE_IND" },
        { MNCC_RETRIEVE_IND,    "MNCC_RETRIEVE_IND" },
-#endif
-#if defined(MNCC_RETRIEVE_CNF)
        { MNCC_RETRIEVE_CNF,    "MNCC_RETRIEVE_CNF" },
        { MNCC_RETRIEVE_CNF,    "MNCC_RETRIEVE_CNF" },
-#endif
-#if defined(MNCC_RETRIEVE_REJ)
        { MNCC_RETRIEVE_REJ,    "MNCC_RETRIEVE_REJ" },
        { MNCC_RETRIEVE_REJ,    "MNCC_RETRIEVE_REJ" },
-#endif
-#if defined(MNCC_USERINFO_REQ)
        { MNCC_USERINFO_REQ,    "MNCC_USERINFO_REQ" },
        { MNCC_USERINFO_REQ,    "MNCC_USERINFO_REQ" },
-#endif
-#if defined(MNCC_USERINFO_IND)
        { MNCC_USERINFO_IND,    "MNCC_USERINFO_IND" },
        { MNCC_USERINFO_IND,    "MNCC_USERINFO_IND" },
-#endif
-#if defined(MNCC_REJ_REQ)
        { MNCC_REJ_REQ,         "MNCC_REJ_REQ" },
        { MNCC_REJ_REQ,         "MNCC_REJ_REQ" },
-#endif
-#if defined(MNCC_REJ_IND)
        { MNCC_REJ_IND,         "MNCC_REJ_IND" },
        { MNCC_REJ_IND,         "MNCC_REJ_IND" },
-#endif
-#if defined(MNCC_PROGRESS_IND)
        { MNCC_PROGRESS_IND,    "MNCC_PROGRESS_IND" },
        { MNCC_PROGRESS_IND,    "MNCC_PROGRESS_IND" },
-#endif
-#if defined(MNCC_CALL_PROC_IND)
        { MNCC_CALL_PROC_IND,   "MNCC_CALL_PROC_IND" },
        { MNCC_CALL_PROC_IND,   "MNCC_CALL_PROC_IND" },
-#endif
-#if defined(MNCC_CALL_CONF_REQ)
        { MNCC_CALL_CONF_REQ,   "MNCC_CALL_CONF_REQ" },
        { MNCC_CALL_CONF_REQ,   "MNCC_CALL_CONF_REQ" },
-#endif
-#if defined(MNCC_START_DTMF_REQ)
        { MNCC_START_DTMF_REQ,  "MNCC_START_DTMF_REQ" },
        { MNCC_START_DTMF_REQ,  "MNCC_START_DTMF_REQ" },
-#endif
-#if defined(MNCC_STOP_DTMF_REQ)
        { MNCC_STOP_DTMF_REQ,   "MNCC_STOP_DTMF_REQ" },
        { MNCC_STOP_DTMF_REQ,   "MNCC_STOP_DTMF_REQ" },
-#endif
-#if defined(MNCC_HOLD_REQ)
        { MNCC_HOLD_REQ,        "MNCC_HOLD_REQ " },
        { MNCC_HOLD_REQ,        "MNCC_HOLD_REQ " },
-#endif
-#if defined(MNCC_RETRIEVE_REQ)
        { MNCC_RETRIEVE_REQ,    "MNCC_RETRIEVE_REQ" },
        { MNCC_RETRIEVE_REQ,    "MNCC_RETRIEVE_REQ" },
-#endif
        { 0,                    NULL }
 };
 
        { 0,                    NULL }
 };
 
@@ -185,6 +96,8 @@ const char *mncc_name(int value)
        return "unknown";
 }
 
        return "unknown";
 }
 
+static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data);
+
 /*
  * create and send mncc message
  */
 /*
  * create and send mncc message
  */
@@ -197,17 +110,12 @@ struct gsm_mncc *create_mncc(int msg_type, unsigned int callref)
        mncc->callref = callref;
        return (mncc);
 }
        mncc->callref = callref;
        return (mncc);
 }
-int send_and_free_mncc(void *instance, unsigned int msg_type, void *data)
+int send_and_free_mncc(struct lcr_gsm *lcr_gsm, unsigned int msg_type, void *data)
 {
        int ret = 0;
 
 {
        int ret = 0;
 
-       if (instance) {
-#ifdef WITH_GSM_BS
-               ret = mncc_send((struct gsm_network *)instance, msg_type, data);
-#endif
-#ifdef WITH_GSM_MS
-               ret = mncc_send((struct osmocom_ms *)instance, msg_type, data);
-#endif
+       if (lcr_gsm) {
+               ret = mncc_send(lcr_gsm, msg_type, data);
        }
        free(data);
 
        }
        free(data);
 
@@ -224,7 +132,7 @@ Pgsm::Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_se
        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_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_instance = NULL;
+       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_callref = 0;
        p_m_g_mode = 0;
        p_m_g_gsm_b_sock = -1;
@@ -385,12 +293,10 @@ void Pgsm::frame_send(void *_frame)
        frame->msg_type = GSM_TCHF_FRAME;
        frame->callref = p_m_g_callref;
        memcpy(frame->data, _frame, 33);
        frame->msg_type = GSM_TCHF_FRAME;
        frame->callref = p_m_g_callref;
        memcpy(frame->data, _frame, 33);
-#ifdef WITH_GSM_BS
-       mncc_send((struct gsm_network *)p_m_g_instance, frame->msg_type, frame);
-#endif
-#ifdef WITH_GSM_MS
-       mncc_send((struct osmocom_ms *)p_m_g_instance, frame->msg_type, frame);
-#endif
+
+       if (p_m_g_lcr_gsm) {
+               mncc_send(p_m_g_lcr_gsm, frame->msg_type, frame);
+       }
 }
 
 
 }
 
 
@@ -479,7 +385,7 @@ void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm
        mode->lchan_mode = 0x01; /* GSM V1 */
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
        mode->lchan_mode = 0x01; /* GSM V1 */
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
-       send_and_free_mncc(p_m_g_instance, mode->msg_type, mode);
+       send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
 
 }
 
 
 }
 
@@ -501,7 +407,7 @@ void Pgsm::call_proc_ind(unsigned int msg_type, unsigned int callref, struct gsm
                gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
                frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
                gsm_trace_header(p_m_mISDNport, 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_instance, frame->msg_type, frame);
+               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
                p_m_g_tch_connected = 1;
        }
 }
                p_m_g_tch_connected = 1;
        }
 }
@@ -524,7 +430,7 @@ void Pgsm::alert_ind(unsigned int msg_type, unsigned int callref, struct gsm_mnc
                gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
                frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
                gsm_trace_header(p_m_mISDNport, 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_instance, frame->msg_type, frame);
+               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
                p_m_g_tch_connected = 1;
        }
 }
                p_m_g_tch_connected = 1;
        }
 }
@@ -556,7 +462,7 @@ void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mnc
        gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
        resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
        end_trace();
        gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_COMPL_REQ, DIRECTION_OUT);
        resp = create_mncc(MNCC_SETUP_COMPL_REQ, p_m_g_callref);
        end_trace();
-       send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
+       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 = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_CONNECT);
        memcpy(&message->param.connectinfo, &p_connectinfo, sizeof(struct connect_info));
@@ -568,7 +474,7 @@ void Pgsm::setup_cnf(unsigned int msg_type, unsigned int callref, struct gsm_mnc
                gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
                frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
                gsm_trace_header(p_m_mISDNport, 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_instance, frame->msg_type, frame);
+               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
                p_m_g_tch_connected = 1;
        }
 }
                p_m_g_tch_connected = 1;
        }
 }
@@ -587,7 +493,7 @@ void Pgsm::setup_compl_ind(unsigned int msg_type, unsigned int callref, struct g
                gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
                frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
                gsm_trace_header(p_m_mISDNport, 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_instance, frame->msg_type, frame);
+               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
                p_m_g_tch_connected = 1;
        }
 }
                p_m_g_tch_connected = 1;
        }
 }
@@ -622,7 +528,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();
        add_trace("cause", "value", "%d", resp->cause.value);
 #endif
        end_trace();
-       send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
+       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
 
        /* sending release to endpoint */
        while(p_epointlist) {
 
        /* sending release to endpoint */
        while(p_epointlist) {
@@ -702,7 +608,7 @@ void Pgsm::message_notify(unsigned int epoint_id, int message_id, union paramete
                        end_trace();
                        mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
                        mncc->notify = notify;
                        end_trace();
                        mncc = create_mncc(MNCC_NOTIFY_REQ, p_m_g_callref);
                        mncc->notify = notify;
-                       send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+                       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
                }
        }
 }
                }
        }
 }
@@ -725,7 +631,7 @@ void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parame
                add_trace("progress", "descr", "%d", mncc->progress.descr);
        }
        end_trace();
                add_trace("progress", "descr", "%d", mncc->progress.descr);
        }
        end_trace();
-       send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_IN_ALERTING);
 
 
        new_state(PORT_STATE_IN_ALERTING);
 
@@ -733,7 +639,7 @@ void Pgsm::message_alerting(unsigned int epoint_id, int message_id, union parame
                gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
                mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
                gsm_trace_header(p_m_mISDNport, 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_instance, mncc->msg_type, mncc);
+               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
                p_m_g_tch_connected = 1;
        }
 }
                p_m_g_tch_connected = 1;
        }
 }
@@ -799,7 +705,7 @@ void Pgsm::message_connect(unsigned int epoint_id, int message_id, union paramet
                add_trace("connected", "number", "%s", mncc->connected.number);
        }
        end_trace();
                add_trace("connected", "number", "%s", mncc->connected.number);
        }
        end_trace();
-       send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_CONNECT_WAITING);
 }
 
        new_state(PORT_STATE_CONNECT_WAITING);
 }
@@ -829,7 +735,7 @@ 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();
        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_instance, mncc->msg_type, mncc);
+       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_OUT_DISCONNECT);
 
 
        new_state(PORT_STATE_OUT_DISCONNECT);
 
@@ -837,7 +743,7 @@ void Pgsm::message_disconnect(unsigned int epoint_id, int message_id, union para
                gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
                mncc = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
                gsm_trace_header(p_m_mISDNport, 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_instance, mncc->msg_type, mncc);
+               send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
                p_m_g_tch_connected = 1;
        }
 }
                p_m_g_tch_connected = 1;
        }
 }
@@ -859,7 +765,7 @@ 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();
        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_instance, mncc->msg_type, mncc);
+       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_RELEASE);
        trigger_work(&p_m_g_delete);
 
        new_state(PORT_STATE_RELEASE);
        trigger_work(&p_m_g_delete);
@@ -985,12 +891,6 @@ static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int i
 
 int gsm_exit(int rc)
 {
 
 int gsm_exit(int rc)
 {
-       /* free gsm instance */
-       if (gsm) {
-               free(gsm);
-               gsm = NULL;
-       }
-
        return(rc);
 }
 
        return(rc);
 }
 
@@ -999,14 +899,214 @@ int gsm_init(void)
        /* seed the PRNG */
        srand(time(NULL));
 
        /* seed the PRNG */
        srand(time(NULL));
 
-       /* create gsm instance */
-       gsm = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
+       return 0;
+}
+
+/*
+ * MNCC interface
+ */
+
+static int mncc_q_enqueue(struct lcr_gsm *lcr_gsm, struct gsm_mncc *mncc, unsigned int len)
+{
+       struct mncc_q_entry *qe;
+
+       qe = (struct mncc_q_entry *) MALLOC(sizeof(*qe)+sizeof(*mncc)+len);
+       if (!qe)
+               return -ENOMEM;
+
+       qe->next = NULL;
+       qe->len = len;
+       memcpy(qe->data, mncc, len);
+
+       /* in case of empty list ... */
+       if (!lcr_gsm->mncc_q_hd && !lcr_gsm->mncc_q_tail) {
+               /* the list head and tail both point to the new qe */
+               lcr_gsm->mncc_q_hd = lcr_gsm->mncc_q_tail = qe;
+       } else {
+               /* append to tail of list */
+               lcr_gsm->mncc_q_tail->next = qe;
+               lcr_gsm->mncc_q_tail = qe;
+       }
+
+       lcr_gsm->mncc_lfd.when |= LCR_FD_WRITE;
 
        return 0;
 }
 
 
        return 0;
 }
 
-int handle_gsm(void)
+static struct mncc_q_entry *mncc_q_dequeue(struct lcr_gsm *lcr_gsm)
+{
+       struct mncc_q_entry *qe = lcr_gsm->mncc_q_hd;
+       if (!qe)
+               return NULL;
+
+       /* dequeue the successfully sent message */
+       lcr_gsm->mncc_q_hd = qe->next;
+       if (!qe)
+               return NULL;
+       if (qe == lcr_gsm->mncc_q_tail)
+               lcr_gsm->mncc_q_tail = NULL;
+
+       return qe;
+}
+
+/* routine called by LCR code if it wants to send a message to OpenBSC */
+static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data)
+{
+       int len = 0;
+
+       /* FIXME: the caller should provide this */
+       switch (msg_type) {
+       case GSM_TCHF_FRAME:
+               len = sizeof(struct gsm_data_frame) + 33;
+               break;
+       default:
+               len = sizeof(struct gsm_mncc);
+               break;
+       }
+               
+       return mncc_q_enqueue(lcr_gsm, (struct gsm_mncc *)data, len);
+}
+
+/* close MNCC socket */
+static int mncc_fd_close(struct lcr_gsm *lcr_gsm, struct lcr_fd *lfd)
 {
 {
+       class Port *port;
+       class Pgsm *pgsm = NULL;
+       struct lcr_msg *message;
+
+       PERROR("Lost MNCC socket, retrying in %u seconds\n", SOCKET_RETRY_TIMER);
+       close(lfd->fd);
+       unregister_fd(lfd);
+       lfd->fd = -1;
+
+       /* free all the calls that were running through the MNCC interface */
+       port = port_first;
+       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) {
+                               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);
+                       }
+               }
+               port = port->next;
+       }
+
+       /* flush the queue */
+       while (mncc_q_dequeue(lcr_gsm))
+               ;
+
+       /* start the re-connect timer */
+       schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
+
+       return 0;
+}
+
+/* write to OpenBSC via MNCC socket */
+static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx)
+{
+       struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
+       struct mncc_q_entry *qe, *qe2;
+       int rc;
+
+       while (1) {
+               qe = lcr_gsm->mncc_q_hd;
+               if (!qe) {
+                       lfd->when &= ~LCR_FD_WRITE;
+                       break;
+               }
+               rc = write(lfd->fd, qe->data, qe->len);
+               if (rc == 0)
+                       return mncc_fd_close(lcr_gsm, lfd);
+               if (rc < 0)
+                       return rc;
+               if (rc < (int)qe->len)
+                       return -1;
+               /* dequeue the successfully sent message */
+               qe2 = mncc_q_dequeue(lcr_gsm);
+               assert(qe == qe2);
+               free(qe);
+       }
+       return 0;
+}
+
+/* read from OpenBSC via MNCC socket */
+static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
+{
+       struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
+       int rc;
+       static char buf[sizeof(struct gsm_mncc)+1024];
+       struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf;
+
+       memset(buf, 0, sizeof(buf));
+       rc = recv(lfd->fd, buf, sizeof(buf), 0);
+       if (rc == 0)
+               return mncc_fd_close(lcr_gsm, lfd);
+       if (rc < 0)
+               return rc;
+
+       /* Hand the MNCC message into LCR */
+       switch (lcr_gsm->type) {
+#ifdef WITH_GSM_BS
+       case LCR_GSM_TYPE_NETWORK:
+               return message_bsc(lcr_gsm, mncc_prim->msg_type, mncc_prim);
+#endif
+#ifdef WITH_GSM_MS
+       case LCR_GSM_TYPE_MS:
+               return message_ms(lcr_gsm, mncc_prim->msg_type, mncc_prim);
+#endif
+       default:
+               return 0;
+       }
+}
+
+/* file descriptor callback if we can read or write form MNCC socket */
+static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *inst, int idx)
+{
+       int rc = 0;
+
+       if (what & LCR_FD_READ)
+               rc = mncc_fd_read(lfd, inst, idx);
+       if (rc < 0)
+               return rc;
+
+       if (what & LCR_FD_WRITE)
+               rc = mncc_fd_write(lfd, inst, idx);
+
+       return rc;
+}
+
+int mncc_socket_retry_cb(struct lcr_timer *timer, void *inst, int index)
+{
+       struct lcr_gsm *lcr_gsm = (struct lcr_gsm *) inst;
+       int fd, rc;
+
+       lcr_gsm->mncc_lfd.fd = -1;
+
+       fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+       if (fd < 0) {
+               PERROR("Cannot create SEQPACKET socket, giving up!\n");
+               return fd;
+       }
+
+       rc = connect(fd, (struct sockaddr *) &lcr_gsm->sun,
+                    sizeof(lcr_gsm->sun));
+       if (rc < 0) {
+               PERROR("Could not connect to MNCC socket %s, "
+                       "retrying in %u seconds\n", lcr_gsm->sun.sun_path,
+                       SOCKET_RETRY_TIMER);
+               close(fd);
+               schedule_timer(&lcr_gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
+       } else {
+               PDEBUG(DEBUG_GSM, "Connected to MNCC socket %s!\n", lcr_gsm->sun.sun_path);
+               lcr_gsm->mncc_lfd.fd = fd;
+               register_fd(&lcr_gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, lcr_gsm, 0);
+       }
+
        return 0;
 }
 
        return 0;
 }
 
diff --git a/gsm.h b/gsm.h
index c12baa0..3ecaf0d 100644 (file)
--- a/gsm.h
+++ b/gsm.h
@@ -9,8 +9,15 @@ struct mncc_q_entry {
        char data[0];                   /* struct gsm_mncc */
 };
 
        char data[0];                   /* struct gsm_mncc */
 };
 
+enum {
+       LCR_GSM_TYPE_NETWORK,
+       LCR_GSM_TYPE_MS,
+};
+
 struct lcr_gsm {
 struct lcr_gsm {
-       void            *network;       /* OpenBSC network handle */
+       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_*/
 
        struct lcr_fd   mncc_lfd;       /* Unix domain socket to OpenBSC MNCC */
        struct mncc_q_entry *mncc_q_hd;
 
        struct lcr_fd   mncc_lfd;       /* Unix domain socket to OpenBSC MNCC */
        struct mncc_q_entry *mncc_q_hd;
@@ -19,8 +26,6 @@ struct lcr_gsm {
        struct sockaddr_un sun;         /* Socket address of MNCC socket */
 };
 
        struct sockaddr_un sun;         /* Socket address of MNCC socket */
 };
 
-extern struct lcr_gsm *gsm;
-
 /* GSM port class */
 class Pgsm : public PmISDN
 {
 /* GSM port class */
 class Pgsm : public PmISDN
 {
@@ -28,9 +33,9 @@ class Pgsm : public PmISDN
        Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
        ~Pgsm();
 
        Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode);
        ~Pgsm();
 
-       void *p_m_g_instance; /* pointer to network/ms instance */
+       struct lcr_gsm *p_m_g_lcr_gsm; /* pointer to network/ms instance */
        unsigned int p_m_g_callref; /* ref by OpenBSC/Osmocom-BB */
        unsigned int p_m_g_callref; /* ref by OpenBSC/Osmocom-BB */
-       struct lcr_work p_m_g_delete;           /* timer for audio transmission */
+       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 */
        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 */
@@ -68,10 +73,10 @@ class Pgsm : public PmISDN
 };
 
 struct gsm_mncc *create_mncc(int msg_type, unsigned int callref);
 };
 
 struct gsm_mncc *create_mncc(int msg_type, unsigned int callref);
-int send_and_free_mncc(void *instance, unsigned int msg_type, void *data);
+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(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction);
-int handle_gsm(void);
 int gsm_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_exit(int rc);
 int gsm_init(void);
 int gsm_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_exit(int rc);
 int gsm_init(void);
+int mncc_socket_retry_cb(struct lcr_timer *timer, void *inst, int index);
 
 
index 2da06c7..285c88f 100644 (file)
 \*****************************************************************************/ 
 
 #include "main.h"
 \*****************************************************************************/ 
 
 #include "main.h"
-#include "config.h"
+#include "mncc.h"
 
 
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-extern "C" {
-#include <assert.h>
-#include <getopt.h>
-
-#include <sys/socket.h>
-#include <sys/un.h>
-
-#include <openbsc/mncc.h>
-#include <openbsc/trau_frame.h>
-}
-
-#define SOCKET_RETRY_TIMER     5
+struct lcr_gsm *gsm_bs = NULL;
 
 /*
  * DTMF stuff
 
 /*
  * DTMF stuff
@@ -61,7 +47,7 @@ void generate_dtmf(void)
  */
 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, struct mISDNport *mISDNport, char *portname, struct port_settings *settings, int channel, int exclusive, int mode) : Pgsm(type, mISDNport, portname, settings, channel, exclusive, mode)
 {
-       p_m_g_instance = gsm->network;
+       p_m_g_lcr_gsm = gsm_bs;
        p_m_g_dtmf = NULL;
        p_m_g_dtmf_index = 0;
 
        p_m_g_dtmf = NULL;
        p_m_g_dtmf_index = 0;
 
@@ -95,7 +81,7 @@ void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct
        resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
        resp->fields |= MNCC_F_KEYPAD;
        resp->keypad = mncc->keypad;
        resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref);
        resp->fields |= MNCC_F_KEYPAD;
        resp->keypad = mncc->keypad;
-       send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
+       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
 
 #if 0
        /* send dialing information */
 
 #if 0
        /* send dialing information */
@@ -143,7 +129,7 @@ void Pgsm_bs::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct
        end_trace();
        resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
        resp->keypad = mncc->keypad;
        end_trace();
        resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref);
        resp->keypad = mncc->keypad;
-       send_and_free_mncc(p_m_g_instance, resp->msg_type, resp);
+       send_and_free_mncc(p_m_g_lcr_gsm, resp->msg_type, resp);
        
        /* stop DTMF */
        p_m_g_dtmf = NULL;
        
        /* stop DTMF */
        p_m_g_dtmf = NULL;
@@ -168,14 +154,14 @@ void Pgsm_bs::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_m
        gsm_trace_header(p_m_mISDNport, this, MNCC_HOLD_CNF, DIRECTION_OUT);
        end_trace();
        resp = create_mncc(MNCC_HOLD_CNF, p_m_g_callref);
        gsm_trace_header(p_m_mISDNport, 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_instance, resp->msg_type, resp);
+       send_and_free_mncc(p_m_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);
                end_trace();
                frame = create_mncc(MNCC_FRAME_DROP, p_m_g_callref);
 
        /* disable audio */
        if (p_m_g_tch_connected) { /* it should be true */
                gsm_trace_header(p_m_mISDNport, 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_instance, frame->msg_type, frame);
+               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
                p_m_g_tch_connected = 0;
        }
 }
                p_m_g_tch_connected = 0;
        }
 }
@@ -200,14 +186,14 @@ void Pgsm_bs::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_m
        gsm_trace_header(p_m_mISDNport, this, MNCC_RETRIEVE_CNF, DIRECTION_OUT);
        end_trace();
        resp = create_mncc(MNCC_RETRIEVE_CNF, p_m_g_callref);
        gsm_trace_header(p_m_mISDNport, 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_instance, resp->msg_type, resp);
+       send_and_free_mncc(p_m_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);
                end_trace();
                frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
 
        /* enable audio */
        if (!p_m_g_tch_connected) { /* it should be true */
                gsm_trace_header(p_m_mISDNport, 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_instance, frame->msg_type, frame);
+               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
                p_m_g_tch_connected = 1;
        }
 }
                p_m_g_tch_connected = 1;
        }
 }
@@ -242,7 +228,7 @@ 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();
                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_instance, mncc->msg_type, mncc);
+               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;
                new_state(PORT_STATE_RELEASE);
                trigger_work(&p_m_g_delete);
                return;
@@ -263,7 +249,7 @@ 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, "port is blocked");
                end_trace();
                add_trace("cause", "value", "%d", mncc->cause.value);
                add_trace("reason", NULL, "port is blocked");
                end_trace();
-               send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+               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;
                new_state(PORT_STATE_RELEASE);
                trigger_work(&p_m_g_delete);
                return;
@@ -335,7 +321,7 @@ 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, "no channel");
                end_trace();
                add_trace("cause", "value", "%d", mncc->cause.value);
                add_trace("reason", NULL, "no channel");
                end_trace();
-               send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+               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;
                new_state(PORT_STATE_RELEASE);
                trigger_work(&p_m_g_delete);
                return;
@@ -369,7 +355,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        mode->lchan_mode = 0x01; /* GSM V1 */
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
        mode->lchan_mode = 0x01; /* GSM V1 */
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
-       send_and_free_mncc(p_m_g_instance, mode->msg_type, mode);
+       send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
 
        /* send call proceeding */
        gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
 
        /* send call proceeding */
        gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT);
@@ -384,7 +370,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
                add_trace("progress", "descr", "%d", proceeding->progress.descr);
        }
        end_trace();
                add_trace("progress", "descr", "%d", proceeding->progress.descr);
        }
        end_trace();
-       send_and_free_mncc(p_m_g_instance, proceeding->msg_type, proceeding);
+       send_and_free_mncc(p_m_g_lcr_gsm, proceeding->msg_type, proceeding);
 
        new_state(PORT_STATE_IN_PROCEEDING);
 
 
        new_state(PORT_STATE_IN_PROCEEDING);
 
@@ -392,7 +378,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
                gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
                frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
                gsm_trace_header(p_m_mISDNport, 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_instance, frame->msg_type, frame);
+               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
                p_m_g_tch_connected = 1;
        }
 
                p_m_g_tch_connected = 1;
        }
 
@@ -413,7 +399,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
 /*
  * BSC sends message to port
  */
 /*
  * BSC sends message to port
  */
-static int message_bsc(struct gsm_network *net, int msg_type, void *arg)
+int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg)
 {
        struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
        unsigned int callref = mncc->callref;
 {
        struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
        unsigned int callref = mncc->callref;
@@ -482,7 +468,7 @@ static int message_bsc(struct gsm_network *net, int msg_type, void *arg)
                        add_trace("cause", "location", "%d", rej->cause.location);
                        add_trace("cause", "value", "%d", rej->cause.value);
                        end_trace();
                        add_trace("cause", "location", "%d", rej->cause.location);
                        add_trace("cause", "value", "%d", rej->cause.value);
                        end_trace();
-                       send_and_free_mncc(gsm->network, rej->msg_type, rej);
+                       send_and_free_mncc(lcr_gsm, rej->msg_type, rej);
                        return 0;
                }
                /* creating port object, transparent until setup with hdlc */
                        return 0;
                }
                /* creating port object, transparent until setup with hdlc */
@@ -565,12 +551,12 @@ 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 */
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
 
        /* no GSM MNCC connection */
-       if (gsm->mncc_lfd.fd < 0) {
+       if (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, "No MNCC connection.");
                end_trace();
                message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                gsm_trace_header(p_m_mISDNport, 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);
-               message->param.disconnectinfo.cause = 27; // temp. unavail.
+               message->param.disconnectinfo.cause = 41; // temp. failure.
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
@@ -762,7 +748,7 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame
        //todo
 
        end_trace();
        //todo
 
        end_trace();
-       send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_OUT_SETUP);
 
 
        new_state(PORT_STATE_OUT_SETUP);
 
@@ -796,215 +782,38 @@ int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parame
 
 int gsm_bs_exit(int rc)
 {
 
 int gsm_bs_exit(int rc)
 {
-       gsm->network = NULL;
-
-       return(rc);
-}
-
-extern "C" {
-
-static int mncc_q_enqueue(struct gsm_mncc *mncc, unsigned int len)
-{
-       struct mncc_q_entry *qe;
-
-       qe = (struct mncc_q_entry *) MALLOC(sizeof(*qe)+sizeof(*mncc)+len);
-       if (!qe)
-               return -ENOMEM;
-
-       qe->next = NULL;
-       qe->len = len;
-       memcpy(qe->data, mncc, len);
-
-       /* in case of empty list ... */
-       if (!gsm->mncc_q_hd && !gsm->mncc_q_tail) {
-               /* the list head and tail both point to the new qe */
-               gsm->mncc_q_hd = gsm->mncc_q_tail = qe;
-       } else {
-               /* append to tail of list */
-               gsm->mncc_q_tail->next = qe;
-               gsm->mncc_q_tail = qe;
-       }
-
-       gsm->mncc_lfd.when |= LCR_FD_WRITE;
-
-       return 0;
-}
-
-static struct mncc_q_entry *mncc_q_dequeue(void)
-{
-       struct mncc_q_entry *qe = gsm->mncc_q_hd;
-       if (!qe)
-               return NULL;
-
-       /* dequeue the successfully sent message */
-       gsm->mncc_q_hd = qe->next;
-       if (!qe)
-               return NULL;
-       if (qe == gsm->mncc_q_tail)
-               gsm->mncc_q_tail = NULL;
-
-       return qe;
-}
-
-/* routine called by LCR code if it wants to send a message to OpenBSC */
-int mncc_send(struct gsm_network *instance, int msg_type, void *data)
-{
-       int len = 0;
-
-       /* FIXME: the caller should provide this */
-       switch (msg_type) {
-       case GSM_TCHF_FRAME:
-               len = sizeof(struct gsm_data_frame) + 33;
-               break;
-       default:
-               len = sizeof(struct gsm_mncc);
-               break;
-       }
-               
-       return mncc_q_enqueue((struct gsm_mncc *)data, len);
-}
-
-} // extern "C"
-
-/* close MNCC socket */
-static int mncc_fd_close(struct lcr_fd *lfd)
-{
-       class Port *port;
-       class Pgsm_bs *pgsm_bs = NULL;
-       struct lcr_msg *message;
-
-       PERROR("Lost MNCC socket, retrying in %u seconds\n", SOCKET_RETRY_TIMER);
-       close(lfd->fd);
-       unregister_fd(lfd);
-       lfd->fd = -1;
-
-       /* free all the calls that were running through the MNCC interface */
-       port = port_first;
-       while(port) {
-               if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) {
-                       pgsm_bs = (class Pgsm_bs *)port;
-                       message = message_create(pgsm_bs->p_serial, ACTIVE_EPOINT(pgsm_bs->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_bs->new_state(PORT_STATE_RELEASE);
-                       trigger_work(&pgsm_bs->p_m_g_delete);
+       /* free gsm instance */
+       if (gsm_bs) {
+               if (gsm_bs->mncc_lfd.fd > -1) {
+                       close(gsm_bs->mncc_lfd.fd);
+                       unregister_fd(&gsm_bs->mncc_lfd);
                }
                }
-               port = port->next;
-       }
-
-       /* flush the queue */
-       while (mncc_q_dequeue())
-               ;
-
-       /* start the re-connect timer */
-       schedule_timer(&gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
-
-       generate_dtmf();
-
-       return 0;
-}
-
-/* read from OpenBSC via MNCC socket */
-static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx)
-{
-       struct mncc_q_entry *qe, *qe2;
-       int rc;
-
-       while (1) {
-               qe = gsm->mncc_q_hd;
-               if (!qe) {
-                       lfd->when &= ~LCR_FD_WRITE;
-                       break;
-               }
-               rc = write(lfd->fd, qe->data, qe->len);
-               if (rc == 0)
-                       return mncc_fd_close(lfd);
-               if (rc < 0)
-                       return rc;
-               if (rc < (int)qe->len)
-                       return -1;
-               /* dequeue the successfully sent message */
-               qe2 = mncc_q_dequeue();
-               assert(qe == qe2);
-               free(qe);
-       }
-       return 0;
-}
-
-/* read from OpenBSC via MNCC socket */
-static int mncc_fd_read(struct lcr_fd *lfd, void *inst, int idx)
-{
-       int rc;
-       static char buf[sizeof(struct gsm_mncc)+1024];
-       struct gsm_mncc *mncc_prim = (struct gsm_mncc *) buf;
-
-       memset(buf, 0, sizeof(buf));
-       rc = recv(lfd->fd, buf, sizeof(buf), 0);
-       if (rc == 0)
-               return mncc_fd_close(lfd);
-       if (rc < 0)
-               return rc;
-
-       /* Hand the MNCC message into LCR */
-       return message_bsc(NULL, mncc_prim->msg_type, mncc_prim);
-}
 
 
-/* file descriptor callback if we can read or write form MNCC socket */
-static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *instance, int idx)
-{
-       int rc = 0;
-
-       if (what & LCR_FD_READ)
-               rc = mncc_fd_read(lfd, instance, idx);
-       if (rc < 0)
-               return rc;
-
-       if (what & LCR_FD_WRITE)
-               rc = mncc_fd_write(lfd, instance, idx);
-
-       return rc;
-}
-
-static int socket_retry_cb(struct lcr_timer *timer, void *instance, int index)
-{
-       int fd, rc;
-
-       fd = socket(PF_UNIX, SOCK_SEQPACKET, 0);
-       if (fd < 0) {
-               PERROR("Cannot create SEQPACKET socket, giving up!\n");
-               return fd;
+               del_timer(&gsm_bs->socket_retry);
+               free(gsm_bs);
+               gsm_bs = NULL;
        }
 
        }
 
-       rc = connect(fd, (struct sockaddr *) &gsm->sun,
-                    sizeof(gsm->sun));
-       if (rc < 0) {
-               PERROR("Could not connect to MNCC socket, "
-                       "retrying in %u seconds\n", SOCKET_RETRY_TIMER);
-               close(fd);
-               schedule_timer(&gsm->socket_retry, SOCKET_RETRY_TIMER, 0);
-       } else {
-               PDEBUG(DEBUG_GSM, "Connected to MNCC socket!\n");
-               gsm->mncc_lfd.fd = fd;
-               register_fd(&gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, NULL, 0);
-       }
 
 
-       return 0;
+       return(rc);
 }
 
 int gsm_bs_init(void)
 {
 }
 
 int gsm_bs_init(void)
 {
-       gsm->sun.sun_family = AF_UNIX;
-       SCPY(gsm->sun.sun_path, "/tmp/bsc_mncc");
+       /* create gsm instance */
+       gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
 
 
-       memset(&gsm->socket_retry, 0, sizeof(gsm->socket_retry));
-       add_timer(&gsm->socket_retry, socket_retry_cb, NULL, 0);
+       gsm_bs->type = LCR_GSM_TYPE_NETWORK;
+       gsm_bs->sun.sun_family = AF_UNIX;
+       SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc");
+
+       memset(&gsm_bs->socket_retry, 0, sizeof(gsm_bs->socket_retry));
+       add_timer(&gsm_bs->socket_retry, mncc_socket_retry_cb, gsm_bs, 0);
 
        /* do the initial connect */
 
        /* do the initial connect */
-       socket_retry_cb(&gsm->socket_retry, NULL, 0);
+       mncc_socket_retry_cb(&gsm_bs->socket_retry, gsm_bs, 0);
 
 
-       /* dummy instance */
-       gsm->network = (void *)1;
+       generate_dtmf();
 
        return 0;
 }
 
        return 0;
 }
index 45bf083..a57b7c7 100644 (file)
--- a/gsm_bs.h
+++ b/gsm_bs.h
@@ -1,7 +1,3 @@
-extern "C" {
-#include <openbsc/gsm_data.h>
-#include <openbsc/mncc.h>
-}
 
 /* GSM port class */
 class Pgsm_bs : public Pgsm
 
 /* GSM port class */
 class Pgsm_bs : public Pgsm
@@ -22,11 +18,8 @@ class Pgsm_bs : public Pgsm
        int message_epoint(unsigned int epoint_id, int message_id, union parameter *param);
 };
 
        int message_epoint(unsigned int epoint_id, int message_id, union parameter *param);
 };
 
-int handle_gsm_bs(void);
 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_conf(struct gsm_conf *gsm_conf, char *conf_error);
 int gsm_bs_exit(int rc);
 int gsm_bs_init(void);
 
-extern "C" {
-int mncc_send(struct gsm_network *instance, int msg_type, void *data);
-};
+int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg);
index e091434..7e5b70e 100644 (file)
 \*****************************************************************************/ 
 
 #include "main.h"
 \*****************************************************************************/ 
 
 #include "main.h"
+#include "mncc.h"
 
 
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-extern "C" {
-#include <getopt.h>
-#include <arpa/inet.h>
-#include <libgen.h>
-
-#include <osmocom/core/select.h>
-#include <osmocom/core/talloc.h>
-#include <osmocom/core/gsmtap_util.h>
-
-#include <osmocom/bb/common/osmocom_data.h>
-#include <osmocom/bb/common/logging.h>
-#include <osmocom/bb/common/l1l2_interface.h>
-#include <osmocom/bb/mobile/app_mobile.h>
-}
-
-//char *config_dir = NULL;
 
 
-short vty_port = 4247;
-
-struct llist_head ms_list;
-struct log_target *stderr_target;
-void *l23_ctx = NULL;
-struct gsmtap_inst *gsmtap_inst;
+struct lcr_gsm *gsm_ms_first = NULL;
 
 static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index);
 
 
 static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index);
 
+#define DTMF_ST_IDLE           0       /* no DTMF active */
+#define DTMF_ST_START          1       /* DTMF started, waiting for resp. */
+#define DTMF_ST_MARK           2       /* wait tone duration */
+#define DTMF_ST_STOP           3       /* DTMF stopped, waiting for resp. */
+#define DTMF_ST_SPACE          4       /* wait space between tones */
+
 /*
  * 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)
 {
 /*
  * 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)
 {
-       struct osmocom_ms *ms = NULL;
+       struct lcr_gsm *gsm_ms = gsm_ms_first;
        char *ms_name = mISDNport->ifport->gsm_ms_name;
 
        char *ms_name = mISDNport->ifport->gsm_ms_name;
 
-       p_m_g_instance = NULL;
+       p_m_g_lcr_gsm = NULL;
 
 
-       llist_for_each_entry(ms, &ms_list, entity) {
-               if (!strcmp(ms->name, ms_name)) {
-                       p_m_g_instance = ms;
+       while (gsm_ms) {
+               if (gsm_ms->type == LCR_GSM_TYPE_MS && !strcmp(gsm_ms->name, ms_name)) {
+                       p_m_g_lcr_gsm = gsm_ms;
                        break;
                }
                        break;
                }
+               gsm_ms = gsm_ms->gsm_ms_next;
        }
 
        p_m_g_dtmf_state = DTMF_ST_IDLE;
        }
 
        p_m_g_dtmf_state = DTMF_ST_IDLE;
@@ -105,7 +89,7 @@ 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();
                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_instance, mncc->msg_type, mncc);
+               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;
                new_state(PORT_STATE_RELEASE);
                trigger_work(&p_m_g_delete);
                return;
@@ -126,7 +110,7 @@ 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, "port is blocked");
                end_trace();
                add_trace("cause", "value", "%d", mncc->cause.value);
                add_trace("reason", NULL, "port is blocked");
                end_trace();
-               send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+               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;
                new_state(PORT_STATE_RELEASE);
                trigger_work(&p_m_g_delete);
                return;
@@ -318,7 +302,7 @@ 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, "no channel");
                end_trace();
                add_trace("cause", "value", "%d", mncc->cause.value);
                add_trace("reason", NULL, "no channel");
                end_trace();
-               send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+               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;
                new_state(PORT_STATE_RELEASE);
                trigger_work(&p_m_g_delete);
                return;
@@ -342,7 +326,7 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        mode->lchan_mode = 0x01; /* GSM V1 */
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
        mode->lchan_mode = 0x01; /* GSM V1 */
        add_trace("mode", NULL, "0x%02x", mode->lchan_mode);
        end_trace();
-       send_and_free_mncc(p_m_g_instance, mode->msg_type, mode);
+       send_and_free_mncc(p_m_g_lcr_gsm, mode->msg_type, mode);
 
        /* send call proceeding */
        gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_CONF_REQ, DIRECTION_OUT);
 
        /* send call proceeding */
        gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_CONF_REQ, DIRECTION_OUT);
@@ -352,7 +336,7 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
        proceeding->fields |= MNCC_F_CCCAP;
        proceeding->cccap.dtmf = 1;
        end_trace();
        proceeding->fields |= MNCC_F_CCCAP;
        proceeding->cccap.dtmf = 1;
        end_trace();
-       send_and_free_mncc(p_m_g_instance, proceeding->msg_type, proceeding);
+       send_and_free_mncc(p_m_g_lcr_gsm, proceeding->msg_type, proceeding);
 
        new_state(PORT_STATE_IN_PROCEEDING);
 
 
        new_state(PORT_STATE_IN_PROCEEDING);
 
@@ -360,7 +344,7 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
                gsm_trace_header(p_m_mISDNport, this, MNCC_FRAME_RECV, DIRECTION_OUT);
                end_trace();
                frame = create_mncc(MNCC_FRAME_RECV, p_m_g_callref);
                gsm_trace_header(p_m_mISDNport, 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_instance, frame->msg_type, frame);
+               send_and_free_mncc(p_m_g_lcr_gsm, frame->msg_type, frame);
                p_m_g_tch_connected = 1;
        }
 
                p_m_g_tch_connected = 1;
        }
 
@@ -381,7 +365,7 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_
 /*
  * MS sends message to port
  */
 /*
  * MS sends message to port
  */
-static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg)
+int message_ms(struct lcr_gsm *gsm_ms, int msg_type, void *arg)
 {
        struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
        unsigned int callref = mncc->callref;
 {
        struct gsm_mncc *mncc = (struct gsm_mncc *)arg;
        unsigned int callref = mncc->callref;
@@ -392,30 +376,6 @@ static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg)
 
        /* Special messages */
        switch (msg_type) {
 
        /* Special messages */
        switch (msg_type) {
-       case MS_NEW:
-               PDEBUG(DEBUG_GSM, "MS %s comes available\n", ms->name);
-               return 0;
-       case MS_DELETE:
-               PDEBUG(DEBUG_GSM, "MS %s is removed\n", ms->name);
-               port = port_first;
-               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_instance == ms) {
-                                       struct lcr_msg *message;
-
-                                       pgsm_ms->p_m_g_instance = 0;
-                                       message = message_create(pgsm_ms->p_serial, ACTIVE_EPOINT(pgsm_ms->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE);
-                                       message->param.disconnectinfo.cause = 27;
-                                       message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
-                                       message_put(message);
-                                       pgsm_ms->new_state(PORT_STATE_RELEASE);
-                                       trigger_work(&pgsm_ms->p_m_g_delete);
-                               }
-                       }
-                       port = port->next;
-               }
-               return 0;
        }
 
        /* find callref */
        }
 
        /* find callref */
@@ -443,7 +403,7 @@ static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg)
                /* find gsm ms port */
                mISDNport = mISDNport_first;
                while(mISDNport) {
                /* find gsm ms port */
                mISDNport = mISDNport_first;
                while(mISDNport) {
-                       if (mISDNport->gsm_ms && !strcmp(mISDNport->ifport->gsm_ms_name, ms->name))
+                       if (mISDNport->gsm_ms && !strcmp(mISDNport->ifport->gsm_ms_name, gsm_ms->name))
                                break;
                        mISDNport = mISDNport->next;
                }
                                break;
                        mISDNport = mISDNport->next;
                }
@@ -460,7 +420,7 @@ static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg)
                        add_trace("cause", "location", "%d", rej->cause.location);
                        add_trace("cause", "value", "%d", rej->cause.value);
                        end_trace();
                        add_trace("cause", "location", "%d", rej->cause.location);
                        add_trace("cause", "value", "%d", rej->cause.value);
                        end_trace();
-                       send_and_free_mncc(ms, rej->msg_type, rej);
+                       send_and_free_mncc(gsm_ms, rej->msg_type, rej);
                        return 0;
                }
                /* creating port object, transparent until setup with hdlc */
                        return 0;
                }
                /* creating port object, transparent until setup with hdlc */
@@ -533,12 +493,12 @@ 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 */
        memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
 
        /* no instance */
-       if (!p_m_g_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);
                end_trace();
                message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
                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);
                end_trace();
                message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE);
-               message->param.disconnectinfo.cause = 27;
+               message->param.disconnectinfo.cause = 41;
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
                message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL;
                message_put(message);
                new_state(PORT_STATE_RELEASE);
@@ -670,7 +630,7 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame
        }
 
        end_trace();
        }
 
        end_trace();
-       send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc);
+       send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc);
 
        new_state(PORT_STATE_OUT_SETUP);
 
 
        new_state(PORT_STATE_OUT_SETUP);
 
@@ -700,7 +660,7 @@ void Pgsm_ms::dtmf_statemachine(struct gsm_mncc *mncc)
                PDEBUG(DEBUG_GSM, "start DTMF (keypad %c)\n",
                        dtmf->keypad);
                end_trace();
                PDEBUG(DEBUG_GSM, "start DTMF (keypad %c)\n",
                        dtmf->keypad);
                end_trace();
-               send_and_free_mncc(p_m_g_instance, dtmf->msg_type, dtmf);
+               send_and_free_mncc(p_m_g_lcr_gsm, dtmf->msg_type, dtmf);
                return;
        case DTMF_ST_START:
                if (mncc->msg_type != MNCC_START_DTMF_RSP) {
                return;
        case DTMF_ST_START:
                if (mncc->msg_type != MNCC_START_DTMF_RSP) {
@@ -716,7 +676,7 @@ void Pgsm_ms::dtmf_statemachine(struct gsm_mncc *mncc)
                dtmf = create_mncc(MNCC_STOP_DTMF_REQ, p_m_g_callref);
                p_m_g_dtmf_state = DTMF_ST_STOP;
                end_trace();
                dtmf = create_mncc(MNCC_STOP_DTMF_REQ, p_m_g_callref);
                p_m_g_dtmf_state = DTMF_ST_STOP;
                end_trace();
-               send_and_free_mncc(p_m_g_instance, dtmf->msg_type, dtmf);
+               send_and_free_mncc(p_m_g_lcr_gsm, dtmf->msg_type, dtmf);
                return;
        case DTMF_ST_STOP:
                schedule_timer(&p_m_g_dtmf_timer, 0, 120 * 1000);
                return;
        case DTMF_ST_STOP:
                schedule_timer(&p_m_g_dtmf_timer, 0, 120 * 1000);
@@ -820,87 +780,77 @@ int Pgsm_ms::message_epoint(unsigned int epoint_id, int message_id, union parame
 
 int gsm_ms_exit(int rc)
 {
 
 int gsm_ms_exit(int rc)
 {
-       l23_app_exit();
+       /* destroy all instances */
+       while (gsm_ms_first)
+               gsm_ms_delete(gsm_ms_first->name);
 
 
-       return(rc);
+       return rc;
 }
 
 int gsm_ms_init(void)
 {
 }
 
 int gsm_ms_init(void)
 {
-       const char *home;
-       size_t len;
-       const char osmocomcfg[] = ".osmocom/bb/mobile.cfg";
-       char *config_file = NULL;
+       return 0;
+}
 
 
-       INIT_LLIST_HEAD(&ms_list);
-       log_init(&log_info, NULL);
-       stderr_target = log_target_create_stderr();
-       log_add_target(stderr_target);
-       log_set_all_filter(stderr_target, 1);
+/* add a new GSM mobile instance */
+int gsm_ms_new(const char *name)
+{
+       struct lcr_gsm *gsm_ms = gsm_ms_first, **gsm_ms_p = &gsm_ms_first;
 
 
-       l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
+       while (gsm_ms) {
+               gsm_ms_p = &gsm_ms->gsm_ms_next;
+               gsm_ms = gsm_ms->gsm_ms_next;
+       }
 
 
-       log_parse_category_mask(stderr_target, "DNB:DCS:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM");
-       log_set_log_level(stderr_target, LOGL_INFO);
+       PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is created\n", name);
 
 
-#if 0
-       if (gsmtap_ip) {
-               rc = gsmtap_init(gsmtap_ip);
-               if (rc < 0) {
-                       fprintf(stderr, "Failed during gsmtap_init()\n");
-                       exit(1);
-               }
-       }
-#endif
+       /* create gsm instance */
+       gsm_ms = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm));
 
 
-       home = getenv("HOME");
-       if (home != NULL) {
-               len = strlen(home) + 1 + sizeof(osmocomcfg);
-               config_file = (char *)talloc_size(l23_ctx, len);
-               if (config_file != NULL)
-                               UNPRINT(config_file, len, "%s/%s", home, osmocomcfg);
-       }
-       /* save the config file directory name */
-       config_dir = talloc_strdup(l23_ctx, config_file);
-       config_dir = dirname(config_dir);
+       gsm_ms->type = LCR_GSM_TYPE_MS;
+       SCPY(gsm_ms->name, name);
+       gsm_ms->sun.sun_family = AF_UNIX;
+       SPRINT(gsm_ms->sun.sun_path, "/tmp/ms_mncc_%s", name);
 
 
-       l23_app_init(message_ms, config_file, vty_port);
+       memset(&gsm_ms->socket_retry, 0, sizeof(gsm_ms->socket_retry));
+       add_timer(&gsm_ms->socket_retry, mncc_socket_retry_cb, gsm_ms, 0);
 
 
-       return 0;
-}
+       /* do the initial connect */
+       mncc_socket_retry_cb(&gsm_ms->socket_retry, gsm_ms, 0);
 
 
-/* add a new GSM mobile instance */
-int gsm_ms_new(const char *name)
-{
-       PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is up\n", name);
+       *gsm_ms_p = gsm_ms;
 
        return 0;
 }
 
 int gsm_ms_delete(const char *name)
 {
 
        return 0;
 }
 
 int gsm_ms_delete(const char *name)
 {
-       struct osmocom_ms *ms;
-       int found = 0;
-       class Port *port;
-       class Pgsm_ms *pgsm_ms = NULL;
+       struct lcr_gsm *gsm_ms = gsm_ms_first, **gsm_ms_p = &gsm_ms_first;
+//     class Port *port;
+//     class Pgsm_ms *pgsm_ms = NULL;
 
 
-       PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is down\n", name);
+       PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is deleted\n", name);
 
 
-       llist_for_each_entry(ms, &ms_list, entity) {
-               if (!strcmp(ms->name, name)) {
-                       found = 1;
+       while (gsm_ms) {
+               if (gsm_ms->type == LCR_GSM_TYPE_MS && !strcmp(gsm_ms->name, name))
                        break;
                        break;
-               }
+               gsm_ms_p = &gsm_ms->gsm_ms_next;
+               gsm_ms = gsm_ms->gsm_ms_next;
        }
 
        }
 
-       if (!found)
+       if (!gsm_ms)
                return 0;
 
                return 0;
 
+/* not needed, because:
+ * - shutdown of interface will destry port instances locally
+ * - closing of socket will make remote socket destroy calls locally
+ */
+#if 0
        port = port_first;
        while(port) {
                if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_MS) {
                        pgsm_ms = (class Pgsm_ms *)port;
        port = port_first;
        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_instance == ms && pgsm_ms->p_m_g_callref) {
+                       if (pgsm_ms->p_m_g_lcr_gsm == gsm_ms && pgsm_ms->p_m_g_callref) {
                                struct gsm_mncc *rej;
 
                                rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_m_g_callref);
                                struct gsm_mncc *rej;
 
                                rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_m_g_callref);
@@ -913,28 +863,25 @@ int gsm_ms_delete(const char *name)
                                add_trace("cause", "location", "%d", rej->cause.location);
                                add_trace("cause", "value", "%d", rej->cause.value);
                                end_trace();
                                add_trace("cause", "location", "%d", rej->cause.location);
                                add_trace("cause", "value", "%d", rej->cause.value);
                                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);
                        }
                }
        }
                        }
                }
        }
+#endif
 
 
-       return 0;
-}
-
-/*
- * handles bsc select function within LCR's main loop
- */
-int handle_gsm_ms(int *_quit)
-{
-       int work = 0, quit = 0;
+       if (gsm_ms->mncc_lfd.fd > -1) {
+               close(gsm_ms->mncc_lfd.fd);
+               unregister_fd(&gsm_ms->mncc_lfd);
+       }
+       del_timer(&gsm_ms->socket_retry);
 
 
-       if (l23_app_work(&quit))
-               work = 1;
-       if (quit && llist_empty(&ms_list))
-               *_quit = 1;
-//     debug_reset_context();
-       if (osmo_select_main(1)) /* polling */
-               work = 1;
+       /* remove instance from list */
+       *gsm_ms_p = gsm_ms->gsm_ms_next;
+       FREE(gsm_ms, sizeof(struct lcr_gsm));
 
 
-       return work;
+       return 0;
 }
 
 }
 
+
index e30f2fd..70ea825 100644 (file)
--- a/gsm_ms.h
+++ b/gsm_ms.h
@@ -1,10 +1,3 @@
-#ifndef _GNU_SOURCE
-#define _GNU_SOURCE
-#endif
-extern "C" {
-#include <osmocom/bb/common/osmocom_data.h>
-#include <osmocom/bb/mobile/mncc.h>
-}
 
 /* GSM port class */
 class Pgsm_ms : public Pgsm
 
 /* GSM port class */
 class Pgsm_ms : public Pgsm
@@ -26,10 +19,10 @@ class Pgsm_ms : public Pgsm
        int message_epoint(unsigned int epoint_id, int message_id, union parameter *param);
 };
 
        int message_epoint(unsigned int epoint_id, int message_id, union parameter *param);
 };
 
-int handle_gsm_ms(int *quit);
 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_delete(const char *name);
 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_delete(const char *name);
+int message_ms(struct lcr_gsm *lcr_gsm, int msg_type, void *arg);
 
 
index 4e432af..57d7fe8 100644 (file)
@@ -897,11 +897,6 @@ static int inter_gsm_bs(struct interface *interface, char *filename, int line, c
        struct interface_port *ifport;
        struct interface *searchif;
 
        struct interface_port *ifport;
        struct interface *searchif;
 
-       /* check gsm */
-       if (!gsm) {
-               SPRINT(interface_error, "Error in %s (line %d): GSM is not activated.\n", filename, line);
-               return(-1);
-       }
        searchif = interface_newlist;
        while(searchif) {
                ifport = searchif->ifport;
        searchif = interface_newlist;
        while(searchif) {
                ifport = searchif->ifport;
@@ -936,13 +931,6 @@ static int inter_gsm_ms(struct interface *interface, char *filename, int line, c
 #else
        struct interface_port *ifport, *searchifport;
        struct interface *searchif;
 #else
        struct interface_port *ifport, *searchifport;
        struct interface *searchif;
-       char *element;
-
-       /* check gsm */
-       if (!gsm) {
-               SPRINT(interface_error, "Error in %s (line %d): GSM is not activated.\n", filename, line);
-               return(-1);
-       }
 
        /* set portname */
        if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
 
        /* set portname */
        if (inter_portname(interface, filename, line, (char *)"portname", options.loopback_lcr))
@@ -955,12 +943,11 @@ static int inter_gsm_ms(struct interface *interface, char *filename, int line, c
        ifport->gsm_ms = 1;
 
        /* copy values */
        ifport->gsm_ms = 1;
 
        /* copy values */
-       element = strsep(&value, " ");
-       if (!element || !element[0]) {
+       if (!value || !value[0]) {
                SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
                return(-1);
        }
                SPRINT(interface_error, "Error in %s (line %d): Missing MS name and socket name.\n", filename, line);
                return(-1);
        }
-       SCPY(ifport->gsm_ms_name, element);
+       SCPY(ifport->gsm_ms_name, value);
 
        /* check if name is used multiple times */
        searchif = interface_newlist;
 
        /* check if name is used multiple times */
        searchif = interface_newlist;
@@ -1539,6 +1526,10 @@ void relink_interfaces(void)
                        if (ifport->gsm_ms)
                                gsm_ms_delete(ifport->gsm_ms_name);
 #endif
                        if (ifport->gsm_ms)
                                gsm_ms_delete(ifport->gsm_ms_name);
 #endif
+#ifdef WITH_GSM_BS
+                       if (ifport->gsm_bs)
+                               gsm_bs_exit(0);
+#endif
                        mISDNport_close(mISDNport);
                        goto closeagain;
                }
                        mISDNport_close(mISDNport);
                        goto closeagain;
                }
@@ -1585,6 +1576,10 @@ void load_port(struct interface_port *ifport)
                if (ifport->gsm_ms)
                        gsm_ms_new(ifport->gsm_ms_name);
 #endif
                if (ifport->gsm_ms)
                        gsm_ms_new(ifport->gsm_ms_name);
 #endif
+#ifdef WITH_GSM_BS
+               if (ifport->gsm_bs)
+                       gsm_bs_init();
+#endif
        } else {
                ifport->block = 2; /* not available */
        }
        } else {
                ifport->block = 2; /* not available */
        }
diff --git a/main.c b/main.c
index 6eb2b68..ce05452 100644 (file)
--- a/main.c
+++ b/main.c
 #undef PACKAGE_VERSION
 #endif
 #include "config.h"
 #undef PACKAGE_VERSION
 #endif
 #include "config.h"
-#ifdef WITH_GSM_MS
-extern "C" {
-#include <osmocom/core/signal.h>
-}
-#endif
 
 //MESSAGES
 
 
 //MESSAGES
 
@@ -146,9 +141,6 @@ void _printerror(const char *function, int line, const char *fmt, ...)
 void sighandler(int sigset)
 {
        struct sched_param schedp;
 void sighandler(int sigset)
 {
        struct sched_param schedp;
-#ifdef WITH_GSM_MS
-       int wait_ms = 0;
-#endif
 
        if (sigset == SIGHUP)
                return;
 
        if (sigset == SIGHUP)
                return;
@@ -156,13 +148,6 @@ void sighandler(int sigset)
                return;
        fprintf(stderr, "LCR: Signal received: %d\n", sigset);
        PDEBUG(DEBUG_LOG, "Signal received: %d\n", sigset);
                return;
        fprintf(stderr, "LCR: Signal received: %d\n", sigset);
        PDEBUG(DEBUG_LOG, "Signal received: %d\n", sigset);
-#ifdef WITH_GSM_MS
-       if (!wait_ms) {
-               wait_ms = 1;
-               osmo_signal_dispatch(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
-               return;
-       }
-#endif
        if (!quit) {
                quit = sigset;
                /* set scheduler & priority */
        if (!quit) {
                quit = sigset;
                /* set scheduler & priority */
@@ -180,7 +165,7 @@ void sighandler(int sigset)
  */
 int main(int argc, char *argv[])
 {
  */
 int main(int argc, char *argv[])
 {
-#if defined WITH_GSM_BS || defined WITH_GSM_MS
+#if 0
        double                  now_d, last_d;
        int                     all_idle;
 #endif
        double                  now_d, last_d;
        int                     all_idle;
 #endif
@@ -383,24 +368,22 @@ int main(int argc, char *argv[])
 
 #if defined WITH_GSM_BS || defined WITH_GSM_MS
        /* init gsm */
 
 #if defined WITH_GSM_BS || defined WITH_GSM_MS
        /* init gsm */
-       if (options.gsm && gsm_init()) {
+       if (gsm_init()) {
                fprintf(stderr, "GSM initialization failed.\n");
                goto free;
        }
                fprintf(stderr, "GSM initialization failed.\n");
                goto free;
        }
-#else
-       if (options.gsm) {
-               fprintf(stderr, "GSM is enabled, but not compiled. Use --with-gsm-bs or --with-gsm-ms while configure!\n");
-               goto free;
-       }
 #endif
 #endif
+#if 0
+init is done when interface is up
 #ifdef WITH_GSM_BS
 #ifdef WITH_GSM_BS
-       if (options.gsm && gsm_bs_init()) {
+       if (gsm_bs_init()) {
                fprintf(stderr, "GSM BS initialization failed.\n");
                goto free;
        }
 #endif
                fprintf(stderr, "GSM BS initialization failed.\n");
                goto free;
        }
 #endif
+#endif
 #ifdef WITH_GSM_MS
 #ifdef WITH_GSM_MS
-       if (options.gsm && gsm_ms_init()) {
+       if (gsm_ms_init()) {
                fprintf(stderr, "GSM MS initialization failed.\n");
                goto free;
        }
                fprintf(stderr, "GSM MS initialization failed.\n");
                goto free;
        }
@@ -467,11 +450,11 @@ int main(int argc, char *argv[])
        printf("%s\n", tracetext);
        end_trace();
        quit = 0;
        printf("%s\n", tracetext);
        end_trace();
        quit = 0;
-#if defined WITH_GSM_BS || defined WITH_GSM_MS
+#if 0
        GET_NOW();
 #endif
        while(!quit) {
        GET_NOW();
 #endif
        while(!quit) {
-#if defined WITH_GSM_BS || defined WITH_GSM_MS
+#if 0
                last_d = now_d;
                GET_NOW();
                if (now_d-last_d > 1.0) {
                last_d = now_d;
                GET_NOW();
                if (now_d-last_d > 1.0) {
@@ -483,23 +466,14 @@ int main(int argc, char *argv[])
                /* must be processed after all queues, so they are empty */
                if (select_main(1, NULL, NULL, NULL))
                        all_idle = 0;
                /* must be processed after all queues, so they are empty */
                if (select_main(1, NULL, NULL, NULL))
                        all_idle = 0;
-               /* handle gsm */
-               if (options.gsm) {
-                       if (handle_gsm())
-                               all_idle = 0;
-#ifdef WITH_GSM_MS
-                       if (handle_gsm_ms(&quit))
-                               all_idle = 0;
-#endif
-               }
                if (all_idle) {
                        usleep(10000);
                }
 #else
                if (all_idle) {
                        usleep(10000);
                }
 #else
-               if (options.polling)
+               if (options.polling) {
                        if (!select_main(1, NULL, NULL, NULL))
                                usleep(10000);
                        if (!select_main(1, NULL, NULL, NULL))
                                usleep(10000);
-               else
+               else
                        select_main(0, NULL, NULL, NULL);
 #endif
        }
                        select_main(0, NULL, NULL, NULL);
 #endif
        }
@@ -604,17 +578,18 @@ free:
                mISDN_deinitialize();
 
        /* free gsm */
                mISDN_deinitialize();
 
        /* free gsm */
-       if (options.gsm) {
+#if 0
+exit is done when interface is down
 #ifdef WITH_GSM_BS
 #ifdef WITH_GSM_BS
-               gsm_bs_exit(0);
+       gsm_bs_exit(0);
+#endif
 #endif
 #ifdef WITH_GSM_MS
 #endif
 #ifdef WITH_GSM_MS
-               gsm_ms_exit(0);
+       gsm_ms_exit(0);
 #endif
 #if defined WITH_GSM_BS || defined WITH_GSM_MS
 #endif
 #if defined WITH_GSM_BS || defined WITH_GSM_MS
-               gsm_exit(0);
+       gsm_exit(0);
 #endif
 #endif
-       }
 
        /* close loopback, if used by GSM or remote */
        if (mISDNloop.sock > -1)
 
        /* close loopback, if used by GSM or remote */
        if (mISDNloop.sock > -1)
diff --git a/mncc.h b/mncc.h
new file mode 100644 (file)
index 0000000..27c8364
--- /dev/null
+++ b/mncc.h
@@ -0,0 +1,186 @@
+
+#define MNCC_SETUP_REQ         0x0101
+#define MNCC_SETUP_IND         0x0102
+#define MNCC_SETUP_RSP         0x0103
+#define MNCC_SETUP_CNF         0x0104
+#define MNCC_SETUP_COMPL_REQ   0x0105
+#define MNCC_SETUP_COMPL_IND   0x0106
+/* MNCC_REJ_* is perfomed via MNCC_REL_* */
+#define MNCC_CALL_CONF_IND     0x0107
+#define MNCC_CALL_PROC_REQ     0x0108
+#define MNCC_PROGRESS_REQ      0x0109
+#define MNCC_ALERT_REQ         0x010a
+#define MNCC_ALERT_IND         0x010b
+#define MNCC_NOTIFY_REQ                0x010c
+#define MNCC_NOTIFY_IND                0x010d
+#define MNCC_DISC_REQ          0x010e
+#define MNCC_DISC_IND          0x010f
+#define MNCC_REL_REQ           0x0110
+#define MNCC_REL_IND           0x0111
+#define MNCC_REL_CNF           0x0112
+#define MNCC_FACILITY_REQ      0x0113
+#define MNCC_FACILITY_IND      0x0114
+#define MNCC_START_DTMF_IND    0x0115
+#define MNCC_START_DTMF_RSP    0x0116
+#define MNCC_START_DTMF_REJ    0x0117
+#define MNCC_STOP_DTMF_IND     0x0118
+#define MNCC_STOP_DTMF_RSP     0x0119
+#define MNCC_MODIFY_REQ                0x011a
+#define MNCC_MODIFY_IND                0x011b
+#define MNCC_MODIFY_RSP                0x011c
+#define MNCC_MODIFY_CNF                0x011d
+#define MNCC_MODIFY_REJ                0x011e
+#define MNCC_HOLD_IND          0x011f
+#define MNCC_HOLD_CNF          0x0120
+#define MNCC_HOLD_REJ          0x0121
+#define MNCC_RETRIEVE_IND      0x0122
+#define MNCC_RETRIEVE_CNF      0x0123
+#define MNCC_RETRIEVE_REJ      0x0124
+#define MNCC_USERINFO_REQ      0x0125
+#define MNCC_USERINFO_IND      0x0126
+#define MNCC_REJ_REQ           0x0127
+#define MNCC_REJ_IND           0x0128
+#define MNCC_PROGRESS_IND      0x0129
+#define MNCC_CALL_PROC_IND     0x012a
+#define MNCC_CALL_CONF_REQ     0x012b
+#define MNCC_START_DTMF_REQ    0x012c
+#define MNCC_STOP_DTMF_REQ     0x012d
+#define MNCC_HOLD_REQ          0x012e
+#define MNCC_RETRIEVE_REQ      0x012f
+
+#define MNCC_BRIDGE            0x0200
+#define MNCC_FRAME_RECV                0x0201
+#define MNCC_FRAME_DROP                0x0202
+#define MNCC_LCHAN_MODIFY      0x0203
+
+#define GSM_TCHF_FRAME         0x0300
+#define GSM_TCHF_FRAME_EFR     0x0301
+
+#define GSM_MAX_FACILITY       128
+#define GSM_MAX_SSVERSION      128
+#define GSM_MAX_USERUSER       128
+
+#define        MNCC_F_BEARER_CAP       0x0001
+#define MNCC_F_CALLED          0x0002
+#define MNCC_F_CALLING         0x0004
+#define MNCC_F_REDIRECTING     0x0008
+#define MNCC_F_CONNECTED       0x0010
+#define MNCC_F_CAUSE           0x0020
+#define MNCC_F_USERUSER                0x0040
+#define MNCC_F_PROGRESS                0x0080
+#define MNCC_F_EMERGENCY       0x0100
+#define MNCC_F_FACILITY                0x0200
+#define MNCC_F_SSVERSION       0x0400
+#define MNCC_F_CCCAP           0x0800
+#define MNCC_F_KEYPAD          0x1000
+#define MNCC_F_SIGNAL          0x2000
+
+#define GSM_MAX_FACILITY       128
+#define GSM_MAX_SSVERSION      128
+#define GSM_MAX_USERUSER       128
+
+/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
+struct gsm_mncc_bearer_cap {
+       int             transfer;       /* Information Transfer Capability */
+       int             mode;           /* Transfer Mode */
+       int             coding;         /* Coding Standard */
+       int             radio;          /* Radio Channel Requirement */
+       int             speech_ctm;     /* CTM text telephony indication */
+       int             speech_ver[8];  /* Speech version indication */
+};
+
+struct gsm_mncc_number {
+       int             type;
+       int             plan;
+       int             present;
+       int             screen;
+       char            number[33];
+};
+
+struct gsm_mncc_cause {
+       int             location;
+       int             coding;
+       int             rec;
+       int             rec_val;
+       int             value;
+       int             diag_len;
+       char            diag[32];
+};
+
+struct gsm_mncc_useruser {
+       int             proto;
+       char            info[GSM_MAX_USERUSER + 1]; /* + termination char */
+};
+
+struct gsm_mncc_progress {
+       int             coding;
+       int             location;
+       int             descr;
+};
+
+struct gsm_mncc_facility {
+       int             len;
+       char            info[GSM_MAX_FACILITY];
+};
+
+struct gsm_mncc_ssversion {
+       int             len;
+       char            info[GSM_MAX_SSVERSION];
+};
+
+struct gsm_mncc_cccap {
+       int             dtmf;
+       int             pcp;
+};
+
+enum {
+       GSM_MNCC_BCAP_SPEECH    = 0,
+       GSM_MNCC_BCAP_UNR_DIG   = 1,
+       GSM_MNCC_BCAP_AUDIO     = 2,
+       GSM_MNCC_BCAP_FAX_G3    = 3,
+       GSM_MNCC_BCAP_OTHER_ITC = 5,
+       GSM_MNCC_BCAP_RESERVED  = 7,
+};
+
+struct gsm_mncc {
+       /* context based information */
+       u_int32_t       msg_type;
+       u_int32_t       callref;
+
+       /* which fields are present */
+       u_int32_t       fields;
+
+       /* data derived informations (MNCC_F_ based) */
+       struct gsm_mncc_bearer_cap      bearer_cap;
+       struct gsm_mncc_number          called;
+       struct gsm_mncc_number          calling;
+       struct gsm_mncc_number          redirecting;
+       struct gsm_mncc_number          connected;
+       struct gsm_mncc_cause           cause;
+       struct gsm_mncc_progress        progress;
+       struct gsm_mncc_useruser        useruser;
+       struct gsm_mncc_facility        facility;
+       struct gsm_mncc_cccap           cccap;
+       struct gsm_mncc_ssversion       ssversion;
+       struct  {
+               int             sup;
+               int             inv;
+       } clir;
+       int             signal;
+
+       /* data derived information, not MNCC_F based */
+       int             keypad;
+       int             more;
+       int             notify; /* 0..127 */
+       int             emergency;
+       char            imsi[16];
+
+       unsigned char   lchan_mode;
+};
+
+struct gsm_data_frame {
+       u_int32_t       msg_type;
+       u_int32_t       callref;
+       unsigned char   data[0];
+};
+
index 7fb9bcb..b1c52cf 100644 (file)
--- a/options.c
+++ b/options.c
@@ -35,7 +35,6 @@ struct options options = {
        0700,                           /* rights of lcr admin socket */
        -1,                             /* socket user (-1= no change) */
        -1,                             /* socket group (-1= no change) */
        0700,                           /* rights of lcr admin socket */
        -1,                             /* socket user (-1= no change) */
        -1,                             /* socket group (-1= no change) */
-       0,                              /* enable gsm */
        1,                              /* use polling of main loop */
        "mISDN_l1loop.1",               /* GSM/Asterisk side */
        "mISDN_l1loop.2",               /* LCR side */
        1,                              /* use polling of main loop */
        "mISDN_l1loop.1",               /* GSM/Asterisk side */
        "mISDN_l1loop.2",               /* LCR side */
@@ -236,9 +235,6 @@ int read_options(char *options_error)
                if (!strcmp(option,"socketrights")) {
                        options.socketrights = strtol(param, NULL, 0);
                } else
                if (!strcmp(option,"socketrights")) {
                        options.socketrights = strtol(param, NULL, 0);
                } else
-               if (!strcmp(option,"gsm")) {
-                       options.gsm = 1;
-               } else
                if (!strcmp(option,"polling")) {
                        options.polling = 1;
                } else
                if (!strcmp(option,"polling")) {
                        options.polling = 1;
                } else
index c7f9f8f..7ea5166 100644 (file)
--- a/options.h
+++ b/options.h
@@ -29,7 +29,6 @@ struct options {
        int     socketrights;           /* rights of lcr admin socket */
        int     socketuser;             /* socket chown to this user */
        int     socketgroup;            /* socket chgrp to this group */
        int     socketrights;           /* rights of lcr admin socket */
        int     socketuser;             /* socket chown to this user */
        int     socketgroup;            /* socket chgrp to this group */
-       int     gsm;                    /* enable gsm support */
        int     polling;
        char loopback_ext[64];          /* loopback interface GSM side */
        char loopback_lcr[64];          /* loopback interface LCR side */
        int     polling;
        char loopback_ext[64];          /* loopback interface GSM side */
        char loopback_lcr[64];          /* loopback interface LCR side */