X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=gsm_bs.cpp;h=d281bc962d67747311c680d7de9c9040b788feda;hp=584b7e27b42aac7ca2a5904755efb2cbc36f0457;hb=41a0668da1dbd5644a50036eaa26c8ba85201ffd;hpb=129a76d1411166176db646138b35e8f5ed9907a2 diff --git a/gsm_bs.cpp b/gsm_bs.cpp index 584b7e2..d281bc9 100644 --- a/gsm_bs.cpp +++ b/gsm_bs.cpp @@ -10,80 +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 -#include -#include -#include -//#include -struct gsm_network *bsc_gsmnet = 0; -extern int ipacc_rtp_direct; -extern int bsc_bootstrap_network(int (*mmc_rev)(struct gsm_network *, int, void *), - const char *cfg_file); -extern int bsc_shutdown_net(struct gsm_network *net); -void talloc_ctx_init(void); -void on_dso_load_token(void); -void on_dso_load_rrlp(void); -void on_dso_load_ho_dec(void); -int bts_model_unknown_init(void); -int bts_model_bs11_init(void); -int bts_model_nanobts_init(void); -static struct log_target *stderr_target; -extern const char *openbsc_copyright; - -/* timer to store statistics */ -#define DB_SYNC_INTERVAL 60, 0 -static struct timer_list db_sync_timer; - -/* FIXME: copied from the include file, because it will con compile with C++ */ -struct vty_app_info { - const char *name; - const char *version; - const char *copyright; - void *tall_ctx; - int (*go_parent_cb)(struct vty *vty); - int (*is_config_node)(struct vty *vty, int node); -}; - -extern int bsc_vty_go_parent(struct vty *vty); -extern int bsc_vty_is_config_node(struct vty *vty, int node); -static struct vty_app_info vty_info = { - "OpenBSC", - PACKAGE_VERSION, - NULL, - NULL, - bsc_vty_go_parent, - bsc_vty_is_config_node, -}; - -void vty_init(struct vty_app_info *app_info); -int bsc_vty_init(void); - -} - -/* timer handling */ -static int _db_store_counter(struct counter *counter, void *data) -{ - return db_store_counter(counter); -} - -static void db_sync_timer_cb(void *data) -{ - /* store counters to database and re-schedule */ - counters_for_each(_db_store_counter, NULL); - bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL); -} +struct lcr_gsm *gsm_bs = NULL; /* * DTMF stuff @@ -118,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; @@ -150,8 +79,9 @@ void Pgsm_bs::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct add_trace("keypad", NULL, "%c", mncc->keypad); end_trace(); 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 */ @@ -199,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; @@ -224,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; } } @@ -256,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; } } @@ -298,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; @@ -319,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; @@ -391,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; @@ -423,9 +353,10 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ gsm_trace_header(p_m_mISDNport, this, MNCC_LCHAN_MODIFY, DIRECTION_OUT); mode = create_mncc(MNCC_LCHAN_MODIFY, p_m_g_callref); mode->lchan_mode = 0x01; /* GSM V1 */ + mode->lchan_type = 0x02; 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); @@ -440,7 +371,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); @@ -448,7 +379,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; } @@ -469,7 +400,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; @@ -538,7 +469,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 */ @@ -620,6 +551,20 @@ void Pgsm_bs::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 GSM MNCC connection */ + 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 = 41; // temp. failure. + 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); @@ -804,7 +749,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); @@ -839,119 +784,37 @@ int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parame int gsm_bs_exit(int rc) { /* free gsm instance */ - if (gsm) { - /* shutdown network */ - if (gsm->network) - bsc_shutdown_net((struct gsm_network *)gsm->network); - /* free network */ -// if (gsm->network) { -// free((struct gsm_network *)gsm->network); /* TBD */ -// } + if (gsm_bs) { + if (gsm_bs->mncc_lfd.fd > -1) { + close(gsm_bs->mncc_lfd.fd); + unregister_fd(&gsm_bs->mncc_lfd); + } + + del_timer(&gsm_bs->socket_retry); + free(gsm_bs); + gsm_bs = NULL; } + return(rc); } int gsm_bs_init(void) { - char hlr[128], cfg[128], filename[128]; - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - int pcapfd, rc; - - vty_info.copyright = openbsc_copyright; - - log_init(&log_info); - tall_bsc_ctx = talloc_named_const(NULL, 1, "openbsc"); - talloc_ctx_init(); - on_dso_load_token(); - on_dso_load_rrlp(); - on_dso_load_ho_dec(); - stderr_target = log_target_create_stderr(); - log_add_target(stderr_target); - - bts_model_unknown_init(); - bts_model_bs11_init(); - bts_model_nanobts_init(); - - /* enable filters */ - log_set_all_filter(stderr_target, 1); - - /* Init VTY (need to preceed options) */ - vty_init(&vty_info); - bsc_vty_init(); - - /* set debug */ - if (gsm->conf.debug[0]) - log_parse_category_mask(stderr_target, gsm->conf.debug); - - /* open pcap file */ - if (gsm->conf.pcapfile[0]) { - if (gsm->conf.pcapfile[0] == '/') - SCPY(filename, gsm->conf.pcapfile); - else - SPRINT(filename, "%s/%s", CONFIG_DATA, gsm->conf.pcapfile); - pcapfd = open(filename, O_WRONLY|O_TRUNC|O_CREAT, mode); - if (pcapfd < 0) { - PERROR("Failed to open file for pcap\n"); - return gsm_exit(-1); - } - e1_set_pcap_fd(pcapfd); - } + /* create gsm instance */ + gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm)); - /* use RTP proxy for audio streaming */ - ipacc_rtp_direct = 0; + gsm_bs->type = LCR_GSM_TYPE_NETWORK; + gsm_bs->sun.sun_family = AF_UNIX; + SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc"); - /* bootstrap network */ - if (gsm->conf.openbsc_cfg[0] == '/') - SCPY(cfg, gsm->conf.openbsc_cfg); - else - SPRINT(cfg, "%s/%s", CONFIG_DATA, gsm->conf.openbsc_cfg); - rc = bsc_bootstrap_network(&message_bsc, cfg); - if (rc < 0) { - PERROR("Failed to bootstrap GSM network.\n"); - return gsm_exit(-1); - } - bsc_api_init(bsc_gsmnet, msc_bsc_api()); - gsm->network = bsc_gsmnet; - - /* init database */ - if (gsm->conf.hlr[0] == '/') - SCPY(hlr, gsm->conf.hlr); - else - SPRINT(hlr, "%s/%s", CONFIG_DATA, gsm->conf.hlr); - if (db_init(hlr)) { - PERROR("GSM DB: Failed to init database '%s'. Please check the option settings.\n", hlr); - return gsm_exit(-1); - } - printf("DB: Database initialized.\n"); - if (db_prepare()) { - PERROR("GSM DB: Failed to prepare database.\n"); - return gsm_exit(-1); - } - printf("DB: Database prepared.\n"); + memset(&gsm_bs->socket_retry, 0, sizeof(gsm_bs->socket_retry)); + add_timer(&gsm_bs->socket_retry, mncc_socket_retry_cb, gsm_bs, 0); - /* setup the timer */ - db_sync_timer.cb = db_sync_timer_cb; - db_sync_timer.data = NULL; - bsc_schedule_timer(&db_sync_timer, DB_SYNC_INTERVAL); + /* do the initial connect */ + mncc_socket_retry_cb(&gsm_bs->socket_retry, gsm_bs, 0); generate_dtmf(); return 0; } - -/* - * handles bsc select function within LCR's main loop - */ -int handle_gsm_bs(void) -{ - int ret1, ret2; - - ret1 = bsc_upqueue((struct gsm_network *)gsm->network); - log_reset_context(); - ret2 = bsc_select_main(1); /* polling */ - if (ret1 || ret2) - return 1; - return 0; -} -