From: Andreas Eversberg Date: Fri, 2 Sep 2011 09:08:56 +0000 (+0200) Subject: Support of GSM uses socket interface for both network and mobile X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=commitdiff_plain;h=97aa0881beacf536e3a2296381c055887583db8f Support of GSM uses socket interface for both network and mobile 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". --- diff --git a/Makefile.am b/Makefile.am index 0da7bb0..61ddb8c 100644 --- a/Makefile.am +++ b/Makefile.am @@ -62,7 +62,7 @@ endif 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 @@ -70,16 +70,9 @@ endif 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 @@ -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 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 \ diff --git a/configure.ac b/configure.ac index cf41b2c..4452371 100644 --- a/configure.ac +++ b/configure.ac @@ -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], - [compile with OpenBSC support @<:@default=check@:>@]) + [compile with OpenBSC support @<:@default=no@:>@]) ], [], [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], - [compile with Osmocom-bb support @<:@default=check@:>@]) + [compile with Osmocom-bb support @<:@default=no@:>@]) ], [], [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") diff --git a/default/openbsc.cfg b/default/openbsc.cfg deleted file mode 100644 index 05ec4c0..0000000 --- a/default/openbsc.cfg +++ /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 - - diff --git a/default/options.conf b/default/options.conf index d1f4d6b..3c222d2 100644 --- a/default/options.conf +++ b/default/options.conf @@ -104,18 +104,6 @@ # 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 diff --git a/gsm.cpp b/gsm.cpp index 14f534c..9236ed2 100644 --- a/gsm.cpp +++ b/gsm.cpp @@ -4,12 +4,14 @@ ** ** **---------------------------------------------------------------------------** ** Copyright: Andreas Eversberg ** +** MNCC-Interface: Harald Welte ** ** ** ** mISDN gsm ** ** ** \*****************************************************************************/ #include "main.h" +#include "mncc.h" #ifndef _GNU_SOURCE #define _GNU_SOURCE @@ -19,8 +21,11 @@ extern "C" { } #include +#include -struct lcr_gsm *gsm = NULL; +#define SOCKET_RETRY_TIMER 5 + +//struct lcr_gsm *gsm = NULL; int new_callref = 1; @@ -29,147 +34,53 @@ static const struct _value_string { int msg_type; const char *name; } mncc_names[] = { -#if defined(MNCC_SETUP_REQ) { MNCC_SETUP_REQ, "MNCC_SETUP_REQ" }, -#endif -#if defined(MNCC_SETUP_IND) { MNCC_SETUP_IND, "MNCC_SETUP_IND" }, -#endif -#if defined(MNCC_SETUP_RSP) { MNCC_SETUP_RSP, "MNCC_SETUP_RSP" }, -#endif -#if defined(MNCC_SETUP_CNF) { MNCC_SETUP_CNF, "MNCC_SETUP_CNF" }, -#endif -#if defined(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" }, -#endif -#if defined(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" }, -#endif -#if defined(MNCC_PROGRESS_REQ) { MNCC_PROGRESS_REQ, "MNCC_PROGRESS_REQ" }, -#endif -#if defined(MNCC_ALERT_REQ) { MNCC_ALERT_REQ, "MNCC_ALERT_REQ" }, -#endif -#if defined(MNCC_ALERT_IND) { MNCC_ALERT_IND, "MNCC_ALERT_IND" }, -#endif -#if defined(MNCC_NOTIFY_REQ) { MNCC_NOTIFY_REQ, "MNCC_NOTIFY_REQ" }, -#endif -#if defined(MNCC_NOTIFY_IND) { MNCC_NOTIFY_IND, "MNCC_NOTIFY_IND" }, -#endif -#if defined(MNCC_DISC_REQ) { MNCC_DISC_REQ, "MNCC_DISC_REQ" }, -#endif -#if defined(MNCC_DISC_IND) { MNCC_DISC_IND, "MNCC_DISC_IND" }, -#endif -#if defined(MNCC_REL_REQ) { MNCC_REL_REQ, "MNCC_REL_REQ" }, -#endif -#if defined(MNCC_REL_IND) { MNCC_REL_IND, "MNCC_REL_IND" }, -#endif -#if defined(MNCC_REL_CNF) { MNCC_REL_CNF, "MNCC_REL_CNF" }, -#endif -#if defined(MNCC_FACILITY_REQ) { MNCC_FACILITY_REQ, "MNCC_FACILITY_REQ" }, -#endif -#if defined(MNCC_FACILITY_IND) { MNCC_FACILITY_IND, "MNCC_FACILITY_IND" }, -#endif -#if defined(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" }, -#endif -#if defined(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" }, -#endif -#if defined(MNCC_STOP_DTMF_RSP) { MNCC_STOP_DTMF_RSP, "MNCC_STOP_DTMF_RSP" }, -#endif -#if defined(MNCC_MODIFY_REQ) { MNCC_MODIFY_REQ, "MNCC_MODIFY_REQ" }, -#endif -#if defined(MNCC_MODIFY_IND) { MNCC_MODIFY_IND, "MNCC_MODIFY_IND" }, -#endif -#if defined(MNCC_MODIFY_RSP) { MNCC_MODIFY_RSP, "MNCC_MODIFY_RSP" }, -#endif -#if defined(MNCC_MODIFY_CNF) { MNCC_MODIFY_CNF, "MNCC_MODIFY_CNF" }, -#endif -#if defined(MNCC_MODIFY_REJ) { MNCC_MODIFY_REJ, "MNCC_MODIFY_REJ" }, -#endif -#if defined(MNCC_HOLD_IND) { MNCC_HOLD_IND, "MNCC_HOLD_IND" }, -#endif -#if defined(MNCC_HOLD_CNF) { MNCC_HOLD_CNF, "MNCC_HOLD_CNF" }, -#endif -#if defined(MNCC_HOLD_REJ) { MNCC_HOLD_REJ, "MNCC_HOLD_REJ" }, -#endif -#if defined(MNCC_RETRIEVE_IND) { MNCC_RETRIEVE_IND, "MNCC_RETRIEVE_IND" }, -#endif -#if defined(MNCC_RETRIEVE_CNF) { MNCC_RETRIEVE_CNF, "MNCC_RETRIEVE_CNF" }, -#endif -#if defined(MNCC_RETRIEVE_REJ) { MNCC_RETRIEVE_REJ, "MNCC_RETRIEVE_REJ" }, -#endif -#if defined(MNCC_USERINFO_REQ) { MNCC_USERINFO_REQ, "MNCC_USERINFO_REQ" }, -#endif -#if defined(MNCC_USERINFO_IND) { MNCC_USERINFO_IND, "MNCC_USERINFO_IND" }, -#endif -#if defined(MNCC_REJ_REQ) { MNCC_REJ_REQ, "MNCC_REJ_REQ" }, -#endif -#if defined(MNCC_REJ_IND) { MNCC_REJ_IND, "MNCC_REJ_IND" }, -#endif -#if defined(MNCC_PROGRESS_IND) { MNCC_PROGRESS_IND, "MNCC_PROGRESS_IND" }, -#endif -#if defined(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" }, -#endif -#if defined(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" }, -#endif -#if defined(MNCC_HOLD_REQ) { MNCC_HOLD_REQ, "MNCC_HOLD_REQ " }, -#endif -#if defined(MNCC_RETRIEVE_REQ) { MNCC_RETRIEVE_REQ, "MNCC_RETRIEVE_REQ" }, -#endif { 0, NULL } }; @@ -185,6 +96,8 @@ const char *mncc_name(int value) return "unknown"; } +static int mncc_send(struct lcr_gsm *lcr_gsm, int msg_type, void *data); + /* * 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); } -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; - 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); @@ -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_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; @@ -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); -#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(); - 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); - 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; } } @@ -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); - 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; } } @@ -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(); - 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)); @@ -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); - 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; } } @@ -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); - 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; } } @@ -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(); - 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) { @@ -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; - 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(); - 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); @@ -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); - 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; } } @@ -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(); - 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); } @@ -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(); - 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); @@ -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); - 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; } } @@ -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(); - 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); @@ -985,12 +891,6 @@ static int b_handler(struct lcr_fd *fd, unsigned int what, void *instance, int i int gsm_exit(int rc) { - /* free gsm instance */ - if (gsm) { - free(gsm); - gsm = NULL; - } - return(rc); } @@ -999,14 +899,214 @@ int gsm_init(void) /* 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; } -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; } diff --git a/gsm.h b/gsm.h index c12baa0..3ecaf0d 100644 --- a/gsm.h +++ b/gsm.h @@ -9,8 +9,15 @@ struct mncc_q_entry { char data[0]; /* struct gsm_mncc */ }; +enum { + LCR_GSM_TYPE_NETWORK, + LCR_GSM_TYPE_MS, +}; + 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; @@ -19,8 +26,6 @@ struct lcr_gsm { struct sockaddr_un sun; /* Socket address of MNCC socket */ }; -extern struct lcr_gsm *gsm; - /* 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(); - 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 */ - 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 */ @@ -68,10 +73,10 @@ class Pgsm : public PmISDN }; 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); -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 mncc_socket_retry_cb(struct lcr_timer *timer, void *inst, int index); diff --git a/gsm_bs.cpp b/gsm_bs.cpp index 2da06c7..285c88f 100644 --- a/gsm_bs.cpp +++ b/gsm_bs.cpp @@ -10,23 +10,9 @@ \*****************************************************************************/ #include "main.h" -#include "config.h" +#include "mncc.h" -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -extern "C" { -#include -#include - -#include -#include - -#include -#include -} - -#define SOCKET_RETRY_TIMER 5 +struct lcr_gsm *gsm_bs = NULL; /* * 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) { - p_m_g_instance = gsm->network; + p_m_g_lcr_gsm = gsm_bs; 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; - 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 */ @@ -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; - 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; @@ -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); - 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); - 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; } } @@ -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); - 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); - 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; } } @@ -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(); - 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; @@ -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(); - 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; @@ -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(); - 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; @@ -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(); - 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); @@ -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(); - 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); @@ -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); - 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; } @@ -413,7 +399,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ /* * 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; @@ -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(); - 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 */ @@ -565,12 +551,12 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame memcpy(&p_redirinfo, ¶m->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); - 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); @@ -762,7 +748,7 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame //todo end_trace(); - send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc); + send_and_free_mncc(p_m_g_lcr_gsm, mncc->msg_type, mncc); 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) { - 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) { - 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 */ - 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; } diff --git a/gsm_bs.h b/gsm_bs.h index 45bf083..a57b7c7 100644 --- a/gsm_bs.h +++ b/gsm_bs.h @@ -1,7 +1,3 @@ -extern "C" { -#include -#include -} /* 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 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); -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); diff --git a/gsm_ms.cpp b/gsm_ms.cpp index e091434..7e5b70e 100644 --- a/gsm_ms.cpp +++ b/gsm_ms.cpp @@ -10,51 +10,35 @@ \*****************************************************************************/ #include "main.h" +#include "mncc.h" -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -extern "C" { -#include -#include -#include - -#include -#include -#include - -#include -#include -#include -#include -} - -//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); +#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) { - struct osmocom_ms *ms = NULL; + struct lcr_gsm *gsm_ms = gsm_ms_first; 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; } + gsm_ms = gsm_ms->gsm_ms_next; } 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(); - 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; @@ -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(); - 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; @@ -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(); - 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; @@ -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(); - 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); @@ -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(); - 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); @@ -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); - 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; } @@ -381,7 +365,7 @@ void Pgsm_ms::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ /* * 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; @@ -392,30 +376,6 @@ static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg) /* 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 */ @@ -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) { - 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; } @@ -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(); - 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 */ @@ -533,12 +493,12 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame memcpy(&p_redirinfo, ¶m->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); - 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); @@ -670,7 +630,7 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame } 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); @@ -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(); - 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) { @@ -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(); - 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); @@ -820,87 +780,77 @@ int Pgsm_ms::message_epoint(unsigned int epoint_id, int message_id, union parame 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) { - 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) { - 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; - } + gsm_ms_p = &gsm_ms->gsm_ms_next; + gsm_ms = gsm_ms->gsm_ms_next; } - if (!found) + if (!gsm_ms) 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; - 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); @@ -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(); + 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; } + diff --git a/gsm_ms.h b/gsm_ms.h index e30f2fd..70ea825 100644 --- a/gsm_ms.h +++ b/gsm_ms.h @@ -1,10 +1,3 @@ -#ifndef _GNU_SOURCE -#define _GNU_SOURCE -#endif -extern "C" { -#include -#include -} /* 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 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 message_ms(struct lcr_gsm *lcr_gsm, int msg_type, void *arg); diff --git a/interface.c b/interface.c index 4e432af..57d7fe8 100644 --- a/interface.c +++ b/interface.c @@ -897,11 +897,6 @@ static int inter_gsm_bs(struct interface *interface, char *filename, int line, c 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; @@ -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; - 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)) @@ -955,12 +943,11 @@ static int inter_gsm_ms(struct interface *interface, char *filename, int line, c 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); } - SCPY(ifport->gsm_ms_name, element); + SCPY(ifport->gsm_ms_name, value); /* 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 +#ifdef WITH_GSM_BS + if (ifport->gsm_bs) + gsm_bs_exit(0); +#endif 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 +#ifdef WITH_GSM_BS + if (ifport->gsm_bs) + gsm_bs_init(); +#endif } else { ifport->block = 2; /* not available */ } diff --git a/main.c b/main.c index 6eb2b68..ce05452 100644 --- a/main.c +++ b/main.c @@ -14,11 +14,6 @@ #undef PACKAGE_VERSION #endif #include "config.h" -#ifdef WITH_GSM_MS -extern "C" { -#include -} -#endif //MESSAGES @@ -146,9 +141,6 @@ void _printerror(const char *function, int line, const char *fmt, ...) void sighandler(int sigset) { struct sched_param schedp; -#ifdef WITH_GSM_MS - int wait_ms = 0; -#endif 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); -#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 */ @@ -180,7 +165,7 @@ void sighandler(int sigset) */ 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 @@ -383,24 +368,22 @@ int main(int argc, char *argv[]) #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; } -#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 +#if 0 +init is done when interface is up #ifdef WITH_GSM_BS - if (options.gsm && gsm_bs_init()) { + if (gsm_bs_init()) { fprintf(stderr, "GSM BS initialization failed.\n"); goto free; } #endif +#endif #ifdef WITH_GSM_MS - if (options.gsm && gsm_ms_init()) { + if (gsm_ms_init()) { 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; -#if defined WITH_GSM_BS || defined WITH_GSM_MS +#if 0 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) { @@ -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; - /* 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 (options.polling) + if (options.polling) { if (!select_main(1, NULL, NULL, NULL)) usleep(10000); - else + } else select_main(0, NULL, NULL, NULL); #endif } @@ -604,17 +578,18 @@ free: mISDN_deinitialize(); /* free gsm */ - if (options.gsm) { +#if 0 +exit is done when interface is down #ifdef WITH_GSM_BS - gsm_bs_exit(0); + gsm_bs_exit(0); +#endif #endif #ifdef WITH_GSM_MS - gsm_ms_exit(0); + gsm_ms_exit(0); #endif #if defined WITH_GSM_BS || defined WITH_GSM_MS - gsm_exit(0); + gsm_exit(0); #endif - } /* close loopback, if used by GSM or remote */ if (mISDNloop.sock > -1) diff --git a/mncc.h b/mncc.h new file mode 100644 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]; +}; + diff --git a/options.c b/options.c index 7fb9bcb..b1c52cf 100644 --- 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) */ - 0, /* enable gsm */ 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,"gsm")) { - options.gsm = 1; - } else if (!strcmp(option,"polling")) { options.polling = 1; } else diff --git a/options.h b/options.h index c7f9f8f..7ea5166 100644 --- 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 gsm; /* enable gsm support */ int polling; char loopback_ext[64]; /* loopback interface GSM side */ char loopback_lcr[64]; /* loopback interface LCR side */