X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=gsm_bs.cpp;h=81a0672990c3f97adcce339de1c0a205768d9a93;hp=e9b6be80bf4450c6fcfaf95de9c35e1f963150de;hb=refs%2Fheads%2Fbackup2;hpb=a3b269f357b7e6b74d91a942f874ee041320dce7 diff --git a/gsm_bs.cpp b/gsm_bs.cpp index e9b6be8..81a0672 100644 --- a/gsm_bs.cpp +++ b/gsm_bs.cpp @@ -12,7 +12,7 @@ #include "main.h" #include "mncc.h" -struct lcr_gsm *gsm_bs = NULL; +struct lcr_gsm *gsm_bs_first = NULL; #define PAYLOAD_TYPE_GSM 3 @@ -49,11 +49,23 @@ void generate_dtmf(void) */ Pgsm_bs::Pgsm_bs(int type, char *portname, struct port_settings *settings, struct interface *interface) : Pgsm(type, portname, settings, interface) { - p_g_lcr_gsm = gsm_bs; + struct lcr_gsm *gsm_bs = gsm_bs_first; + + p_g_lcr_gsm = NULL; + SCPY(p_g_bs_name, interface->gsm_bs_name); + + while (gsm_bs) { + if (gsm_bs->type == LCR_GSM_TYPE_NETWORK && !strcmp(gsm_bs->name, p_g_bs_name)) { + p_g_lcr_gsm = gsm_bs; + break; + } + gsm_bs = gsm_bs->gsm_next; + } + p_g_dtmf = NULL; p_g_dtmf_index = 0; - PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s).\n", portname); + PDEBUG(DEBUG_GSM, "Created new GSMBSPort(%s %s).\n", portname, p_g_bs_name); } /* @@ -181,6 +193,15 @@ void Pgsm_bs::call_conf_ind(unsigned int msg_type, unsigned int callref, struct modify_lchan(media_types[0]); p_g_payload_type = payload_types[0]; } + + if (p_g_earlyb && !p_g_tch_connected) { /* only if ... */ + struct gsm_mncc *frame; + gsm_trace_header(p_interface_name, this, MNCC_FRAME_RECV, DIRECTION_OUT); + end_trace(); + frame = create_mncc(MNCC_FRAME_RECV, p_g_callref); + send_and_free_mncc(p_g_lcr_gsm, frame->msg_type, frame); + p_g_tch_connected = 1; + } } /* DTMF INDICATION */ @@ -395,6 +416,13 @@ void Pgsm_bs::select_payload_type(struct gsm_mncc *mncc, unsigned char *payload_ decoder = p_g_amr_decoder; half = 1; break; + case 0x80: + add_trace("speech", "version", "Analog 8000Hz given"); + media_type = MEDIA_TYPE_ANALOG; + payload_type = dynamic_type++; + encoder = (void *)1; + decoder = (void *)1; + break; default: add_trace("speech", "version", "%d given", mncc->bearer_cap.speech_ver[i]); media_type = 0; @@ -463,6 +491,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ if (p_g_callref) { /* release in case the ID is already in use */ add_trace("error", NULL, "callref already in use"); +reject: end_trace(); mncc = create_mncc(MNCC_REJ_REQ, callref); gsm_trace_header(p_interface_name, this, MNCC_REJ_REQ, DIRECTION_OUT); @@ -480,6 +509,11 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ trigger_work(&p_g_delete); return; } + if (callref < 0x40000000) { + /* release in case the ID is invalid */ + add_trace("error", NULL, "callref invalid, not of BSC type"); + goto reject; + } p_g_callref = callref; end_trace(); @@ -494,7 +528,20 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ p_callerinfo.present = INFO_PRESENT_NOTAVAIL; SCPY(p_callerinfo.imsi, mncc->imsi); p_callerinfo.screen = INFO_SCREEN_NETWORK; - p_callerinfo.ntype = INFO_NTYPE_UNKNOWN; + switch (mncc->calling.type) { + case 0x1: + p_callerinfo.ntype = INFO_NTYPE_INTERNATIONAL; + break; + case 0x2: + p_callerinfo.ntype = INFO_NTYPE_NATIONAL; + break; + case 0x4: + p_callerinfo.ntype = INFO_NTYPE_SUBSCRIBER; + break; + default: + p_callerinfo.ntype = INFO_NTYPE_UNKNOWN; + break; + } SCPY(p_callerinfo.interface, p_interface_name); /* dialing information */ @@ -571,7 +618,7 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ gsm_trace_header(p_interface_name, this, msg_type, DIRECTION_IN); if (p_callerinfo.id[0]) add_trace("calling", "number", "%s", p_callerinfo.id); - else + else if (p_callerinfo.imsi[0]) 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); @@ -647,38 +694,23 @@ void Pgsm_bs::setup_ind(unsigned int msg_type, unsigned int callref, struct gsm_ /* * BSC sends message to port */ -int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg) +int message_bsc(class Pgsm_bs *pgsm_bs, struct lcr_gsm *lcr_gsm, int msg_type, void *arg) { struct gsm_mncc *mncc = (struct gsm_mncc *)arg; unsigned int callref = mncc->callref; - class Port *port; - class Pgsm_bs *pgsm_bs = 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_GSM_MASK) == PORT_CLASS_GSM_BS) { - pgsm_bs = (class Pgsm_bs *)port; - if (pgsm_bs->p_g_callref == callref) { - break; - } - } - port = port->next; - } - if (msg_type == GSM_TCHF_FRAME || msg_type == GSM_TCHF_FRAME_EFR || msg_type == GSM_TCHH_FRAME || msg_type == GSM_TCH_FRAME_AMR + || msg_type == ANALOG_8000HZ || msg_type == GSM_BAD_FRAME) { - if (port) { + if (pgsm_bs) { /* inject DTMF, if enabled */ if (pgsm_bs->p_g_dtmf) { unsigned char data[160]; @@ -706,7 +738,7 @@ int message_bsc(struct lcr_gsm *lcr_gsm, int msg_type, void *arg) return 0; } - if (!port) { + if (!pgsm_bs) { struct interface *interface; if (msg_type != MNCC_SETUP_IND) @@ -807,6 +839,13 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame struct lcr_msg *message; struct epoint_list *epointlist; struct gsm_mncc *mncc; + struct interface *interface; + + interface = getinterfacebyname(p_interface_name); + if (!interface) { + PERROR("Cannot find interface %s.\n", p_interface_name); + return; + } /* copy setup infos to port */ memcpy(&p_callerinfo, ¶m->setup.callerinfo, sizeof(p_callerinfo)); @@ -1010,6 +1049,14 @@ void Pgsm_bs::message_setup(unsigned int epoint_id, int message_id, union parame add_trace("redir", "number", "%s", mncc->redirecting.number); } + if (interface->gsm_bs_hr) { + add_trace("lchan", "type", "TCH/H or TCH/F"); + mncc->lchan_type = GSM_LCHAN_TCH_H; + } else { + add_trace("lchan", "type", "TCH/F"); + mncc->lchan_type = GSM_LCHAN_TCH_F; + } + end_trace(); send_and_free_mncc(p_g_lcr_gsm, mncc->msg_type, mncc); @@ -1051,31 +1098,41 @@ 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_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; - } + /* destroy all instances */ + while (gsm_bs_first) + gsm_bs_delete(gsm_bs_first->name); + return rc; +} - return(rc); +int gsm_bs_init(void) +{ + return 0; } -int gsm_bs_init(struct interface *interface) +/* add a new GSM base station instance */ +int gsm_bs_new(struct interface *interface) { + struct lcr_gsm *gsm_bs = gsm_bs_first, **gsm_bs_p = &gsm_bs_first; + + while (gsm_bs) { + gsm_bs_p = &gsm_bs->gsm_next; + gsm_bs = gsm_bs->gsm_next; + } + + PDEBUG(DEBUG_GSM, "GSM: interface for BS '%s' is created\n", interface->gsm_bs_name); + /* create gsm instance */ gsm_bs = (struct lcr_gsm *)MALLOC(sizeof(struct lcr_gsm)); SCPY(gsm_bs->interface_name, interface->name); gsm_bs->type = LCR_GSM_TYPE_NETWORK; + SCPY(gsm_bs->name, interface->gsm_bs_name); gsm_bs->sun.sun_family = AF_UNIX; - SCPY(gsm_bs->sun.sun_path, "/tmp/bsc_mncc"); + if (gsm_bs->name[0]) + SPRINT(gsm_bs->sun.sun_path, "/tmp/bsc_mncc_%s", gsm_bs->name); + else + 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); @@ -1085,5 +1142,37 @@ int gsm_bs_init(struct interface *interface) generate_dtmf(); + *gsm_bs_p = gsm_bs; + return 0; } + +int gsm_bs_delete(const char *name) +{ + struct lcr_gsm *gsm_bs = gsm_bs_first, **gsm_bs_p = &gsm_bs_first; + + PDEBUG(DEBUG_GSM, "GSM: interface for BS '%s' is deleted\n", name); + + while (gsm_bs) { + if (gsm_bs->type == LCR_GSM_TYPE_NETWORK && !strcmp(gsm_bs->name, name)) + break; + gsm_bs_p = &gsm_bs->gsm_next; + gsm_bs = gsm_bs->gsm_next; + } + + if (!gsm_bs) + return 0; + + 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); + + /* remove instance from list */ + *gsm_bs_p = gsm_bs->gsm_next; + FREE(gsm_bs, sizeof(struct lcr_gsm)); + + return 0; +} +