X-Git-Url: http://git.eversberg.eu/gitweb.cgi?p=lcr.git;a=blobdiff_plain;f=gsm_bs.cpp;h=e25732aacc7c5ae00255af97e5f299676c35dd66;hp=710c2370c4bf690c64448a5078af5308c33bd5ca;hb=2f5c3dc13063fc5e4cc4b72d2c3484be238c142e;hpb=d40eedaf166b92a428c01088ce05079f93d590bf diff --git a/gsm_bs.cpp b/gsm_bs.cpp index 710c237..e25732a 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); @@ -815,6 +832,7 @@ static int mncc_q_enqueue(struct gsm_mncc *mncc, unsigned int len) } else { /* append to tail of list */ gsm->mncc_q_tail->next = qe; + gsm->mncc_q_tail = qe; } gsm->mncc_lfd.when |= LCR_FD_WRITE; @@ -846,7 +864,7 @@ int mncc_send(struct gsm_network *instance, int msg_type, void *data) /* FIXME: the caller should provide this */ switch (msg_type) { case GSM_TCHF_FRAME: - len = 33; + len = sizeof(struct gsm_data_frame) + 33; break; default: len = sizeof(struct gsm_mncc); @@ -861,17 +879,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) { + 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(); @@ -895,7 +932,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(); @@ -939,24 +976,42 @@ 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; +} + +int gsm_bs_init(void) +{ + gsm->sun.sun_family = AF_UNIX; + SCPY(gsm->sun.sun_path, "/tmp/bsc_mncc"); - rc = register_fd(&gsm->mncc_lfd, LCR_FD_READ, &mncc_fd_cb, NULL, 0); + memset(&gsm->socket_retry, 0, sizeof(gsm->socket_retry)); + add_timer(&gsm->socket_retry, socket_retry_cb, NULL, 0); - return rc; + /* do the initial connect */ + socket_retry_cb(&gsm->socket_retry, NULL, 0); + + return 0; }