X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=gsm.cpp;h=e4d5792a0fb98820525b0f6f0f67e95194a247c8;hp=d6109c9e230223bf606c38edff33ec4fe9022466;hb=a12d7eee22a72f4c999535892763dde15212e89e;hpb=0f805e041a900551a8c3cf9a75a78c2b34e1977c diff --git a/gsm.cpp b/gsm.cpp index d6109c9..e4d5792 100644 --- a/gsm.cpp +++ b/gsm.cpp @@ -15,60 +15,19 @@ #define _GNU_SOURCE #endif extern "C" { -#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; - -/* timer to store statistics */ -#define DB_SYNC_INTERVAL 60, 0 -static struct timer_list db_sync_timer; - #include "gsm_audio.h" - } #include struct lcr_gsm *gsm = NULL; -static unsigned int new_callref = 1; - -/* 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); -} +int new_callref = 1; /* * create and send mncc message */ -static struct gsm_mncc *create_mncc(int msg_type, unsigned int callref) +struct gsm_mncc *create_mncc(int msg_type, unsigned int callref) { struct gsm_mncc *mncc; @@ -77,11 +36,16 @@ static struct gsm_mncc *create_mncc(int msg_type, unsigned int callref) mncc->callref = callref; return (mncc); } -static int send_and_free_mncc(struct gsm_network *net, unsigned int msg_type, void *data) +int send_and_free_mncc(void *instance, unsigned int msg_type, void *data) { int ret; - ret = mncc_send(net, msg_type, data); +#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 free(data); return ret; @@ -97,6 +61,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_callref = 0; p_m_g_mode = 0; p_m_g_gsm_b_sock = -1; @@ -112,7 +77,7 @@ Pgsm::Pgsm(int type, struct mISDNport *mISDNport, char *portname, struct port_se p_m_g_rxpos = 0; p_m_g_tch_connected = 0; - PDEBUG(DEBUG_GSM, "Created new mISDNPort(%s).\n", portname); + PDEBUG(DEBUG_GSM, "Created new GSMPort(%s).\n", portname); } /* @@ -257,7 +222,12 @@ void Pgsm::frame_send(void *_frame) frame->msg_type = GSM_TCHF_FRAME; frame->callref = p_m_g_callref; memcpy(frame->data, _frame, 33); - mncc_send((struct gsm_network *)gsm->network, frame->msg_type, frame); +#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 } @@ -288,7 +258,7 @@ void Pgsm::frame_receive(void *_frame) /* * create trace **/ -static void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction) +void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, unsigned int msg_type, int direction) { char msgtext[64]; @@ -296,10 +266,20 @@ static void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, un SCPY(msgtext, get_mncc_name(msg_type)); /* add direction */ - if (direction == DIRECTION_OUT) - SCAT(msgtext, " MSC->BSC"); - else - SCAT(msgtext, " MSC<-BSC"); + switch(port->p_type) { + case PORT_TYPE_GSM_BS_OUT: + SCAT(msgtext, " LCR->BSC"); + break; + case PORT_TYPE_GSM_BS_IN: + SCAT(msgtext, " LCR<-BSC"); + break; + case PORT_TYPE_GSM_MS_OUT: + SCAT(msgtext, " LCR->MS"); + break; + case PORT_TYPE_GSM_MS_IN: + SCAT(msgtext, " LCR<-MS"); + break; + } /* init trace with given values */ start_trace(mISDNport?mISDNport->portnum:-1, @@ -312,13 +292,14 @@ static void gsm_trace_header(struct mISDNport *mISDNport, class PmISDN *port, un msgtext); } - - /* select bchannel */ int Pgsm::hunt_bchannel(void) { int channel; int i; + char map[p_m_mISDNport->b_num]; + struct interface *interface; + struct interface_port *ifport; chan_trace_header(p_m_mISDNport, this, "CHANNEL SELECTION (setup)", DIRECTION_NONE); add_trace("channel", "reserved", "%d", p_m_mISDNport->b_reserved); @@ -327,11 +308,40 @@ int Pgsm::hunt_bchannel(void) end_trace(); return(-34); // no channel } + + /* map all used ports of shared loopback interface */ + memset(map, 0, sizeof(map)); + interface = interface_first; + while(interface) { + ifport = interface->ifport; + while(ifport) { +#if defined WITH_GSM_BS && defined WITH_GSM_MS + if ((ifport->gsm_bs || ifport->gsm_ms) && ifport->mISDNport) { +#else +#ifdef WITH_GSM_BS + if (ifport->gsm_bs && ifport->mISDNport) { +#endif +#ifdef WITH_GSM_MS + if (ifport->gsm_ms && ifport->mISDNport) { +#endif +#endif + i = 0; + while(i < p_m_mISDNport->b_num) { + if (p_m_mISDNport->b_port[i]) + map[i] = 1; + i++; + } + } + ifport = ifport->next; + } + interface = interface->next; + } + /* find channel */ i = 0; channel = 0; while(i < p_m_mISDNport->b_num) { - if (p_m_mISDNport->b_port[i] == NULL) { + if (!map[i]) { channel = i+1+(i>=15); break; } @@ -348,261 +358,6 @@ int Pgsm::hunt_bchannel(void) return(channel); } - -/* - * handles all indications - */ -/* SETUP INDICATION */ -void Pgsm::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc) -{ - int ret; - class Endpoint *epoint; - struct lcr_msg *message; - int channel; - struct gsm_mncc *mode, *proceeding, *frame; - - /* emergency shutdown */ - printf("%d %d\n", mncc->emergency, !gsm->conf.noemergshut); - if (mncc->emergency && !gsm->conf.noemergshut) { - start_trace(p_m_mISDNport->portnum, - p_m_mISDNport->ifport->interface, - NULL, - NULL, - DIRECTION_NONE, - CATEGORY_CH, - 0, - "EMERGENCY SHUTDOWN (due to received emergency call)"); - end_trace(); - quit = 1; - } - /* process given callref */ - l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_IND, DIRECTION_IN); - add_trace("callref", "new", "0x%x", callref); - if (p_m_g_callref) { - /* release in case the ID is already in use */ - add_trace("error", NULL, "callref already in use"); - end_trace(); - mncc = create_mncc(MNCC_REJ_REQ, callref); - gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT); - mncc->fields |= MNCC_F_CAUSE; - mncc->cause.coding = 3; - mncc->cause.location = 1; - mncc->cause.value = 47; - add_trace("cause", "coding", "%d", mncc->cause.coding); - add_trace("cause", "location", "%d", mncc->cause.location); - add_trace("cause", "value", "%d", mncc->cause.value); - add_trace("reason", NULL, "callref already in use"); - end_trace(); - send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc); - new_state(PORT_STATE_RELEASE); - trigger_work(&p_m_g_delete); - return; - } - p_m_g_callref = callref; - end_trace(); - - /* if blocked, release call with MT_RELEASE_COMPLETE */ - if (p_m_mISDNport->ifport->block) { - mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref); - gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT); - mncc->fields |= MNCC_F_CAUSE; - mncc->cause.coding = 3; - mncc->cause.location = 1; - mncc->cause.value = 27; - add_trace("cause", "coding", "%d", mncc->cause.coding); - add_trace("cause", "location", "%d", mncc->cause.location); - add_trace("cause", "value", "%d", mncc->cause.value); - add_trace("reason", NULL, "port is blocked"); - end_trace(); - send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc); - new_state(PORT_STATE_RELEASE); - trigger_work(&p_m_g_delete); - return; - } - - /* caller info */ - if (mncc->clir.inv) - p_callerinfo.present = INFO_PRESENT_RESTRICTED; - else - p_callerinfo.present = INFO_PRESENT_ALLOWED; - if (mncc->calling.number[0]) - SCPY(p_callerinfo.id, mncc->calling.number); - else - p_callerinfo.present = INFO_PRESENT_NOTAVAIL; - SCPY(p_callerinfo.imsi, mncc->imsi); - p_callerinfo.screen = INFO_SCREEN_NETWORK; - p_callerinfo.ntype = INFO_NTYPE_UNKNOWN; - p_callerinfo.isdn_port = p_m_portnum; - SCPY(p_callerinfo.interface, p_m_mISDNport->ifport->interface->name); - - /* dialing information */ - SCAT(p_dialinginfo.id, mncc->called.number); - switch (mncc->called.type) { - case 0x1: - p_dialinginfo.ntype = INFO_NTYPE_INTERNATIONAL; - break; - case 0x2: - p_dialinginfo.ntype = INFO_NTYPE_NATIONAL; - break; - case 0x4: - p_dialinginfo.ntype = INFO_NTYPE_SUBSCRIBER; - break; - default: - p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN; - break; - } - if (mncc->emergency) { - SCPY(p_dialinginfo.id, "emergency"); - } - p_dialinginfo.sending_complete = 1; - - /* bearer capability */ - // todo - p_capainfo.bearer_capa = INFO_BC_SPEECH; - p_capainfo.bearer_info1 = (options.law=='a')?3:2; - p_capainfo.bearer_mode = INFO_BMODE_CIRCUIT; - p_capainfo.source_mode = B_MODE_TRANSPARENT; - p_m_g_mode = p_capainfo.source_mode; - - /* useruser */ - - /* hunt channel */ - ret = channel = hunt_bchannel(); - if (ret < 0) - goto no_channel; - - /* open channel */ - ret = seize_bchannel(channel, 1); - if (ret < 0) { - no_channel: - mncc = create_mncc(MNCC_REJ_REQ, p_m_g_callref); - gsm_trace_header(p_m_mISDNport, this, MNCC_REJ_REQ, DIRECTION_OUT); - mncc->fields |= MNCC_F_CAUSE; - mncc->cause.coding = 3; - mncc->cause.location = 1; - mncc->cause.value = 34; - add_trace("cause", "coding", "%d", mncc->cause.coding); - add_trace("cause", "location", "%d", mncc->cause.location); - add_trace("cause", "value", "%d", mncc->cause.value); - add_trace("reason", NULL, "no channel"); - end_trace(); - send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc); - new_state(PORT_STATE_RELEASE); - trigger_work(&p_m_g_delete); - return; - } - bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE); - if (bchannel_open(p_m_b_index)) - goto no_channel; - - /* what infos did we got ... */ - gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN); - if (p_callerinfo.id[0]) - add_trace("calling", "number", "%s", p_callerinfo.id); - else - SPRINT(p_callerinfo.id, "imsi-%s", p_callerinfo.imsi); - add_trace("calling", "imsi", "%s", p_callerinfo.imsi); - add_trace("dialing", "number", "%s", p_dialinginfo.id); - end_trace(); - - /* create endpoint */ - if (p_epointlist) - FATAL("Incoming call but already got an endpoint.\n"); - if (!(epoint = new Endpoint(p_serial, 0))) - FATAL("No memory for Endpoint instance\n"); - if (!(epoint->ep_app = new DEFAULT_ENDPOINT_APP(epoint, 0))) //incoming - FATAL("No memory for Endpoint Application instance\n"); - epointlist_new(epoint->ep_serial); - - /* modify lchan to GSM codec V1 */ - 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 */ - add_trace("mode", NULL, "0x%02x", mode->lchan_mode); - end_trace(); - send_and_free_mncc((struct gsm_network *)gsm->network, mode->msg_type, mode); - - /* send call proceeding */ - gsm_trace_header(p_m_mISDNport, this, MNCC_CALL_PROC_REQ, DIRECTION_OUT); - proceeding = create_mncc(MNCC_CALL_PROC_REQ, p_m_g_callref); - if (p_m_mISDNport->tones) { - proceeding->fields |= MNCC_F_PROGRESS; - proceeding->progress.coding = 3; /* GSM */ - proceeding->progress.location = 1; - proceeding->progress.descr = 8; - add_trace("progress", "coding", "%d", proceeding->progress.coding); - add_trace("progress", "location", "%d", proceeding->progress.location); - add_trace("progress", "descr", "%d", proceeding->progress.descr); - } - end_trace(); - send_and_free_mncc((struct gsm_network *)gsm->network, proceeding->msg_type, proceeding); - - new_state(PORT_STATE_IN_PROCEEDING); - - if (p_m_mISDNport->tones && !p_m_g_tch_connected) { /* only if ... */ - 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((struct gsm_network *)gsm->network, frame->msg_type, frame); - p_m_g_tch_connected = 1; - } - - /* send setup message to endpoit */ - message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_SETUP); - message->param.setup.isdn_port = p_m_portnum; - message->param.setup.port_type = p_type; -// message->param.setup.dtmf = 0; - memcpy(&message->param.setup.dialinginfo, &p_dialinginfo, sizeof(struct dialing_info)); - memcpy(&message->param.setup.callerinfo, &p_callerinfo, sizeof(struct caller_info)); - memcpy(&message->param.setup.capainfo, &p_capainfo, sizeof(struct capa_info)); - SCPY((char *)message->param.setup.useruser.data, (char *)mncc->useruser.info); - message->param.setup.useruser.len = strlen(mncc->useruser.info); - message->param.setup.useruser.protocol = mncc->useruser.proto; - message_put(message); -} - -/* DTMF INDICATION */ -void Pgsm::start_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc) -{ - struct lcr_msg *message; - struct gsm_mncc *resp; - - gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN); - add_trace("keypad", NULL, "%c", mncc->keypad); - end_trace(); - SPRINT(p_dialinginfo.id, "%c", mncc->keypad); - p_dialinginfo.ntype = INFO_NTYPE_UNKNOWN; - - /* send resp */ - gsm_trace_header(p_m_mISDNport, this, MNCC_START_DTMF_RSP, DIRECTION_OUT); - add_trace("keypad", NULL, "%c", mncc->keypad); - end_trace(); - resp = create_mncc(MNCC_START_DTMF_RSP, p_m_g_callref); - resp->keypad = mncc->keypad; - send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp); - - /* send dialing information */ - message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_INFORMATION); - memcpy(&message->param.information, &p_dialinginfo, sizeof(struct dialing_info)); - message_put(message); -} -void Pgsm::stop_dtmf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc) -{ - struct gsm_mncc *resp; - - gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN); - add_trace("keypad", NULL, "%c", mncc->keypad); - end_trace(); - - /* send resp */ - gsm_trace_header(p_m_mISDNport, this, MNCC_STOP_DTMF_RSP, DIRECTION_OUT); - add_trace("keypad", NULL, "%c", mncc->keypad); - end_trace(); - resp = create_mncc(MNCC_STOP_DTMF_RSP, p_m_g_callref); - resp->keypad = mncc->keypad; - send_and_free_mncc((struct gsm_network *)gsm->network, resp->msg_type, resp); -} - /* PROCEEDING INDICATION */ void Pgsm::call_conf_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc) { @@ -622,7 +377,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((struct gsm_network *)gsm->network, mode->msg_type, mode); + send_and_free_mncc(p_m_g_instance, mode->msg_type, mode); } @@ -668,7 +423,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((struct gsm_network *)gsm->network, resp->msg_type, resp); + send_and_free_mncc(p_m_g_instance, 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)); @@ -680,7 +435,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((struct gsm_network *)gsm->network, frame->msg_type, frame); + send_and_free_mncc(p_m_g_instance, frame->msg_type, frame); p_m_g_tch_connected = 1; } } @@ -699,7 +454,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((struct gsm_network *)gsm->network, frame->msg_type, frame); + send_and_free_mncc(p_m_g_instance, frame->msg_type, frame); p_m_g_tch_connected = 1; } } @@ -734,7 +489,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((struct gsm_network *)gsm->network, resp->msg_type, resp); + send_and_free_mncc(p_m_g_instance, resp->msg_type, resp); /* sending release to endpoint */ while(p_epointlist) { @@ -792,404 +547,6 @@ void Pgsm::notify_ind(unsigned int msg_type, unsigned int callref, struct gsm_mn message_put(message); } - -/* HOLD INDICATION */ -void Pgsm::hold_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc) -{ - struct lcr_msg *message; - struct gsm_mncc *resp, *frame; - - gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN); - end_trace(); - - /* notify the hold of call */ - message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY); - message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_HOLD; - message->param.notifyinfo.local = 1; /* call is held by supplementary service */ - message_put(message); - - /* acknowledge hold */ - 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((struct gsm_network *)gsm->network, 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((struct gsm_network *)gsm->network, frame->msg_type, frame); - p_m_g_tch_connected = 0; - } -} - - -/* RETRIEVE INDICATION */ -void Pgsm::retr_ind(unsigned int msg_type, unsigned int callref, struct gsm_mncc *mncc) -{ - struct lcr_msg *message; - struct gsm_mncc *resp, *frame; - - gsm_trace_header(p_m_mISDNport, this, msg_type, DIRECTION_IN); - end_trace(); - - /* notify the retrieve of call */ - message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_NOTIFY); - message->param.notifyinfo.notify = INFO_NOTIFY_REMOTE_RETRIEVAL; - message->param.notifyinfo.local = 1; /* call is retrieved by supplementary service */ - message_put(message); - - /* acknowledge retr */ - 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((struct gsm_network *)gsm->network, 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((struct gsm_network *)gsm->network, frame->msg_type, frame); - p_m_g_tch_connected = 1; - } -} - -/* - * BSC sends message to port - */ -static int message_bsc(struct gsm_network *net, int msg_type, void *arg) -{ - struct gsm_mncc *mncc = (struct gsm_mncc *)arg; - unsigned int callref = mncc->callref; - class Port *port; - class Pgsm *pgsm = NULL; - char name[64]; - struct mISDNport *mISDNport; - - /* Special messages */ - switch(msg_type) { - } - - /* find callref */ - callref = mncc->callref; - port = port_first; - while(port) { - if ((port->p_type & PORT_CLASS_mISDN_MASK) == PORT_CLASS_mISDN_GSM) { - pgsm = (class Pgsm *)port; - if (pgsm->p_m_g_callref == callref) { - break; - } - } - port = port->next; - } - - if (msg_type == GSM_TCHF_FRAME) { - if (port) - pgsm->frame_receive((struct gsm_trau_frame *)arg); - return 0; - } - - if (!port) { - if (msg_type != MNCC_SETUP_IND) - return(0); - /* find gsm port */ - mISDNport = mISDNport_first; - while(mISDNport) { - if (mISDNport->gsm) - break; - mISDNport = mISDNport->next; - } - if (!mISDNport) { - struct gsm_mncc *rej; - - rej = create_mncc(MNCC_REJ_REQ, 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(); - send_and_free_mncc((struct gsm_network *)gsm->network, rej->msg_type, rej); - return 0; - } - /* creating port object, transparent until setup with hdlc */ - SPRINT(name, "%s-%d-in", mISDNport->ifport->interface->name, mISDNport->portnum); - if (!(pgsm = new Pgsm(PORT_TYPE_GSM_IN, mISDNport, name, NULL, 0, 0, B_MODE_TRANSPARENT))) - - FATAL("Cannot create Port instance.\n"); - } - - switch(msg_type) { - case MNCC_SETUP_IND: - pgsm->setup_ind(msg_type, callref, mncc); - break; - - case MNCC_START_DTMF_IND: - pgsm->start_dtmf_ind(msg_type, callref, mncc); - break; - - case MNCC_STOP_DTMF_IND: - pgsm->stop_dtmf_ind(msg_type, callref, mncc); - break; - - case MNCC_CALL_CONF_IND: - pgsm->call_conf_ind(msg_type, callref, mncc); - break; - - case MNCC_ALERT_IND: - pgsm->alert_ind(msg_type, callref, mncc); - break; - - case MNCC_SETUP_CNF: - pgsm->setup_cnf(msg_type, callref, mncc); - break; - - case MNCC_SETUP_COMPL_IND: - pgsm->setup_compl_ind(msg_type, callref, mncc); - break; - - case MNCC_DISC_IND: - pgsm->disc_ind(msg_type, callref, mncc); - break; - - case MNCC_REL_IND: - case MNCC_REL_CNF: - case MNCC_REJ_IND: - pgsm->rel_ind(msg_type, callref, mncc); - break; - - case MNCC_NOTIFY_IND: - pgsm->notify_ind(msg_type, callref, mncc); - break; - - case MNCC_HOLD_IND: - pgsm->hold_ind(msg_type, callref, mncc); - break; - - case MNCC_RETRIEVE_IND: - pgsm->retr_ind(msg_type, callref, mncc); - break; - - default: - PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: 0x%x\n", pgsm->p_name, pgsm->p_callerinfo.id, msg_type); - } - return(0); -} - -/* MESSAGE_SETUP */ -void Pgsm::message_setup(unsigned int epoint_id, int message_id, union parameter *param) -{ - struct lcr_msg *message; - int ret; - struct epoint_list *epointlist; - struct gsm_mncc *mncc; - int channel; - - /* copy setup infos to port */ - memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo)); - memcpy(&p_dialinginfo, ¶m->setup.dialinginfo, sizeof(p_dialinginfo)); - memcpy(&p_capainfo, ¶m->setup.capainfo, sizeof(p_capainfo)); - memcpy(&p_redirinfo, ¶m->setup.redirinfo, sizeof(p_redirinfo)); - - /* no number */ - if (!p_dialinginfo.id[0]) { - gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); - add_trace("failure", NULL, "No dialed subscriber given."); - end_trace(); - message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE); - message->param.disconnectinfo.cause = 28; - message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; - message_put(message); - new_state(PORT_STATE_RELEASE); - trigger_work(&p_m_g_delete); - return; - } - - /* release if port is blocked */ - if (p_m_mISDNport->ifport->block) { - gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); - add_trace("failure", NULL, "Port blocked."); - end_trace(); - message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE); - message->param.disconnectinfo.cause = 27; // temp. unavail. - message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; - message_put(message); - new_state(PORT_STATE_RELEASE); - trigger_work(&p_m_g_delete); - return; - } - - /* hunt channel */ - ret = channel = hunt_bchannel(); - if (ret < 0) - goto no_channel; - /* open channel */ - ret = seize_bchannel(channel, 1); - if (ret < 0) { - no_channel: - gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); - add_trace("failure", NULL, "No internal audio channel available."); - end_trace(); - message = message_create(p_serial, epoint_id, PORT_TO_EPOINT, MESSAGE_RELEASE); - message->param.disconnectinfo.cause = 34; - message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; - message_put(message); - new_state(PORT_STATE_RELEASE); - trigger_work(&p_m_g_delete); - return; - } - bchannel_event(p_m_mISDNport, p_m_b_index, B_EVENT_USE); - if (bchannel_open(p_m_b_index)) - goto no_channel; - -// SCPY(&p_m_tones_dir, param->setup.ext.tones_dir); - /* screen outgoing caller id */ - do_screen(1, p_callerinfo.id, sizeof(p_callerinfo.id), &p_callerinfo.ntype, &p_callerinfo.present, p_m_mISDNport->ifport->interface); - - /* attach only if not already */ - epointlist = p_epointlist; - while(epointlist) { - if (epointlist->epoint_id == epoint_id) - break; - epointlist = epointlist->next; - } - if (!epointlist) - epointlist_new(epoint_id); - - /* creating l3id */ - l1l2l3_trace_header(p_m_mISDNport, this, L3_NEW_L3ID_REQ, DIRECTION_OUT); - p_m_g_callref = new_callref++; - add_trace("callref", "new", "0x%x", p_m_g_callref); - end_trace(); - - gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); - mncc = create_mncc(MNCC_SETUP_REQ, p_m_g_callref); - /* caller information */ - mncc->fields |= MNCC_F_CALLING; - mncc->calling.plan = 1; - switch (p_callerinfo.ntype) { - case INFO_NTYPE_UNKNOWN: - mncc->calling.type = 0x0; - break; - case INFO_NTYPE_INTERNATIONAL: - mncc->calling.type = 0x1; - break; - case INFO_NTYPE_NATIONAL: - mncc->calling.type = 0x2; - break; - case INFO_NTYPE_SUBSCRIBER: - mncc->calling.type = 0x4; - break; - default: /* INFO_NTYPE_NOTPRESENT */ - mncc->fields &= ~MNCC_F_CALLING; - break; - } - switch (p_callerinfo.screen) { - case INFO_SCREEN_USER: - mncc->calling.screen = 0; - break; - default: /* INFO_SCREEN_NETWORK */ - mncc->calling.screen = 3; - break; - } - switch (p_callerinfo.present) { - case INFO_PRESENT_ALLOWED: - mncc->calling.present = 0; - break; - case INFO_PRESENT_RESTRICTED: - mncc->calling.present = 1; - break; - default: /* INFO_PRESENT_NOTAVAIL */ - mncc->calling.present = 2; - break; - } - if (mncc->fields & MNCC_F_CALLING) { - SCPY(mncc->calling.number, p_callerinfo.id); - add_trace("calling", "type", "%d", mncc->calling.type); - add_trace("calling", "plan", "%d", mncc->calling.plan); - add_trace("calling", "present", "%d", mncc->calling.present); - add_trace("calling", "screen", "%d", mncc->calling.screen); - add_trace("calling", "number", "%s", mncc->calling.number); - } - /* dialing information */ - mncc->fields |= MNCC_F_CALLED; - if (!strncmp(p_dialinginfo.id, "imsi-", 5)) { - SCPY(mncc->imsi, p_dialinginfo.id+5); - add_trace("dialing", "imsi", "%s", mncc->imsi); - } else { - SCPY(mncc->called.number, p_dialinginfo.id); - add_trace("dialing", "number", "%s", mncc->called.number); - } - - /* sending user-user */ - - /* redirecting number */ - mncc->fields |= MNCC_F_REDIRECTING; - mncc->redirecting.plan = 1; - switch (p_redirinfo.ntype) { - case INFO_NTYPE_UNKNOWN: - mncc->redirecting.type = 0x0; - break; - case INFO_NTYPE_INTERNATIONAL: - mncc->redirecting.type = 0x1; - break; - case INFO_NTYPE_NATIONAL: - mncc->redirecting.type = 0x2; - break; - case INFO_NTYPE_SUBSCRIBER: - mncc->redirecting.type = 0x4; - break; - default: /* INFO_NTYPE_NOTPRESENT */ - mncc->fields &= ~MNCC_F_REDIRECTING; - break; - } - switch (p_redirinfo.screen) { - case INFO_SCREEN_USER: - mncc->redirecting.screen = 0; - break; - default: /* INFO_SCREE_NETWORK */ - mncc->redirecting.screen = 3; - break; - } - switch (p_redirinfo.present) { - case INFO_PRESENT_ALLOWED: - mncc->redirecting.present = 0; - break; - case INFO_PRESENT_RESTRICTED: - mncc->redirecting.present = 1; - break; - default: /* INFO_PRESENT_NOTAVAIL */ - mncc->redirecting.present = 2; - break; - } - /* sending redirecting number only in ntmode */ - if (mncc->fields & MNCC_F_REDIRECTING) { - SCPY(mncc->redirecting.number, p_redirinfo.id); - add_trace("redir", "type", "%d", mncc->redirecting.type); - add_trace("redir", "plan", "%d", mncc->redirecting.plan); - add_trace("redir", "present", "%d", mncc->redirecting.present); - add_trace("redir", "screen", "%d", mncc->redirecting.screen); - add_trace("redir", "number", "%s", mncc->redirecting.number); - } - /* bearer capability */ - //todo - - end_trace(); - send_and_free_mncc((struct gsm_network *)gsm->network, mncc->msg_type, mncc); - - new_state(PORT_STATE_OUT_SETUP); - - message = message_create(p_serial, ACTIVE_EPOINT(p_epointlist), PORT_TO_EPOINT, MESSAGE_PROCEEDING); - message_put(message); - - new_state(PORT_STATE_OUT_PROCEEDING); -} - /* MESSAGE_NOTIFY */ void Pgsm::message_notify(unsigned int epoint_id, int message_id, union parameter *param) { @@ -1212,7 +569,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((struct gsm_network *)gsm->network, mncc->msg_type, mncc); + send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc); } } } @@ -1235,7 +592,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((struct gsm_network *)gsm->network, mncc->msg_type, mncc); + send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc); new_state(PORT_STATE_IN_ALERTING); @@ -1243,7 +600,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((struct gsm_network *)gsm->network, mncc->msg_type, mncc); + send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc); p_m_g_tch_connected = 1; } } @@ -1309,7 +666,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((struct gsm_network *)gsm->network, mncc->msg_type, mncc); + send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc); new_state(PORT_STATE_CONNECT_WAITING); } @@ -1339,7 +696,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((struct gsm_network *)gsm->network, mncc->msg_type, mncc); + send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc); new_state(PORT_STATE_OUT_DISCONNECT); @@ -1347,7 +704,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((struct gsm_network *)gsm->network, mncc->msg_type, mncc); + send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc); p_m_g_tch_connected = 1; } } @@ -1369,14 +726,13 @@ 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((struct gsm_network *)gsm->network, mncc->msg_type, mncc); + send_and_free_mncc(p_m_g_instance, mncc->msg_type, mncc); new_state(PORT_STATE_RELEASE); trigger_work(&p_m_g_delete); return; } - /* * endpoint sends messages to the port */ @@ -1386,12 +742,6 @@ int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter return(1); switch(message_id) { - case MESSAGE_SETUP: /* dial-out command received from epoint */ - if (p_state!=PORT_STATE_IDLE) - break; - message_setup(epoint_id, message_id, param); - break; - case MESSAGE_NOTIFY: /* display and notifications */ message_notify(epoint_id, message_id, param); break; @@ -1447,14 +797,11 @@ int Pgsm::message_epoint(unsigned int epoint_id, int message_id, union parameter message_release(epoint_id, message_id, param); break; - default: - PDEBUG(DEBUG_GSM, "Pgsm(%s) gsm port with (caller id %s) received unhandled nessage: %d\n", p_name, p_callerinfo.id, message_id); } - return(1); + return(0); } - /* deletes only if l3id is release, otherwhise it will be triggered then */ static int delete_event(struct lcr_work *work, void *instance, int index) { @@ -1578,20 +925,12 @@ static int gsm_sock_open(char *portname) return 0; } - int gsm_exit(int rc) { /* free gsm instance */ if (gsm) { if (gsm->gsm_sock > -1) gsm_sock_close(); - /* 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 */ -// } free(gsm); gsm = NULL; } @@ -1601,27 +940,7 @@ int gsm_exit(int rc) int gsm_init(void) { - char hlr[128], cfg[128], filename[128]; - mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH; - int pcapfd, rc; - char conf_error[128] = ""; - - - 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); + char conf_error[256] = ""; /* seed the PRNG */ srand(time(NULL)); @@ -1633,63 +952,15 @@ int gsm_init(void) /* parse options */ if (!gsm_conf(&gsm->conf, conf_error)) { PERROR("%s", conf_error); +#ifdef WITH_GSM_BS + gsm_bs_exit(-EINVAL); +#endif +#ifdef WITH_GSM_MS + gsm_ms_exit(-EINVAL); +#endif return gsm_exit(-EINVAL); } - /* 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); - } - - /* use RTP proxy for audio streaming */ - ipacc_rtp_direct = 0; - - /* 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"); - - /* 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); - - /* 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); - } - gsm->network = bsc_gsmnet; - /* open gsm loop interface */ if (gsm_sock_open(gsm->conf.interface_bsc)) { return gsm_exit(-1); @@ -1698,18 +969,8 @@ int gsm_init(void) return 0; } -/* - * handles bsc select function within LCR's main loop - */ int handle_gsm(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; }