From 849d0a83e8598e0f21a3e9c5438c222d8ab417eb Mon Sep 17 00:00:00 2001 From: Jacob Erlbeck Date: Thu, 18 Dec 2014 15:00:29 +0100 Subject: gprs: Add automatic re-connect if the GSUP connection is down Currently the GSUP connection to a server is not restarted if the connection cannot be established or is terminated during operation. This commit adds a timer based connection mechanism, basically consisting of a timer callback that calls gsup_client_connect. The timer is eventually triggered (up == 0) or cleared (up != 0) by gsup_client_updown_cb. It adds calls to osmo_timer_del() to gsup_client_connect and gprs_gsup_client_destroy. The latter is now called instead of talloc_free in gprs_gsup_client_create on error to be on the safe side. Sponsored-by: On-Waves ehf --- openbsc/include/openbsc/gprs_gsup_client.h | 7 +++ openbsc/src/gprs/gprs_gsup_client.c | 76 +++++++++++++++++++++++++++--- 2 files changed, 76 insertions(+), 7 deletions(-) diff --git a/openbsc/include/openbsc/gprs_gsup_client.h b/openbsc/include/openbsc/gprs_gsup_client.h index 89034e00a..1165c4a78 100644 --- a/openbsc/include/openbsc/gprs_gsup_client.h +++ b/openbsc/include/openbsc/gprs_gsup_client.h @@ -21,6 +21,10 @@ */ #pragma once +#include + +#define GPRS_GSUP_RECONNECT_INTERVAL 10 + struct msgb; struct ipa_client_conn; struct gprs_gsup_client; @@ -32,6 +36,9 @@ struct gprs_gsup_client { struct ipa_client_conn *link; gprs_gsup_read_cb_t read_cb; void *data; + + struct osmo_timer_list connect_timer; + int is_connected; }; struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, diff --git a/openbsc/src/gprs/gprs_gsup_client.c b/openbsc/src/gprs/gprs_gsup_client.c index 15988bcc8..52099005c 100644 --- a/openbsc/src/gprs/gprs_gsup_client.c +++ b/openbsc/src/gprs/gprs_gsup_client.c @@ -29,14 +29,69 @@ #include #include +#include extern void *tall_bsc_ctx; +static int gsup_client_connect(struct gprs_gsup_client *gsupc) +{ + int rc; + + if (gsupc->is_connected) + return 0; + + if (osmo_timer_pending(&gsupc->connect_timer)) { + LOGP(DLINP, LOGL_DEBUG, + "GSUP connect: connect timer already running\n"); + osmo_timer_del(&gsupc->connect_timer); + } + + rc = ipa_client_conn_open(gsupc->link); + + if (rc >= 0) + return rc; + + LOGP(DGPRS, LOGL_INFO, "GSUP failed to connect to %s:%d: %s\n", + gsupc->link->addr, gsupc->link->port, strerror(-rc)); + + if (rc == -EBADF || rc == -ENOTSOCK || rc == -EAFNOSUPPORT || + rc == -EINVAL) + return rc; + + osmo_timer_schedule(&gsupc->connect_timer, GPRS_GSUP_RECONNECT_INTERVAL, 0); + + return 0; +} + +static void connect_timer_cb(void *gsupc_) +{ + struct gprs_gsup_client *gsupc = gsupc_; + + if (gsupc->is_connected) + return; + + gsup_client_connect(gsupc); +} + static void gsup_client_updown_cb(struct ipa_client_conn *link, int up) { + struct gprs_gsup_client *gsupc = link->data; + LOGP(DGPRS, LOGL_NOTICE, "GSUP link to %s:%d %s\n", link->addr, link->port, up ? "UP" : "DOWN"); + gsupc->is_connected = up; + + if (up) { + /* TODO: Start ping procedure */ + + osmo_timer_del(&gsupc->connect_timer); + } else { + /* TODO: Stop ping procedure */ + + osmo_timer_schedule(&gsupc->connect_timer, + GPRS_GSUP_RECONNECT_INTERVAL, 0); + } } static int gsup_client_read_cb(struct ipa_client_conn *link, struct msgb *msg) @@ -90,26 +145,33 @@ struct gprs_gsup_client *gprs_gsup_client_create(const char *ip_addr, if (!gsupc->link) goto failed; - rc = ipa_client_conn_open(gsupc->link); + gsupc->connect_timer.data = gsupc; + gsupc->connect_timer.cb = &connect_timer_cb; - if (rc < 0 && rc != -EINPROGRESS) { - LOGP(DGPRS, LOGL_NOTICE, "GSUP failed to connect to %s:%d\n", - ip_addr, tcp_port); + rc = gsup_client_connect(gsupc); + + if (rc < 0 && rc != -EINPROGRESS) goto failed; - } gsupc->read_cb = read_cb; return gsupc; failed: - talloc_free(gsupc); + gprs_gsup_client_destroy(gsupc); return NULL; } void gprs_gsup_client_destroy(struct gprs_gsup_client *gsupc) { - ipa_client_conn_destroy(gsupc->link); + osmo_timer_del(&gsupc->connect_timer); + + if (gsupc->link) { + ipa_client_conn_close(gsupc->link); + ipa_client_conn_destroy(gsupc->link); + gsupc->link = NULL; + } + talloc_free(gsupc); } int gprs_gsup_client_send(struct gprs_gsup_client *gsupc, struct msgb *msg) -- cgit v1.2.3