summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJacob Erlbeck <jerlbeck@sysmocom.de>2014-12-18 15:00:29 +0100
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2015-01-18 17:24:37 +0100
commit849d0a83e8598e0f21a3e9c5438c222d8ab417eb (patch)
treebae240697759ec34811a1bcce2795c139fa6b5e4
parent7660ffa29fb463fc24b2ac8d735b9b345017bba6 (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
-rw-r--r--openbsc/include/openbsc/gprs_gsup_client.h7
-rw-r--r--openbsc/src/gprs/gprs_gsup_client.c76
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)