MNCC: Re-connect to the MNCC socket if connection was lost
[lcr.git] / gsm_bs.cpp
index 78ef8af..259e8a9 100644 (file)
@@ -26,6 +26,8 @@ extern "C" {
 #include <openbsc/trau_frame.h>
 }
 
+#define SOCKET_RETRY_TIMER     5
+
 /*
  * DTMF stuff
  */
@@ -815,6 +817,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;
@@ -861,18 +864,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();
 
@@ -940,24 +961,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;
+}
 
-       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;
+       strcpy(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);
+
+       return 0;
 }