summaryrefslogtreecommitdiff
path: root/src/device.c
diff options
context:
space:
mode:
authorArchie Pusaka <apusaka@chromium.org>2021-11-25 15:06:25 +0800
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2021-11-29 09:43:42 -0800
commitee004ee7bd8f3d4e10ee4e3eadacbaca4b3b0936 (patch)
tree760106963a3eedc2b6c7131c211ebf0c6772125d /src/device.c
parent69c7d34744e5ea1ca84b20ea3fe8f83436567e70 (diff)
downloadbluez-ee004ee7bd8f3d4e10ee4e3eadacbaca4b3b0936.tar.gz
device: Save remote name request attempts into cache file
Since a peer device is potentially removed if not discovered for more than 30 seconds, we would lost the remote name request activity when the device is rediscovered. This could end up with a remote name request much sooner than we intend it to be. Therefore, put the RNR record into a cache file, so we can recover it when the peer device is rediscovered. Reviewed-by: Miao-chen Chou <mcchou@chromium.org>
Diffstat (limited to 'src/device.c')
-rw-r--r--src/device.c94
1 files changed, 91 insertions, 3 deletions
diff --git a/src/device.c b/src/device.c
index a83cb61f8..44450b113 100644
--- a/src/device.c
+++ b/src/device.c
@@ -567,6 +567,59 @@ void device_store_cached_name(struct btd_device *dev, const char *name)
g_key_file_free(key_file);
}
+static void device_store_cached_name_resolve(struct btd_device *dev)
+{
+ char filename[PATH_MAX];
+ char d_addr[18];
+ GKeyFile *key_file;
+ GError *gerr = NULL;
+ char *data;
+ char *data_old;
+ gsize length = 0;
+ gsize length_old = 0;
+ uint64_t failed_time;
+
+ if (device_address_is_private(dev)) {
+ DBG("Can't store name resolve for private addressed device %s",
+ dev->path);
+ return;
+ }
+
+ ba2str(&dev->bdaddr, d_addr);
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s",
+ btd_adapter_get_storage_dir(dev->adapter), d_addr);
+ create_file(filename, 0600);
+
+ key_file = g_key_file_new();
+ if (!g_key_file_load_from_file(key_file, filename, 0, &gerr)) {
+ error("Unable to load key file from %s: (%s)", filename,
+ gerr->message);
+ g_error_free(gerr);
+ }
+
+ failed_time = (uint64_t) dev->name_resolve_failed_time;
+
+ data_old = g_key_file_to_data(key_file, &length_old, NULL);
+
+ g_key_file_set_uint64(key_file, "NameResolving", "FailedTime",
+ failed_time);
+
+ data = g_key_file_to_data(key_file, &length, NULL);
+
+ if ((length != length_old) || (memcmp(data, data_old, length))) {
+ if (!g_file_set_contents(filename, data, length, &gerr)) {
+ error("Unable set contents for %s: (%s)", filename,
+ gerr->message);
+ g_error_free(gerr);
+ }
+ }
+
+ g_free(data);
+ g_free(data_old);
+
+ g_key_file_free(key_file);
+}
+
static void browse_request_free(struct browse_req *req)
{
struct btd_device *device = req->device;
@@ -3304,6 +3357,32 @@ failed:
return str;
}
+static void load_cached_name_resolve(struct btd_device *device,
+ const char *local, const char *peer)
+{
+ char filename[PATH_MAX];
+ GKeyFile *key_file;
+ uint64_t failed_time;
+
+ if (device_address_is_private(device))
+ return;
+
+ snprintf(filename, PATH_MAX, STORAGEDIR "/%s/cache/%s", local, peer);
+
+ key_file = g_key_file_new();
+
+ if (!g_key_file_load_from_file(key_file, filename, 0, NULL))
+ goto failed;
+
+ failed_time = g_key_file_get_uint64(key_file, "NameResolving",
+ "FailedTime", NULL);
+
+ device->name_resolve_failed_time = failed_time;
+
+failed:
+ g_key_file_free(key_file);
+}
+
static struct csrk_info *load_csrk(GKeyFile *key_file, const char *group)
{
struct csrk_info *csrk;
@@ -4311,6 +4390,7 @@ struct btd_device *device_create(struct btd_adapter *adapter,
struct btd_device *device;
char dst[18];
char *str;
+ const char *storage_dir;
ba2str(bdaddr, dst);
DBG("dst %s", dst);
@@ -4326,13 +4406,15 @@ struct btd_device *device_create(struct btd_adapter *adapter,
else
device->le = true;
- str = load_cached_name(device, btd_adapter_get_storage_dir(adapter),
- dst);
+ storage_dir = btd_adapter_get_storage_dir(adapter);
+ str = load_cached_name(device, storage_dir, dst);
if (str) {
strcpy(device->name, str);
g_free(str);
}
+ load_cached_name_resolve(device, storage_dir, dst);
+
return device;
}
@@ -4401,7 +4483,12 @@ bool device_is_name_resolve_allowed(struct btd_device *device)
return false;
clock_gettime(CLOCK_MONOTONIC, &now);
- return now.tv_sec >= device->name_resolve_failed_time +
+
+ /* If now < failed_time, it means the clock has somehow turned back,
+ * possibly because of system restart. Allow name request in this case.
+ */
+ return now.tv_sec < device->name_resolve_failed_time ||
+ now.tv_sec >= device->name_resolve_failed_time +
NAME_RESOLVE_RETRY_DELAY;
}
@@ -4414,6 +4501,7 @@ void device_name_resolve_fail(struct btd_device *device)
clock_gettime(CLOCK_MONOTONIC, &now);
device->name_resolve_failed_time = now.tv_sec;
+ device_store_cached_name_resolve(device);
}
void device_set_class(struct btd_device *device, uint32_t class)