From: Pablo Neira Ayuso <pablo(a)gnumonks.org>
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