summaryrefslogtreecommitdiff
path: root/plugins/policy.c
diff options
context:
space:
mode:
authorJohan Hedberg <johan.hedberg@intel.com>2014-05-13 16:44:40 +0300
committerJohan Hedberg <johan.hedberg@intel.com>2014-05-15 11:16:34 +0300
commit42fd4ce72c2b9bbc9ccf035964d90ada0b4a2796 (patch)
tree5921473663cac42f22162c5bc5ae0d48c554218f /plugins/policy.c
parentc3a21d33936d6fa7b896251a5751185f71a4d626 (diff)
downloadbluez-42fd4ce72c2b9bbc9ccf035964d90ada0b4a2796.tar.gz
plugins/policy: Add exponential backoff for reconnection attempts
Diffstat (limited to 'plugins/policy.c')
-rw-r--r--plugins/policy.c30
1 files changed, 23 insertions, 7 deletions
diff --git a/plugins/policy.c b/plugins/policy.c
index cff8dd6ae..93bad170e 100644
--- a/plugins/policy.c
+++ b/plugins/policy.c
@@ -59,6 +59,7 @@ struct reconnect_data {
guint timer;
bool active;
time_t start;
+ int timeout;
};
static const char *default_reconnect[] = {
@@ -423,6 +424,12 @@ static void target_cb(struct btd_service *service,
}
}
+static void reconnect_reset(struct reconnect_data *reconnect)
+{
+ reconnect->start = 0;
+ reconnect->timeout = 1;
+}
+
static bool reconnect_match(const char *uuid)
{
char **str;
@@ -554,7 +561,7 @@ static void service_cb(struct btd_service *service,
reconnect = reconnect_add(service);
reconnect->active = false;
- reconnect->start = 0;
+ reconnect_reset(reconnect);
/*
* Should this device be reconnected? A matching UUID might not
@@ -574,12 +581,19 @@ static gboolean reconnect_timeout(gpointer data)
DBG("Reconnecting profiles");
+ /* Mark the GSource as invalid */
reconnect->timer = 0;
+ /* Increase timeout for the next attempt if this * one fails. */
+ reconnect->timeout *= 2;
+
err = btd_device_connect_services(reconnect->dev, reconnect->services);
- if (err < 0)
+ if (err < 0) {
error("Reconnecting services failed: %s (%d)",
strerror(-err), -err);
+ reconnect_reset(reconnect);
+ return FALSE;
+ }
reconnect->active = true;
@@ -605,7 +619,7 @@ static void disconnect_cb(struct btd_device *dev, uint8_t reason)
DBG("Device %s identified for auto-reconnection",
device_get_path(dev));
- reconnect->timer = g_timeout_add_seconds(RECONNECT_TIMEOUT,
+ reconnect->timer = g_timeout_add_seconds(reconnect->timeout,
reconnect_timeout,
reconnect);
}
@@ -613,6 +627,7 @@ static void disconnect_cb(struct btd_device *dev, uint8_t reason)
static void conn_fail_cb(struct btd_device *dev, uint8_t status)
{
struct reconnect_data *reconnect;
+ time_t duration;
DBG("status %u", status);
@@ -627,17 +642,18 @@ static void conn_fail_cb(struct btd_device *dev, uint8_t status)
/* Give up if we were powered off */
if (status == MGMT_STATUS_NOT_POWERED) {
- reconnect->start = 0;
+ reconnect_reset(reconnect);
return;
}
/* Give up if we've tried for too long */
- if (time(NULL) - reconnect->start > RECONNECT_GIVE_UP) {
- reconnect->start = 0;
+ duration = time(NULL) - reconnect->start;
+ if (duration + reconnect->timeout >= RECONNECT_GIVE_UP) {
+ reconnect_reset(reconnect);
return;
}
- reconnect->timer = g_timeout_add_seconds(RECONNECT_TIMEOUT,
+ reconnect->timer = g_timeout_add_seconds(reconnect->timeout,
reconnect_timeout,
reconnect);
}