aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2013-06-30 20:13:16 +0200
committerHarald Welte <laforge@gnumonks.org>2013-10-06 11:55:18 +0200
commit51de9ca3a64ccb652acdfa72f4f4bd27a60f474b (patch)
treebd107de8fd7f909c0e54823398b6eeb0a9e5e32d
parenta3e9dd57570630d020fdf308d38e0650801da0a5 (diff)
IPA: remove automatic reconnect logic
When an IPA link is in client (BTS) mode, we should not automatically re-connect in the lowest (ipa) layer. Instead, we properly close the socket if the link is dead, and we call link->updown_cb() to notify the user that the link is down. The e1inp/ipaccess layer translates this into a line->sign_link_down() callback that propagates up to the user.
-rw-r--r--include/osmocom/abis/ipa.h4
-rw-r--r--src/input/ipa.c57
-rw-r--r--src/input/ipaccess.c15
3 files changed, 34 insertions, 42 deletions
diff --git a/include/osmocom/abis/ipa.h b/include/osmocom/abis/ipa.h
index 397cf9c..d577d74 100644
--- a/include/osmocom/abis/ipa.h
+++ b/include/osmocom/abis/ipa.h
@@ -49,13 +49,13 @@ struct ipa_client_conn {
enum ipa_client_conn_state state;
const char *addr;
uint16_t port;
- int (*connect_cb)(struct ipa_client_conn *link);
+ void (*updown_cb)(struct ipa_client_conn *link, int up);
int (*read_cb)(struct ipa_client_conn *link, struct msgb *msg);
int (*write_cb)(struct ipa_client_conn *link);
void *data;
};
-struct ipa_client_conn *ipa_client_conn_create(void *ctx, struct e1inp_ts *ts, int priv_nr, const char *addr, uint16_t port, int (*connect)(struct ipa_client_conn *link), int (*read_cb)(struct ipa_client_conn *link, struct msgb *msgb), int (*write_cb)(struct ipa_client_conn *link), void *data);
+struct ipa_client_conn *ipa_client_conn_create(void *ctx, struct e1inp_ts *ts, int priv_nr, const char *addr, uint16_t port, void (*updown)(struct ipa_client_conn *link, int), int (*read_cb)(struct ipa_client_conn *link, struct msgb *msgb), int (*write_cb)(struct ipa_client_conn *link), void *data);
void ipa_client_conn_destroy(struct ipa_client_conn *link);
int ipa_client_conn_open(struct ipa_client_conn *link);
diff --git a/src/input/ipa.c b/src/input/ipa.c
index 8c6f603..ba92163 100644
--- a/src/input/ipa.c
+++ b/src/input/ipa.c
@@ -95,17 +95,6 @@ int ipa_msg_recv(int fd, struct msgb **rmsg)
return ret;
}
-void ipa_client_conn_close(struct ipa_client_conn *link);
-
-static void ipa_client_retry(struct ipa_client_conn *link)
-{
- LOGP(DLINP, LOGL_NOTICE, "connection closed\n");
- ipa_client_conn_close(link);
- LOGP(DLINP, LOGL_NOTICE, "retrying in 5 seconds...\n");
- osmo_timer_schedule(&link->timer, 5, 0);
- link->state = IPA_CLIENT_LINK_STATE_CONNECTING;
-}
-
void ipa_client_conn_close(struct ipa_client_conn *link)
{
/* be safe against multiple calls */
@@ -129,11 +118,15 @@ static void ipa_client_read(struct ipa_client_conn *link)
if (errno == EPIPE || errno == ECONNRESET) {
LOGP(DLINP, LOGL_ERROR, "lost connection with server\n");
}
- ipa_client_retry(link);
+ ipa_client_conn_close(link);
+ if (link->updown_cb)
+ link->updown_cb(link, 0);
return;
} else if (ret == 0) {
LOGP(DLINP, LOGL_ERROR, "connection closed with server\n");
- ipa_client_retry(link);
+ ipa_client_conn_close(link);
+ if (link->updown_cb)
+ link->updown_cb(link, 0);
return;
}
if (link->read_cb)
@@ -166,7 +159,9 @@ static int ipa_client_write_default_cb(struct ipa_client_conn *link)
ret = send(link->ofd->fd, msg->data, msg->len, 0);
if (ret < 0) {
if (errno == EPIPE || errno == ENOTCONN) {
- ipa_client_retry(link);
+ ipa_client_conn_close(link);
+ if (link->updown_cb)
+ link->updown_cb(link, 0);
}
LOGP(DLINP, LOGL_ERROR, "error to send\n");
}
@@ -184,14 +179,16 @@ static int ipa_client_fd_cb(struct osmo_fd *ofd, unsigned int what)
case IPA_CLIENT_LINK_STATE_CONNECTING:
ret = getsockopt(ofd->fd, SOL_SOCKET, SO_ERROR, &error, &len);
if (ret >= 0 && error > 0) {
- ipa_client_retry(link);
+ ipa_client_conn_close(link);
+ if (link->updown_cb)
+ link->updown_cb(link, 0);
return 0;
}
ofd->when &= ~BSC_FD_WRITE;
LOGP(DLINP, LOGL_NOTICE, "connection done.\n");
link->state = IPA_CLIENT_LINK_STATE_CONNECTED;
- if (link->connect_cb)
- link->connect_cb(link);
+ if (link->updown_cb)
+ link->updown_cb(link, 1);
break;
case IPA_CLIENT_LINK_STATE_CONNECTED:
if (what & BSC_FD_READ) {
@@ -209,12 +206,10 @@ static int ipa_client_fd_cb(struct osmo_fd *ofd, unsigned int what)
return 0;
}
-static void ipa_link_timer_cb(void *data);
-
struct ipa_client_conn *
ipa_client_conn_create(void *ctx, struct e1inp_ts *ts,
int priv_nr, const char *addr, uint16_t port,
- int (*connect_cb)(struct ipa_client_conn *link),
+ void (*updown_cb)(struct ipa_client_conn *link, int up),
int (*read_cb)(struct ipa_client_conn *link,
struct msgb *msgb),
int (*write_cb)(struct ipa_client_conn *link),
@@ -244,12 +239,11 @@ ipa_client_conn_create(void *ctx, struct e1inp_ts *ts,
ipa_link->ofd->priv_nr = priv_nr;
ipa_link->ofd->cb = ipa_client_fd_cb;
ipa_link->ofd->data = ipa_link;
+ ipa_link->ofd->fd = -1;
ipa_link->state = IPA_CLIENT_LINK_STATE_CONNECTING;
- ipa_link->timer.cb = ipa_link_timer_cb;
- ipa_link->timer.data = ipa_link;
ipa_link->addr = talloc_strdup(ipa_link, addr);
ipa_link->port = port;
- ipa_link->connect_cb = connect_cb;
+ ipa_link->updown_cb = updown_cb;
ipa_link->read_cb = read_cb;
/* default to generic write callback if not set. */
if (write_cb == NULL)
@@ -284,24 +278,11 @@ int ipa_client_conn_open(struct ipa_client_conn *link)
link->ofd->fd = ret;
if (osmo_fd_register(link->ofd) < 0) {
close(ret);
+ link->ofd->fd = -1;
return -EIO;
}
- return 0;
-}
-static void ipa_link_timer_cb(void *data)
-{
- struct ipa_client_conn *link = data;
-
- LOGP(DLINP, LOGL_NOTICE, "reconnecting.\n");
-
- switch(link->state) {
- case IPA_CLIENT_LINK_STATE_CONNECTING:
- ipa_client_conn_open(link);
- break;
- default:
- break;
- }
+ return 0;
}
void ipa_client_conn_send(struct ipa_client_conn *link, struct msgb *msg)
diff --git a/src/input/ipaccess.c b/src/input/ipaccess.c
index 6663b9f..cf0cc15 100644
--- a/src/input/ipaccess.c
+++ b/src/input/ipaccess.c
@@ -800,6 +800,17 @@ static struct msgb *ipa_bts_id_ack(void)
return nmsg2;
}
+static void ipaccess_bts_updown_cb(struct ipa_client_conn *link, int up)
+{
+ struct e1inp_line *line = link->line;
+
+ if (up)
+ return;
+
+ if (line->ops->sign_link_down)
+ line->ops->sign_link_down(line);
+}
+
static int ipaccess_bts_read_cb(struct ipa_client_conn *link, struct msgb *msg)
{
struct ipaccess_head *hh = (struct ipaccess_head *) msg->data;
@@ -973,7 +984,7 @@ static int ipaccess_line_update(struct e1inp_line *line)
E1INP_SIGN_OML,
line->ops->cfg.ipa.addr,
IPA_TCP_PORT_OML,
- NULL,
+ ipaccess_bts_updown_cb,
ipaccess_bts_read_cb,
ipaccess_bts_write_cb,
line);
@@ -1007,7 +1018,7 @@ int e1inp_ipa_bts_rsl_connect(struct e1inp_line *line,
&line->ts[E1INP_SIGN_RSL-1],
E1INP_SIGN_RSL,
rem_addr, rem_port,
- NULL,
+ ipaccess_bts_updown_cb,
ipaccess_bts_read_cb,
ipaccess_bts_write_cb,
line);