X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=gsm_bs.cpp;h=2da06c74099c30cd6cdcba7410120c093aba6330;hp=8bb647f2db4778af7767bcb50e2285db133d7936;hb=b6eb8547861d8bafe3f59d0c4a732e0f4ce862fc;hpb=dd2ae2236f653cbbca28979e81bf8a8eb7b049fb diff --git a/gsm_bs.cpp b/gsm_bs.cpp index 8bb647f..2da06c7 100644 --- a/gsm_bs.cpp +++ b/gsm_bs.cpp @@ -26,6 +26,8 @@ extern "C" { #include } +#define SOCKET_RETRY_TIMER 5 + /* * DTMF stuff */ @@ -91,6 +93,7 @@ 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); @@ -561,6 +564,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 (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 = 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; + } + /* no number */ if (!p_dialinginfo.id[0]) { gsm_trace_header(p_m_mISDNport, this, MNCC_SETUP_REQ, DIRECTION_OUT); @@ -779,18 +796,8 @@ int Pgsm_bs::message_epoint(unsigned int epoint_id, int message_id, union parame int gsm_bs_exit(int rc) { -#if 0 - /* 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 */ -// } - } -#endif + gsm->network = NULL; + return(rc); } @@ -862,18 +869,36 @@ int mncc_send(struct gsm_network *instance, int msg_type, void *data) /* close MNCC socket */ static int mncc_fd_close(struct lcr_fd *lfd) { - printf("mncc_sock: closing\n"); + class Port *port; + class Pgsm_bs *pgsm_bs = NULL; + struct lcr_msg *message; + + PERROR("Lost MNCC socket, retrying in %u seconds\n", SOCKET_RETRY_TIMER); close(lfd->fd); unregister_fd(lfd); lfd->fd = -1; + /* free all the calls that were running through the MNCC interface */ + port = port_first; + while(port) { + if ((port->p_type & PORT_CLASS_GSM_MASK) == PORT_CLASS_GSM_BS) { + pgsm_bs = (class Pgsm_bs *)port; + message = message_create(pgsm_bs->p_serial, ACTIVE_EPOINT(pgsm_bs->p_epointlist), PORT_TO_EPOINT, MESSAGE_RELEASE); + message->param.disconnectinfo.cause = 27; // temp. unavail. + message->param.disconnectinfo.location = LOCATION_PRIVATE_LOCAL; + message_put(message); + pgsm_bs->new_state(PORT_STATE_RELEASE); + trigger_work(&pgsm_bs->p_m_g_delete); + } + port = port->next; + } + /* flush the queue */ while (mncc_q_dequeue()) ; - /* FIXME: free all the calls that were running through the MNCC interface */ - - /* FIXME: start a re-connect timer */ + /* start the re-connect timer */ + schedule_timer(&gsm->socket_retry, SOCKET_RETRY_TIMER, 0); generate_dtmf(); @@ -897,7 +922,7 @@ static int mncc_fd_write(struct lcr_fd *lfd, void *inst, int idx) return mncc_fd_close(lfd); if (rc < 0) return rc; - if (rc < qe->len) + if (rc < (int)qe->len) return -1; /* dequeue the successfully sent message */ qe2 = mncc_q_dequeue(); @@ -941,24 +966,45 @@ static int mncc_fd_cb(struct lcr_fd *lfd, unsigned int what, void *instance, int return rc; } -int gsm_bs_init(void) +static int socket_retry_cb(struct lcr_timer *timer, void *instance, int index) { - struct sockaddr_un sun; - int rc; + int fd, rc; - rc = socket(PF_UNIX, SOCK_SEQPACKET, 0); - if (rc < 0) - return rc; + fd = socket(PF_UNIX, SOCK_SEQPACKET, 0); + if (fd < 0) { + PERROR("Cannot create SEQPACKET socket, giving up!\n"); + return fd; + } - gsm->mncc_lfd.fd = rc; + rc = connect(fd, (struct sockaddr *) &gsm->sun, + sizeof(gsm->sun)); + if (rc < 0) { + PERROR("Could not connect to MNCC socket, " + "retrying in %u seconds\n", SOCKET_RETRY_TIMER); + close(fd); + schedule_timer(&gsm->socket_retry, SOCKET_RETRY_TIMER, 0); + } else { + PDEBUG(DEBUG_GSM, "Connected to MNCC socket!\n"); + gsm->mncc_lfd.fd = fd; + register_fd(&gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, NULL, 0); + } - sun.sun_family = AF_UNIX; - strcpy(sun.sun_path, "/tmp/bsc_mncc"); - rc = connect(rc, (struct sockaddr *)&sun, sizeof(sun)); - if (rc < 0) - return rc; + return 0; +} - rc = register_fd(&gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, NULL, 0); +int gsm_bs_init(void) +{ + gsm->sun.sun_family = AF_UNIX; + SCPY(gsm->sun.sun_path, "/tmp/bsc_mncc"); - return rc; + memset(&gsm->socket_retry, 0, sizeof(gsm->socket_retry)); + add_timer(&gsm->socket_retry, socket_retry_cb, NULL, 0); + + /* do the initial connect */ + socket_retry_cb(&gsm->socket_retry, NULL, 0); + + /* dummy instance */ + gsm->network = (void *)1; + + return 0; }