summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.am18
-rw-r--r--configure.ac28
-rw-r--r--default/openbsc.cfg155
-rw-r--r--default/options.conf12
-rw-r--r--gsm.cpp366
-rw-r--r--gsm.h19
-rw-r--r--gsm_bs.cpp269
-rw-r--r--gsm_bs.h9
-rw-r--r--gsm_ms.cpp219
-rw-r--r--gsm_ms.h9
-rw-r--r--interface.c25
-rw-r--r--main.c59
-rw-r--r--mncc.h186
-rw-r--r--options.c4
-rw-r--r--options.h1
15 files changed, 587 insertions, 792 deletions
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 <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;
@@ -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 <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
@@ -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, &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);
- 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 <openbsc/gsm_data.h>
-#include <openbsc/mncc.h>
-}
/* 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 <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);
+#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, &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);
- 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 <osmocom/bb/common/osmocom_data.h>
-#include <osmocom/bb/mobile/mncc.h>
-}
/* 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 <osmocom/core/signal.h>
-}
-#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 */