summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas Eversberg2011-02-26 17:49:21 +0100
committerAndreas Eversberg2011-02-26 17:49:21 +0100
commit34598a346419f0e661526e6208dade4aff570008 (patch)
tree182a626ad5834ae5f4f8315a4732d3cc6a0c504e
parent[mail] Prevent bustling error message when sending mail without attachment (diff)
downloadlcr-34598a346419f0e661526e6208dade4aff570008.tar.gz
lcr-34598a346419f0e661526e6208dade4aff570008.tar.xz
lcr-34598a346419f0e661526e6208dade4aff570008.zip
[gsm] Make LCR work with current Osmocom-BB.
Osmocom-BB is still developed, and this only works with the jolly/voice branch. Audio is not yet transmitted, so it is not quite usefull yet.
-rw-r--r--default/interface.conf2
-rw-r--r--gsm.cpp8
-rw-r--r--gsm.h3
-rw-r--r--gsm_bs.h4
-rw-r--r--gsm_ms.cpp155
-rw-r--r--gsm_ms.h4
-rw-r--r--interface.c14
-rw-r--r--interface.h2
-rw-r--r--mISDN.cpp4
-rw-r--r--main.c21
10 files changed, 135 insertions, 82 deletions
diff --git a/default/interface.conf b/default/interface.conf
index 4c80fed..004df59 100644
--- a/default/interface.conf
+++ b/default/interface.conf
@@ -180,7 +180,7 @@
# of LCR. The actual interface is defined in gsm.conf.
# You may add 'extern' to make this interface the external line by default.
#[GSM]
-#gsm-ms 1 /tmp/osmocom_l2
+#gsm-ms 1
#layer1hold no
#layer2hold no
#tones no
diff --git a/gsm.cpp b/gsm.cpp
index 07746f7..119f0f5 100644
--- a/gsm.cpp
+++ b/gsm.cpp
@@ -199,14 +199,16 @@ 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 ret;
+ int ret = 0;
+ if (instance) {
#ifdef WITH_GSM_BS
- ret = mncc_send((struct gsm_network *)instance, msg_type, data);
+ 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);
+ ret = mncc_send((struct osmocom_ms *)instance, msg_type, data);
#endif
+ }
free(data);
return ret;
diff --git a/gsm.h b/gsm.h
index 4bfad78..c12baa0 100644
--- a/gsm.h
+++ b/gsm.h
@@ -75,6 +75,3 @@ int gsm_conf(struct gsm_conf *gsm_conf, char *conf_error);
int gsm_exit(int rc);
int gsm_init(void);
-extern "C" {
-int mncc_send(struct gsm_network *instance, int msg_type, void *data);
-};
diff --git a/gsm_bs.h b/gsm_bs.h
index fd56efe..8a55213 100644
--- a/gsm_bs.h
+++ b/gsm_bs.h
@@ -25,3 +25,7 @@ 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);
+};
diff --git a/gsm_ms.cpp b/gsm_ms.cpp
index 551fcad..481a4ac 100644
--- a/gsm_ms.cpp
+++ b/gsm_ms.cpp
@@ -16,24 +16,24 @@
#endif
extern "C" {
#include <getopt.h>
+#include <arpa/inet.h>
#include <osmocore/select.h>
#include <osmocore/talloc.h>
+#include <osmocore/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/common/l23_app.h>
+#include <osmocom/bb/mobile/app_mobile.h>
}
-const char *openbsc_copyright = "";
+static const char *config_file = "/etc/osmocom/osmocom.cfg";
short vty_port = 4247;
struct llist_head ms_list;
struct log_target *stderr_target;
void *l23_ctx = NULL;
-int (*l23_app_work) (struct osmocom_ms *ms) = NULL;
-int (*l23_app_exit) (struct osmocom_ms *ms) = NULL;
static int dtmf_timeout(struct lcr_timer *timer, void *instance, int index);
@@ -54,9 +54,6 @@ Pgsm_ms::Pgsm_ms(int type, struct mISDNport *mISDNport, char *portname, struct p
}
}
- if (!p_m_g_instance)
- FATAL("MS name %s does not exists. Please fix!");
-
p_m_g_dtmf_state = DTMF_ST_IDLE;
p_m_g_dtmf_index = 0;
p_m_g_dtmf[0] = '\0';
@@ -391,7 +388,31 @@ static int message_ms(struct osmocom_ms *ms, int msg_type, void *arg)
struct mISDNport *mISDNport;
/* Special messages */
- if (msg_type) {
+ 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 */
@@ -508,6 +529,20 @@ void Pgsm_ms::message_setup(unsigned int epoint_id, int message_id, union parame
memcpy(&p_capainfo, &param->setup.capainfo, sizeof(p_capainfo));
memcpy(&p_redirinfo, &param->setup.redirinfo, sizeof(p_redirinfo));
+ /* no instance */
+ if (!p_m_g_instance) {
+ 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.location = LOCATION_PRIVATE_LOCAL;
+ message_put(message);
+ new_state(PORT_STATE_RELEASE);
+ trigger_work(&p_m_g_delete);
+ return;
+ }
+
/* no number */
if (!p_dialinginfo.id[0]) {
gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT);
@@ -782,6 +817,7 @@ int Pgsm_ms::message_epoint(unsigned int epoint_id, int message_id, union parame
int gsm_ms_exit(int rc)
{
+ l23_app_exit();
return(rc);
}
@@ -796,50 +832,40 @@ int gsm_ms_init(void)
l23_ctx = talloc_named_const(NULL, 1, "layer2 context");
- return 0;
-}
-
-/* add a new GSM mobile instance */
-int gsm_ms_new(const char *name, const char *socket_path)
-{
- struct osmocom_ms *ms = NULL;
- int rc;
-
- PDEBUG(DEBUG_GSM, "GSM: creating new instance '%s' on '%s'\n", name, socket_path);
+ log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DSIM:DCC:DMNCC:DPAG:DSUM");
+ log_set_log_level(stderr_target, LOGL_INFO);
- ms = talloc_zero(l23_ctx, struct osmocom_ms);
- if (!ms) {
- FATAL("Failed to allocate MS\n");
+#if 0
+ if (gsmtap_ip) {
+ rc = gsmtap_init(gsmtap_ip);
+ if (rc < 0) {
+ fprintf(stderr, "Failed during gsmtap_init()\n");
+ exit(1);
+ }
}
- /* must add here, because other init processes may search in the list */
- llist_add_tail(&ms->entity, &ms_list);
-
-
- SPRINT(ms->name, name);
+#endif
- rc = layer2_open(ms, socket_path);
- if (rc < 0) {
- FATAL("Failed during layer2_open()\n");
- }
+ l23_app_init(message_ms, config_file, vty_port);
- lapdm_init(&ms->l2_entity.lapdm_dcch, ms);
- lapdm_init(&ms->l2_entity.lapdm_acch, ms);
+ return 0;
+}
- rc = l23_app_init(ms);
- if (rc < 0) {
- FATAL("Failed to init layer23\n");
- }
- ms->mncc_entity.mncc_recv = message_ms;
+/* 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);
return 0;
}
int gsm_ms_delete(const char *name)
{
- struct osmocom_ms *ms = NULL;
+ struct osmocom_ms *ms;
int found = 0;
+ class Port *port;
+ class Pgsm_ms *pgsm_ms = NULL;
- PDEBUG(DEBUG_GSM, "GSM: destroying instance '%s'\n", name);
+ PDEBUG(DEBUG_GSM, "GSM: interface for MS '%s' is down\n", name);
llist_for_each_entry(ms, &ms_list, entity) {
if (!strcmp(ms->name, name)) {
@@ -848,15 +874,29 @@ int gsm_ms_delete(const char *name)
}
}
- if (!found) {
- FATAL("Failed delete layer23, instance '%s' not found\n", name);
- }
-
- l23_app_exit(ms);
- lapdm_exit(&ms->l2_entity.lapdm_dcch);
- lapdm_exit(&ms->l2_entity.lapdm_acch);
+ if (!found)
+ return 0;
- llist_del(&ms->entity);
+ 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) {
+ struct gsm_mncc *rej;
+
+ rej = create_mncc(MNCC_REL_REQ, pgsm_ms->p_m_g_callref);
+ rej->fields |= MNCC_F_CAUSE;
+ rej->cause.coding = 3;
+ rej->cause.location = 1;
+ rej->cause.value = 27;
+ gsm_trace_header(NULL, NULL, MNCC_REJ_REQ, DIRECTION_OUT);
+ add_trace("cause", "coding", "%d", rej->cause.coding);
+ add_trace("cause", "location", "%d", rej->cause.location);
+ add_trace("cause", "value", "%d", rej->cause.value);
+ end_trace();
+ }
+ }
+ }
return 0;
}
@@ -864,18 +904,17 @@ int gsm_ms_delete(const char *name)
/*
* handles bsc select function within LCR's main loop
*/
-int handle_gsm_ms(void)
+int handle_gsm_ms(int *_quit)
{
- struct osmocom_ms *ms = NULL;
- int work = 0;
-
- llist_for_each_entry(ms, &ms_list, entity) {
- if (l23_app_work(ms))
- work = 1;
-// debug_reset_context();
- if (bsc_select_main(1)) /* polling */
- work = 1;
- }
+ int work = 0, quit = 0;
+
+ if (l23_app_work(&quit))
+ work = 1;
+ if (quit && llist_empty(&ms_list))
+ *_quit = 1;
+// debug_reset_context();
+ if (bsc_select_main(1)) /* polling */
+ work = 1;
return work;
}
diff --git a/gsm_ms.h b/gsm_ms.h
index 3e9794f..822f0a6 100644
--- a/gsm_ms.h
+++ b/gsm_ms.h
@@ -23,10 +23,10 @@ class Pgsm_ms : public Pgsm
int message_epoint(unsigned int epoint_id, int message_id, union parameter *param);
};
-int handle_gsm_ms(void);
+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, const char *socket_path);
+int gsm_ms_new(const char *name);
int gsm_ms_delete(const char *name);
diff --git a/interface.c b/interface.c
index 4b894cf..4e432af 100644
--- a/interface.c
+++ b/interface.c
@@ -961,21 +961,15 @@ static int inter_gsm_ms(struct interface *interface, char *filename, int line, c
return(-1);
}
SCPY(ifport->gsm_ms_name, element);
- element = strsep(&value, " ");
- if (!element || !element[0]) {
- SPRINT(interface_error, "Error in %s (line %d): Missing socket name after MS name.\n", filename, line);
- return(-1);
- }
- SCPY(ifport->gsm_ms_socket, element);
- /* check if socket is used multiple times */
+ /* check if name is used multiple times */
searchif = interface_newlist;
while(searchif) {
searchifport = searchif->ifport;
while(searchifport) {
if (searchifport != ifport
- && !strcmp(searchifport->gsm_ms_socket, ifport->gsm_ms_socket)) {
- SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given socket '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_socket);
+ && !strcmp(searchifport->gsm_ms_name, ifport->gsm_ms_name)) {
+ SPRINT(interface_error, "Error in %s (line %d): mobile '%s' already uses the given MS name '%s', choose a different one.\n", filename, line, ifport->gsm_ms_name, searchifport->gsm_ms_name);
return(-1);
}
searchifport = searchifport->next;
@@ -1589,7 +1583,7 @@ void load_port(struct interface_port *ifport)
mISDNport_static(mISDNport);
#ifdef WITH_GSM_MS
if (ifport->gsm_ms)
- gsm_ms_new(ifport->gsm_ms_name, ifport->gsm_ms_socket);
+ gsm_ms_new(ifport->gsm_ms_name);
#endif
} else {
ifport->block = 2; /* not available */
diff --git a/interface.h b/interface.h
index eea6915..f271080 100644
--- a/interface.h
+++ b/interface.h
@@ -57,8 +57,6 @@ struct interface_port {
#ifdef WITH_GSM_MS
int gsm_ms; /* interface is an GSM MS interface */
char gsm_ms_name[32]; /* name of ms */
- char gsm_ms_socket[128]; /* layer1 socket name */
- char gsm_ms_service; /* see GSM_SERVICE_* */
#endif
unsigned int ss5; /* set, if SS5 signalling enabled, also holds feature bits */
int remote; /* interface is a remote app interface */
diff --git a/mISDN.cpp b/mISDN.cpp
index 087963c..50746ec 100644
--- a/mISDN.cpp
+++ b/mISDN.cpp
@@ -1367,7 +1367,11 @@ void PmISDN::bchannel_receive(struct mISDNhead *hh, unsigned char *data, int len
if ((cont&(~DTMF_TONE_MASK)) == DTMF_TONE_VAL) {
chan_trace_header(p_m_mISDNport, this, "BCHANNEL control", DIRECTION_IN);
add_trace("DTMF", NULL, "%c", cont & DTMF_TONE_MASK);
+ if (!p_m_dtmf)
+ add_trace("info", NULL, "DTMF is disabled");
end_trace();
+ if (!p_m_dtmf)
+ return;
message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_DTMF);
message->param.dtmf = cont & DTMF_TONE_MASK;
PDEBUG(DEBUG_PORT, "PmISDN(%s) PH_CONTROL INDICATION DTMF digit '%c'\n", p_name, message->param.dtmf);
diff --git a/main.c b/main.c
index b9e836c..1aa2d8b 100644
--- a/main.c
+++ b/main.c
@@ -11,6 +11,11 @@
#include "main.h"
#include "config.h"
+#ifdef WITH_GSM_MS
+extern "C" {
+#include <osmocore/signal.h>
+}
+#endif
//MESSAGES
@@ -138,11 +143,23 @@ 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;
if (sigset == SIGPIPE)
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;
+ dispatch_signal(SS_GLOBAL, S_GLOBAL_SHUTDOWN, NULL);
+ return;
+ }
+#endif
if (!quit) {
quit = sigset;
/* set scheduler & priority */
@@ -151,8 +168,6 @@ void sighandler(int sigset)
schedp.sched_priority = 0;
sched_setscheduler(0, SCHED_OTHER, &schedp);
}
- fprintf(stderr, "LCR: Signal received: %d\n", sigset);
- PDEBUG(DEBUG_LOG, "Signal received: %d\n", sigset);
}
}
@@ -470,7 +485,7 @@ int main(int argc, char *argv[])
if (handle_gsm())
all_idle = 0;
#ifdef WITH_GSM_MS
- if (handle_gsm_ms())
+ if (handle_gsm_ms(&quit))
all_idle = 0;
#endif
}