From: Pablo Neira Ayuso <[email protected]>

In case of problems to transmit message, spot an error and
close the socket to force a re-establishment.

This also modifies ipa_client_read to close the socket in
case that our callback reports an error.
---
 src/input/ipa.c      |   10 ++++++--
 src/input/ipaccess.c |   66 +++++++++++++++++++++++++++++++++++++++++---------
 2 files changed, 63 insertions(+), 13 deletions(-)

diff --git a/src/input/ipa.c b/src/input/ipa.c
index 3c6a507..015d957 100644
--- a/src/input/ipa.c
+++ b/src/input/ipa.c
@@ -131,8 +131,14 @@ static void ipa_client_read(struct ipa_client_conn *link)
                ipa_client_retry(link);
                return;
        }
-       if (link->read_cb)
-               link->read_cb(link, msg);
+       if (link->read_cb) {
+               ret = link->read_cb(link, msg);
+               if (ret < 0) {
+                       LOGP(DLINP, LOGL_ERROR, "connection closed with "
+                                               "server\n");
+                       ipa_client_retry(link);
+               }
+       }
 }
 
 static void ipa_client_write(struct ipa_client_conn *link)
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index c69ae24..e59ab18 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -189,26 +189,33 @@ int ipaccess_send_id_req(int fd)
 /* base handling of the ip.access protocol */
 int ipaccess_rcvmsg_base(struct msgb *msg, struct osmo_fd *bfd)
 {
-       int ipa_ccm = 0;
        uint8_t msg_type = *(msg->l2h);
        int ret = 0;
 
        switch (msg_type) {
        case IPAC_MSGT_PING:
-               ipa_ccm = 1;
                ret = ipaccess_send_pong(bfd->fd);
+               if (ret < 0) {
+                       LOGP(DLINP, LOGL_ERROR, "cannot send PING "
+                            "message. Reason: %s\n", strerror(errno));
+               } else
+                       ret = 1;
                break;
        case IPAC_MSGT_PONG:
                DEBUGP(DLMI, "PONG!\n");
-               ipa_ccm = 1;
+               ret = 1;
                break;
        case IPAC_MSGT_ID_ACK:
                DEBUGP(DLMI, "ID_ACK? -> ACK!\n");
-               ipa_ccm = 1;
                ret = ipaccess_send_id_ack(bfd->fd);
+               if (ret < 0) {
+                       LOGP(DLINP, LOGL_ERROR, "cannot send ID_ACK "
+                            "message. Reason: %s\n", strerror(errno));
+               } else
+                       ret = 1;
                break;
        }
-       return ipa_ccm;
+       return ret;
 }
 
 /* base handling of the ip.access protocol */
@@ -221,6 +228,10 @@ int ipaccess_rcvmsg_bts_base(struct msgb *msg,
        switch (msg_type) {
        case IPAC_MSGT_PING:
                ret = ipaccess_send_pong(bfd->fd);
+               if (ret < 0) {
+                       LOGP(DLINP, LOGL_ERROR, "cannot send PONG "
+                            "message. Reason: %s\n", strerror(errno));
+               }
                break;
        case IPAC_MSGT_PONG:
                DEBUGP(DLMI, "PONG!\n");
@@ -229,7 +240,7 @@ int ipaccess_rcvmsg_bts_base(struct msgb *msg,
                DEBUGP(DLMI, "ID_ACK\n");
                break;
        }
-       return 0;
+       return ret;
 }
 
 static int ipaccess_drop(struct osmo_fd *bfd)
@@ -269,8 +280,15 @@ static int ipaccess_rcvmsg(struct e1inp_line *line, struct 
msgb *msg,
        int len, ret;
 
        /* Handle IPA PING, PONG and ID_ACK messages. */
-       if (ipaccess_rcvmsg_base(msg, bfd))
+       ret = ipaccess_rcvmsg_base(msg, bfd);
+       switch(ret) {
+       case -1:
+               /* error in IPA control message handling */
+               goto err;
+       case 1:
+               /* this is an IPA control message, skip further processing */
                return 0;
+       }
 
        switch (msg_type) {
        case IPAC_MSGT_ID_RESP:
@@ -517,6 +535,16 @@ static int __handle_ts1_write(struct osmo_fd *bfd, struct 
e1inp_line *line)
        DEBUGP(DLMI, "TX %u: %s\n", ts_nr, osmo_hexdump(msg->l2h, 
msgb_l2len(msg)));
 
        ret = send(bfd->fd, msg->data, msg->len, 0);
+       if (ret < 0) {
+               LOGP(DLINP, LOGL_ERROR, "failed to send A-bis IPA signalling "
+                       "message. Reason: %s\n", strerror(errno));
+               if (ipaccess_drop(bfd) >= 0) {
+                       LOGP(DLINP, LOGL_NOTICE, "Sign link problems, "
+                       "closing socket. Reason: %s\n", strerror(errno));
+                       return ret;
+               }
+       }
+
        msgb_free(msg);
 
        /* set tx delay timer for next event */
@@ -759,13 +787,16 @@ static int ipaccess_bts_cb(struct ipa_client_conn *link, 
struct msgb *msg)
        struct ipaccess_head *hh = (struct ipaccess_head *) msg->data;
        struct e1inp_ts *e1i_ts = NULL;
        struct e1inp_sign_link *sign_link;
+       int ret = 0;
 
        /* special handling for IPA CCM. */
        if (hh->proto == IPAC_PROTO_IPACCESS) {
                uint8_t msg_type = *(msg->l2h);
 
                /* ping, pong and acknowledgment cases. */
-               ipaccess_rcvmsg_bts_base(msg, link->ofd);
+               ret = ipaccess_rcvmsg_bts_base(msg, link->ofd);
+               if (ret < 0)
+                       return ret;
 
                /* this is a request for identification from the BSC. */
                if (msg_type == IPAC_MSGT_ID_GET) {
@@ -798,15 +829,28 @@ static int ipaccess_bts_cb(struct ipa_client_conn *link, 
struct msgb *msg)
                        }
                        rmsg = ipa_bts_id_resp(link->line->ops->cfg.ipa.dev,
                                                data + 1, len - 1);
-                       ipaccess_send(link->ofd->fd, rmsg->data, rmsg->len);
+                       ret = ipaccess_send(link->ofd->fd, rmsg->data,
+                                               rmsg->len);
                        msgb_free(rmsg);
 
+                       if (ret < 0) {
+                               LOGP(DLINP, LOGL_ERROR, "cannot send ID_RESP "
+                                    "message. Reason: %s\n", strerror(errno));
+                               return ret;
+                       }
+
                        /* send ID_ACK. */
                        rmsg = ipa_bts_id_ack();
-                       ipaccess_send(link->ofd->fd, rmsg->data, rmsg->len);
+                       ret = ipaccess_send(link->ofd->fd, rmsg->data,
+                                               rmsg->len);
                        msgb_free(rmsg);
+
+                       if (ret < 0) {
+                               LOGP(DLINP, LOGL_ERROR, "cannot send ID_ACK "
+                                    "message. Reason: %s\n", strerror(errno));
+                       }
                }
-               return 0;
+               return ret;
        } else if (link->port == IPA_TCP_PORT_OML)
                e1i_ts = &link->line->ts[0];
        else if (link->port == IPA_TCP_PORT_RSL)
-- 
1.7.10.4


Reply via email to