summaryrefslogtreecommitdiff
path: root/plugins
diff options
context:
space:
mode:
authorLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2015-04-01 12:54:19 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2015-04-08 10:23:14 +0300
commit3b7ad511ea4a18360b7ea30f74008f83b5e625c5 (patch)
tree8ed48e10ef8dfd3cb63333d2ddb7dc726b7bf429 /plugins
parente59ef82d91b9fe12ca8e7a4a9322de12574c8fae (diff)
downloadbluez-3b7ad511ea4a18360b7ea30f74008f83b5e625c5.tar.gz
policy: Add parameters to control reconnection
This adds ReconnectAttempts and ReconnectIntervals so platforms can fine tune the reconnection strategy.
Diffstat (limited to 'plugins')
-rw-r--r--plugins/policy.c85
1 files changed, 57 insertions, 28 deletions
diff --git a/plugins/policy.c b/plugins/policy.c
index 45706f62a..809868914 100644
--- a/plugins/policy.c
+++ b/plugins/policy.c
@@ -55,24 +55,26 @@
#define CT_RETRIES 1
#define TG_RETRIES CT_RETRIES
-/* Tracking of remote services to be auto-reconnected upon link loss */
-
-#define RECONNECT_GIVE_UP (3 * 60)
-#define RECONNECT_TIMEOUT 1
-
struct reconnect_data {
struct btd_device *dev;
bool reconnect;
GSList *services;
guint timer;
bool active;
- time_t start;
- int timeout;
+ int attempt;
};
static const char *default_reconnect[] = {
HSP_AG_UUID, HFP_AG_UUID, A2DP_SOURCE_UUID, NULL };
static char **reconnect_uuids = NULL;
+
+static const int default_attempts = 7;
+static int reconnect_attempts = 0;
+
+static const int default_intervals[] = { 1, 2, 4, 8, 16, 32, 64 };
+static int *reconnect_intervals = NULL;
+static int reconnect_intervals_len = 0;
+
static GSList *reconnects = NULL;
static unsigned int service_id = 0;
@@ -491,8 +493,7 @@ static void target_cb(struct btd_service *service,
static void reconnect_reset(struct reconnect_data *reconnect)
{
- reconnect->start = 0;
- reconnect->timeout = 1;
+ reconnect->attempt = 0;
if (reconnect->timer > 0) {
g_source_remove(reconnect->timer);
@@ -664,9 +665,6 @@ static gboolean reconnect_timeout(gpointer data)
/* 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) {
error("Reconnecting services failed: %s (%d)",
@@ -676,13 +674,24 @@ static gboolean reconnect_timeout(gpointer data)
}
reconnect->active = true;
-
- if (!reconnect->start)
- reconnect->start = time(NULL);
+ reconnect->attempt++;
return FALSE;
}
+static void reconnect_set_timer(struct reconnect_data *reconnect)
+{
+ static int timeout = 0;
+
+ if (reconnect->attempt < reconnect_intervals_len)
+ timeout = reconnect_intervals[reconnect->attempt];
+
+ DBG("%d seconds", timeout);
+
+ reconnect->timer = g_timeout_add_seconds(timeout, reconnect_timeout,
+ reconnect);
+}
+
static void disconnect_cb(struct btd_device *dev, uint8_t reason)
{
struct reconnect_data *reconnect;
@@ -699,15 +708,12 @@ 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_timeout,
- reconnect);
+ reconnect_set_timer(reconnect);
}
static void conn_fail_cb(struct btd_device *dev, uint8_t status)
{
struct reconnect_data *reconnect;
- time_t duration;
DBG("status %u", status);
@@ -726,16 +732,13 @@ static void conn_fail_cb(struct btd_device *dev, uint8_t status)
return;
}
- /* Give up if we've tried for too long */
- duration = time(NULL) - reconnect->start;
- if (duration + reconnect->timeout >= RECONNECT_GIVE_UP) {
+ /* Reset if ReconnectAttempts was reached */
+ if (reconnect->attempt == reconnect_attempts) {
reconnect_reset(reconnect);
return;
}
- reconnect->timer = g_timeout_add_seconds(reconnect->timeout,
- reconnect_timeout,
- reconnect);
+ reconnect_set_timer(reconnect);
}
static int policy_init(void)
@@ -748,6 +751,11 @@ static int policy_init(void)
conf = btd_get_main_conf();
if (!conf) {
reconnect_uuids = g_strdupv((char **) default_reconnect);
+ reconnect_attempts = default_attempts;
+ reconnect_intervals_len = sizeof(default_intervals) /
+ sizeof(*reconnect_intervals);
+ reconnect_intervals = g_memdup(default_intervals,
+ reconnect_intervals_len);
goto add_cb;
}
@@ -755,12 +763,31 @@ static int policy_init(void)
"ReconnectUUIDs",
NULL, &gerr);
if (gerr) {
- g_error_free(gerr);
+ g_clear_error(&gerr);
reconnect_uuids = g_strdupv((char **) default_reconnect);
- goto add_cb;
}
+
+ reconnect_attempts = g_key_file_get_integer(conf, "Policy",
+ "ReconnectAttempts",
+ &gerr);
+ if (gerr) {
+ g_clear_error(&gerr);
+ reconnect_attempts = default_attempts;
+ }
+
+ reconnect_intervals = g_key_file_get_integer_list(conf, "Policy",
+ "ReconnectIntervals",
+ (size_t *) &reconnect_intervals_len,
+ &gerr);
+ if (gerr) {
+ g_clear_error(&gerr);
+ reconnect_intervals_len = sizeof(default_intervals);
+ reconnect_intervals = g_memdup(default_intervals,
+ reconnect_intervals_len);
+ }
+
add_cb:
- if (reconnect_uuids && reconnect_uuids[0]) {
+ if (reconnect_uuids && reconnect_uuids[0] && reconnect_attempts) {
btd_add_disconnect_cb(disconnect_cb);
btd_add_conn_fail_cb(conn_fail_cb);
}
@@ -776,6 +803,8 @@ static void policy_exit(void)
if (reconnect_uuids)
g_strfreev(reconnect_uuids);
+ g_free(reconnect_intervals);
+
g_slist_free_full(reconnects, reconnect_destroy);
g_slist_free_full(devices, policy_remove);