From 34598a346419f0e661526e6208dade4aff570008 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sat, 26 Feb 2011 16:49:21 +0000 Subject: [PATCH 1/1] [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. --- default/interface.conf | 2 +- gsm.cpp | 8 ++- gsm.h | 3 - gsm_bs.h | 4 ++ gsm_ms.cpp | 155 +++++++++++++++++++++++++++++++------------------ gsm_ms.h | 4 +- interface.c | 14 ++--- interface.h | 2 - mISDN.cpp | 4 ++ main.c | 21 ++++++- 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 +#include #include #include +#include #include #include #include -#include +#include } -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, ¶m->setup.capainfo, sizeof(p_capainfo)); memcpy(&p_redirinfo, ¶m->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 +} +#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 } -- 2.13.6