@@ -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)