diff options
author | Christophe Guiraud <christophe.guiraud@intel.com> | 2013-08-14 11:48:56 +0200 |
---|---|---|
committer | rmerlino <regis.merlino@intel.com> | 2013-12-12 14:53:42 +0100 |
commit | 344aafd8c04ddf9d0e8af7b0bca1307fec53b6a7 (patch) | |
tree | 181614b71ff0efc9699f4aca0f576721bdae4aaa | |
parent | 03b444374dfa6bcd0ad90bb4d8814aaf57e6d27f (diff) | |
download | dleyna-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.c | 61 | ||||
-rw-r--r-- | libdleyna/server/device.h | 2 | ||||
-rw-r--r-- | libdleyna/server/server.c | 6 | ||||
-rw-r--r-- | libdleyna/server/server.h | 2 | ||||
-rw-r--r-- | libdleyna/server/upnp.c | 19 | ||||
-rw-r--r-- | libdleyna/server/upnp.h | 2 |
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); |