diff options
author | Jacob Erlbeck <jerlbeck@sysmocom.de> | 2014-12-18 15:00:29 +0100 |
---|---|---|
committer | Holger Hans Peter Freyther <holger@moiji-mobile.com> | 2015-01-18 17:24:37 +0100 |
commit | 849d0a83e8598e0f21a3e9c5438c222d8ab417eb (patch) | |
tree | bae240697759ec34811a1bcce2795c139fa6b5e4 /openbsc | |
parent | 7660ffa29fb463fc24b2ac8d735b9b345017bba6 (diff) |
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
Diffstat (limited to 'openbsc')
-rw-r--r-- | openbsc/include/openbsc/gprs_gsup_client.h | 7 | ||||
-rw-r--r-- | 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 <osmocom/core/timer.h> + +#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 <openbsc/debug.h> #include <errno.h> +#include <string.h> 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) |