summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristophe Guiraud <christophe.guiraud@intel.com>2013-08-14 11:48:56 +0200
committerrmerlino <regis.merlino@intel.com>2013-12-12 14:53:42 +0100
commit344aafd8c04ddf9d0e8af7b0bca1307fec53b6a7 (patch)
tree181614b71ff0efc9699f4aca0f576721bdae4aaa
parent03b444374dfa6bcd0ad90bb4d8814aaf57e6d27f (diff)
downloaddleyna-server-344aafd8c04ddf9d0e8af7b0bca1307fec53b6a7.tar.gz
[Device] Sleeping devices cache cleanup
When a sleeping device is removed from the network we persist it in our memory cache device->sleeping_context to keep possible the call of its wake method. This patch delete a sleeping device persisted in memory cache if after we call its wake method (successfully or not) we have not received any alive sign from the device for a timeout based on the device LPE estimated wake-on delay if it can be retrieved or a default one (30 seconds) if none is provided. Signed-off-by: Christophe Guiraud <christophe.guiraud@intel.com>
-rw-r--r--libdleyna/server/device.c61
-rw-r--r--libdleyna/server/device.h2
-rw-r--r--libdleyna/server/server.c6
-rw-r--r--libdleyna/server/server.h2
-rw-r--r--libdleyna/server/upnp.c19
-rw-r--r--libdleyna/server/upnp.h2
6 files changed, 90 insertions, 2 deletions
diff --git a/libdleyna/server/device.c b/libdleyna/server/device.c
index b7407a6..2bb9901 100644
--- a/libdleyna/server/device.c
+++ b/libdleyna/server/device.c
@@ -54,6 +54,7 @@
#define DLS_UPLOAD_STATUS_COMPLETED "COMPLETED"
#define DLS_DEFAULT_WAKE_PORT 9
+#define DLS_DEFAULT_WAKE_ON_DELAY 30
typedef gboolean(*dls_device_count_cb_t)(dls_async_task_t *cb_data,
gint count);
@@ -104,6 +105,7 @@ struct dls_tcp_wake_t_ {
guint8 *buffer;
gssize to_send;
gssize sent;
+ guint max_wake_on_delay;
dls_async_task_t *task;
};
@@ -349,6 +351,10 @@ void dls_device_delete(void *device)
g_ptr_array_unref(dev->contexts);
dls_device_delete_context(dev->sleeping_context);
+
+ if (dev->wake_on_timeout_id)
+ (void) g_source_remove(dev->wake_on_timeout_id);
+
g_free(dev->path);
g_variant_unref(dev->search_caps);
g_variant_unref(dev->sort_caps);
@@ -577,6 +583,7 @@ static dls_network_if_info_t *prv_get_network_if_info(xmlNode *device_if_node,
dls_network_if_info_t *info = NULL;
GList *ipv4_addresses;
GList *ipv6_addresses;
+ gchar *wake_on_delay = NULL;
info = g_new0(dls_network_if_info_t, 1);
@@ -625,6 +632,20 @@ static dls_network_if_info_t *prv_get_network_if_info(xmlNode *device_if_node,
"WakeSupportedTransport",
NULL);
+ wake_on_delay = xml_util_get_child_string_content_by_name(
+ device_if_node,
+ "NetworkInterface",
+ "MaxWakeOnDelay",
+ NULL);
+
+ if (wake_on_delay == NULL) {
+ info->max_wake_on_delay = DLS_DEFAULT_WAKE_ON_DELAY;
+ } else {
+ info->max_wake_on_delay = atoi(wake_on_delay);
+
+ g_free(wake_on_delay);
+ }
+
if ((info->device_uuid == NULL || strlen(info->device_uuid) > 70) ||
(info->mac_address == NULL || strlen(info->mac_address) != 17) ||
(info->network_if_mode == NULL) || (info->ip_addresses == NULL) ||
@@ -5720,6 +5741,30 @@ static void prv_free_tcp_data(dls_tcp_wake_t *tcp_data)
}
}
+static gboolean prv_wake_on_timeout_elapsed(gpointer user_data)
+{
+ dls_device_t *device = user_data;
+
+ DLEYNA_LOG_DEBUG("WAKE-ON time-out ellapsed.");
+
+ dls_server_delete_sleeping_device(device);
+
+ return FALSE;
+}
+
+static void prv_start_wake_on_watcher(dls_device_t *device, guint timeout)
+{
+ if (device->wake_on_timeout_id)
+ (void) g_source_remove(device->wake_on_timeout_id);
+
+ DLEYNA_LOG_DEBUG("Starting WAKE-ON watcher...");
+
+ device->wake_on_timeout_id = g_timeout_add_seconds(
+ timeout,
+ prv_wake_on_timeout_elapsed,
+ device);
+}
+
static void tcp_wake_cb(GObject *source, GAsyncResult *result,
gpointer user_data)
{
@@ -5794,9 +5839,14 @@ on_write:
on_complete:
prv_free_tcp_data(tcp_data);
- if (!g_cancellable_is_cancelled(cb_data->cancellable))
+ if (!g_cancellable_is_cancelled(cb_data->cancellable)) {
(void) g_idle_add(dls_async_task_complete, cb_data);
+ if (cb_data->task.target.device->sleeping_context != NULL)
+ prv_start_wake_on_watcher(cb_data->task.target.device,
+ tcp_data->max_wake_on_delay);
+ }
+
g_cancellable_disconnect(cb_data->cancellable, cb_data->cancel_id);
on_exit:
@@ -5865,6 +5915,7 @@ on_exit:
static void prv_device_wake_tcp(guint8 *packet, gsize packet_len,
const gchar *host,
+ guint max_wake_on_delay,
dls_async_task_t *cb_data)
{
GSocketClient *socket_client;
@@ -5876,6 +5927,7 @@ static void prv_device_wake_tcp(guint8 *packet, gsize packet_len,
tcp_data->task = cb_data;
tcp_data->buffer = packet;
tcp_data->to_send = packet_len;
+ tcp_data->max_wake_on_delay = max_wake_on_delay;
cb_data->cancel_id =
g_cancellable_connect(cb_data->cancellable,
@@ -5998,6 +6050,7 @@ void dls_device_wake(dls_client_t *client, dls_task_t *task)
DLEYNA_LOG_DEBUG("NetworkInterfaceMode = %s", info->network_if_mode);
DLEYNA_LOG_DEBUG("WakeOnPattern = %s", info->wake_on_pattern);
DLEYNA_LOG_DEBUG("WakeSupportedTransport = %s", info->wake_transport);
+ DLEYNA_LOG_DEBUG("WakeOnDelay = %u", info->max_wake_on_delay);
wake_on_ip_address = (gchar *)g_list_nth_data(info->ip_addresses,
info->ip_address_position);
@@ -6039,9 +6092,13 @@ void dls_device_wake(dls_client_t *client, dls_task_t *task)
cb_data->error = prv_device_wake_udp(packet, packet_len,
host_inet_address,
socket_family, broadcast);
+
+ if (device->sleeping_context != NULL)
+ prv_start_wake_on_watcher(device,
+ info->max_wake_on_delay);
} else {
prv_device_wake_tcp(packet, packet_len, wake_on_ip_address,
- cb_data);
+ info->max_wake_on_delay, cb_data);
goto on_exit;
}
diff --git a/libdleyna/server/device.h b/libdleyna/server/device.h
index 8b4888a..ef728ed 100644
--- a/libdleyna/server/device.h
+++ b/libdleyna/server/device.h
@@ -40,6 +40,7 @@ struct dls_network_if_info_t_ {
gchar *network_if_mode;
gchar *wake_on_pattern;
gchar *wake_transport;
+ guint max_wake_on_delay;
GList *ip_addresses;
guint ip_address_position;
};
@@ -73,6 +74,7 @@ struct dls_device_t_ {
gchar *path;
GPtrArray *contexts;
dls_device_context_t *sleeping_context;
+ guint wake_on_timeout_id;
guint timeout_id;
GHashTable *uploads;
GHashTable *upload_jobs;
diff --git a/libdleyna/server/server.c b/libdleyna/server/server.c
index 02909c5..b564348 100644
--- a/libdleyna/server/server.c
+++ b/libdleyna/server/server.c
@@ -979,6 +979,12 @@ gboolean dls_server_is_device_sleeping(dls_device_t *dev)
return dev->sleeping;
}
+void dls_server_delete_sleeping_device(dls_device_t *dev)
+{
+ if (dev->sleeping_context != NULL)
+ dls_upnp_delete_sleeping_device(g_context.upnp, dev);
+}
+
static const gchar *prv_get_device_id(const gchar *object, GError **error)
{
dls_device_t *device;
diff --git a/libdleyna/server/server.h b/libdleyna/server/server.h
index 36261de..932b2ba 100644
--- a/libdleyna/server/server.h
+++ b/libdleyna/server/server.h
@@ -42,6 +42,8 @@ dls_upnp_t *dls_server_get_upnp(void);
gboolean dls_server_is_device_sleeping(dls_device_t *dev);
+void dls_server_delete_sleeping_device(dls_device_t *dev);
+
dleyna_task_processor_t *dls_server_get_task_processor(void);
const dleyna_connector_t *dls_server_get_connector(void);
diff --git a/libdleyna/server/upnp.c b/libdleyna/server/upnp.c
index 3074645..5f87458 100644
--- a/libdleyna/server/upnp.c
+++ b/libdleyna/server/upnp.c
@@ -254,6 +254,13 @@ static void prv_device_available_cb(GUPnPControlPoint *cp,
g_hash_table_insert(upnp->device_udn_map, g_strdup(udn),
device);
+ if (device->wake_on_timeout_id) {
+ DLEYNA_LOG_DEBUG("Stop WAKE-ON watcher...");
+
+ (void) g_source_remove(
+ device->wake_on_timeout_id);
+ device->wake_on_timeout_id = 0;
+ }
dls_device_delete_context(device->sleeping_context);
device->sleeping_context = NULL;
device->sleeping = FALSE;
@@ -594,6 +601,18 @@ GHashTable *dls_upnp_get_sleeping_device_udn_map(dls_upnp_t *upnp)
return upnp->sleeping_device_udn_map;
}
+void dls_upnp_delete_sleeping_device(dls_upnp_t *upnp, dls_device_t *device)
+{
+ const char *udn;
+ dls_device_context_t *ctx = device->sleeping_context;
+
+ udn = gupnp_device_info_get_udn((GUPnPDeviceInfo *)ctx->device_proxy);
+
+ upnp->lost_server(device->path, upnp->user_data);
+
+ g_hash_table_remove(upnp->sleeping_device_udn_map, udn);
+}
+
void dls_upnp_get_children(dls_upnp_t *upnp, dls_client_t *client,
dls_task_t *task,
dls_upnp_task_complete_t cb)
diff --git a/libdleyna/server/upnp.h b/libdleyna/server/upnp.h
index fc1b3a3..854083a 100644
--- a/libdleyna/server/upnp.h
+++ b/libdleyna/server/upnp.h
@@ -45,6 +45,8 @@ GHashTable *dls_upnp_get_device_udn_map(dls_upnp_t *upnp);
GHashTable *dls_upnp_get_sleeping_device_udn_map(dls_upnp_t *upnp);
+void dls_upnp_delete_sleeping_device(dls_upnp_t *upnp, dls_device_t *device);
+
void dls_upnp_get_children(dls_upnp_t *upnp, dls_client_t *client,
dls_task_t *task,
dls_upnp_task_complete_t cb);