diff options
author | Regis Merlino <regis.merlino@intel.com> | 2013-04-02 16:12:35 +0200 |
---|---|---|
committer | Mark Ryan <mark.d.ryan@intel.com> | 2013-04-09 15:13:03 +0200 |
commit | 2022ea78c884e6b6488afcd3d409e81a531d06f1 (patch) | |
tree | e7f62e122c1bdada3ee1a477a21c16babca0b202 | |
parent | efe4c711bc1e470d77f2b5cc4cc6c75f301b1032 (diff) | |
download | dleyna-server-2022ea78c884e6b6488afcd3d409e81a531d06f1.tar.gz |
[Device] Fix device construction
Signed-off-by: Regis Merlino <regis.merlino@intel.com>
-rw-r--r-- | libdleyna/server/device.c | 101 | ||||
-rw-r--r-- | libdleyna/server/device.h | 9 | ||||
-rw-r--r-- | libdleyna/server/upnp.c | 106 |
3 files changed, 165 insertions, 51 deletions
diff --git a/libdleyna/server/device.c b/libdleyna/server/device.c index 1669345..34818a8 100644 --- a/libdleyna/server/device.c +++ b/libdleyna/server/device.c @@ -221,6 +221,8 @@ void dls_device_delete(void *device) dls_device_t *dev = device; if (dev) { + DLEYNA_LOG_DEBUG("Deleting device"); + dev->shutting_down = TRUE; g_hash_table_unref(dev->upload_jobs); g_hash_table_unref(dev->uploads); @@ -628,6 +630,8 @@ static void prv_get_feature_list_cb(GUPnPServiceProxy *proxy, GError *error = NULL; prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data; + priv_t->dev->construct_step++; + if (!gupnp_service_proxy_end_action(proxy, action, &error, "FeatureList", G_TYPE_STRING, &result, NULL)) { @@ -701,6 +705,8 @@ static void prv_get_sort_ext_capabilities_cb(GUPnPServiceProxy *proxy, GError *error = NULL; prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data; + priv_t->dev->construct_step++; + if (!gupnp_service_proxy_end_action(proxy, action, &error, "SortExtensionCaps", G_TYPE_STRING, &result, NULL)) { @@ -782,6 +788,8 @@ static void prv_get_sort_capabilities_cb(GUPnPServiceProxy *proxy, GError *error = NULL; prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data; + priv_t->dev->construct_step++; + if (!gupnp_service_proxy_end_action(proxy, action, &error, "SortCaps", G_TYPE_STRING, &result, NULL)) { DLEYNA_LOG_WARNING("GetSortCapabilities operation failed: %s", @@ -824,6 +832,8 @@ static void prv_get_search_capabilities_cb(GUPnPServiceProxy *proxy, GError *error = NULL; prv_new_device_ct_t *priv_t = (prv_new_device_ct_t *)user_data; + priv_t->dev->construct_step++; + if (!gupnp_service_proxy_end_action(proxy, action, &error, "SearchCaps", G_TYPE_STRING, &result, NULL)) { DLEYNA_LOG_WARNING("GetSearchCapabilities operation failed: %s", @@ -864,6 +874,8 @@ static GUPnPServiceProxyAction *prv_subscribe(dleyna_service_task_t *task, dls_device_t *device; device = (dls_device_t *)dleyna_service_task_get_user_data(task); + + device->construct_step++; dls_device_subscribe_to_contents_change(device); *failed = FALSE; @@ -916,6 +928,7 @@ static GUPnPServiceProxyAction *prv_declare(dleyna_service_task_t *task, priv_t = (prv_new_device_ct_t *)dleyna_service_task_get_user_data(task); device = priv_t->dev; + device->construct_step++; id = dls_server_get_connector()->publish_subtree(priv_t->connection, device->path, @@ -945,6 +958,61 @@ static GUPnPServiceProxyAction *prv_declare(dleyna_service_task_t *task, return NULL; } +void dls_device_construct( + dls_device_t *dev, + dls_device_context_t *context, + dleyna_connector_id_t connection, + const dleyna_connector_dispatch_cb_t *dispatch_table, + GHashTable *property_map, + const dleyna_task_queue_key_t *queue_id) +{ + prv_new_device_ct_t *priv_t; + GUPnPServiceProxy *s_proxy; + + DLEYNA_LOG_DEBUG("Current step: %d", dev->construct_step); + + priv_t = g_new0(prv_new_device_ct_t, 1); + + priv_t->dev = dev; + priv_t->connection = connection; + priv_t->vtable = dispatch_table; + priv_t->property_map = property_map; + + s_proxy = context->service_proxy; + + if (dev->construct_step < 1) + dleyna_service_task_add(queue_id, prv_get_search_capabilities, + s_proxy, + prv_get_search_capabilities_cb, NULL, + priv_t); + + if (dev->construct_step < 2) + dleyna_service_task_add(queue_id, prv_get_sort_capabilities, + s_proxy, + prv_get_sort_capabilities_cb, NULL, + priv_t); + + if (dev->construct_step < 3) + dleyna_service_task_add(queue_id, prv_get_sort_ext_capabilities, + s_proxy, + prv_get_sort_ext_capabilities_cb, NULL, + priv_t); + + if (dev->construct_step < 4) + dleyna_service_task_add(queue_id, prv_get_feature_list, s_proxy, + prv_get_feature_list_cb, NULL, priv_t); + + /* The following task should always be completed */ + dleyna_service_task_add(queue_id, prv_subscribe, s_proxy, + NULL, NULL, dev); + + if (dev->construct_step < 6) + dleyna_service_task_add(queue_id, prv_declare, s_proxy, + NULL, g_free, priv_t); + + dleyna_task_queue_start(queue_id); +} + dls_device_t *dls_device_new( dleyna_connector_id_t connection, GUPnPDeviceProxy *proxy, @@ -955,10 +1023,8 @@ dls_device_t *dls_device_new( const dleyna_task_queue_key_t *queue_id) { dls_device_t *dev; - prv_new_device_ct_t *priv_t; gchar *new_path; dls_device_context_t *context; - GUPnPServiceProxy *s_proxy; DLEYNA_LOG_DEBUG("New Device on %s", ip_address); @@ -966,42 +1032,15 @@ dls_device_t *dls_device_new( DLEYNA_LOG_DEBUG("Server Path %s", new_path); dev = g_new0(dls_device_t, 1); - priv_t = g_new0(prv_new_device_ct_t, 1); dev->connection = connection; dev->contexts = g_ptr_array_new_with_free_func(prv_context_delete); dev->path = new_path; - priv_t->dev = dev; - priv_t->connection = connection; - priv_t->vtable = dispatch_table; - priv_t->property_map = property_map; - context = dls_device_append_new_context(dev, ip_address, proxy); - s_proxy = context->service_proxy; - - dleyna_service_task_add(queue_id, prv_get_search_capabilities, - s_proxy, - prv_get_search_capabilities_cb, NULL, priv_t); - - dleyna_service_task_add(queue_id, prv_get_sort_capabilities, - s_proxy, - prv_get_sort_capabilities_cb, NULL, priv_t); - - dleyna_service_task_add(queue_id, prv_get_sort_ext_capabilities, - s_proxy, - prv_get_sort_ext_capabilities_cb, NULL, priv_t); - dleyna_service_task_add(queue_id, prv_get_feature_list, s_proxy, - prv_get_feature_list_cb, NULL, priv_t); - - dleyna_service_task_add(queue_id, prv_subscribe, s_proxy, - NULL, NULL, dev); - - dleyna_service_task_add(queue_id, prv_declare, s_proxy, - NULL, g_free, priv_t); - - dleyna_task_queue_start(queue_id); + dls_device_construct(dev, context, connection, dispatch_table, + property_map, queue_id); return dev; } diff --git a/libdleyna/server/device.h b/libdleyna/server/device.h index fa74ac8..9a47c6e 100644 --- a/libdleyna/server/device.h +++ b/libdleyna/server/device.h @@ -56,6 +56,7 @@ struct dls_device_t_ { GVariant *sort_ext_caps; GVariant *feature_list; gboolean shutting_down; + guint construct_step; }; dls_device_context_t *dls_device_append_new_context(dls_device_t *device, @@ -65,6 +66,14 @@ void dls_device_delete(void *device); void dls_device_unsubscribe(void *device); +void dls_device_construct( + dls_device_t *dev, + dls_device_context_t *context, + dleyna_connector_id_t connection, + const dleyna_connector_dispatch_cb_t *dispatch_table, + GHashTable *property_map, + const dleyna_task_queue_key_t *queue_id); + dls_device_t *dls_device_new( dleyna_connector_id_t connection, GUPnPDeviceProxy *proxy, diff --git a/libdleyna/server/upnp.c b/libdleyna/server/upnp.c index 90e54c3..073e9a2 100644 --- a/libdleyna/server/upnp.c +++ b/libdleyna/server/upnp.c @@ -57,6 +57,7 @@ typedef struct prv_device_new_ct_t_ prv_device_new_ct_t; struct prv_device_new_ct_t_ { dls_upnp_t *upnp; char *udn; + gchar *ip_address; dls_device_t *device; const dleyna_task_queue_key_t *queue_id; }; @@ -65,6 +66,7 @@ static void prv_device_new_free(prv_device_new_ct_t *priv_t) { if (priv_t) { g_free(priv_t->udn); + g_free(priv_t->ip_address); g_free(priv_t); } } @@ -89,14 +91,64 @@ static void prv_device_chain_end(gboolean cancelled, gpointer data) on_clear: g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn); - prv_device_new_free(priv_t); if (cancelled) dls_device_delete(device); + prv_device_new_free(priv_t); + DLEYNA_LOG_DEBUG_NL(); } +static void prv_device_context_switch_end(gboolean cancelled, gpointer data) +{ + prv_device_new_ct_t *priv_t = (prv_device_new_ct_t *)data; + + DLEYNA_LOG_DEBUG("Enter"); + + g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn); + prv_device_new_free(priv_t); + + DLEYNA_LOG_DEBUG("Exit"); +} + +static const dleyna_task_queue_key_t *prv_create_device_queue( + prv_device_new_ct_t **priv_t) +{ + const dleyna_task_queue_key_t *queue_id; + + *priv_t = g_new0(prv_device_new_ct_t, 1); + + queue_id = dleyna_task_processor_add_queue( + dls_server_get_task_processor(), + dleyna_service_task_create_source(), + DLS_SERVER_SINK, + DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE, + dleyna_service_task_process_cb, + dleyna_service_task_cancel_cb, + dleyna_service_task_delete_cb); + dleyna_task_queue_set_finally(queue_id, prv_device_chain_end); + dleyna_task_queue_set_user_data(queue_id, *priv_t); + + + return queue_id; +} + +static void prv_update_device_context(prv_device_new_ct_t *priv_t, + dls_upnp_t *upnp, const char *udn, + dls_device_t *device, + const gchar *ip_address, + const dleyna_task_queue_key_t *queue_id) +{ + priv_t->upnp = upnp; + priv_t->udn = g_strdup(udn); + priv_t->ip_address = g_strdup(ip_address); + priv_t->queue_id = queue_id; + priv_t->device = device; + + g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t); +} + static void prv_server_available_cb(GUPnPControlPoint *cp, GUPnPDeviceProxy *proxy, gpointer user_data) @@ -133,32 +185,17 @@ static void prv_server_available_cb(GUPnPControlPoint *cp, DLEYNA_LOG_DEBUG("Device not found. Adding"); DLEYNA_LOG_DEBUG_NL(); - priv_t = g_new0(prv_device_new_ct_t, 1); - - queue_id = dleyna_task_processor_add_queue( - dls_server_get_task_processor(), - dleyna_service_task_create_source(), - DLS_SERVER_SINK, - DLEYNA_TASK_QUEUE_FLAG_AUTO_REMOVE, - dleyna_service_task_process_cb, - dleyna_service_task_cancel_cb, - dleyna_service_task_delete_cb); - dleyna_task_queue_set_finally(queue_id, prv_device_chain_end); - dleyna_task_queue_set_user_data(queue_id, priv_t); + queue_id = prv_create_device_queue(&priv_t); device = dls_device_new(upnp->connection, proxy, ip_address, upnp->interface_info, upnp->property_map, upnp->counter, queue_id); - upnp->counter++; - - priv_t->upnp = upnp; - priv_t->udn = g_strdup(udn); - priv_t->queue_id = queue_id; - priv_t->device = device; + prv_update_device_context(priv_t, upnp, udn, device, ip_address, + queue_id); - g_hash_table_insert(upnp->server_uc_map, g_strdup(udn), priv_t); + upnp->counter++; } else { DLEYNA_LOG_DEBUG("Device Found"); @@ -203,8 +240,10 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp, unsigned int i; dls_device_context_t *context; gboolean subscribed; + gboolean construction_ctx = FALSE; gboolean under_construction = FALSE; prv_device_new_ct_t *priv_t; + const dleyna_task_queue_key_t *queue_id; DLEYNA_LOG_DEBUG("Enter"); @@ -244,6 +283,9 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp, goto on_error; subscribed = context->subscribed; + if (under_construction) + construction_ctx = !strcmp(context->ip_address, + priv_t->ip_address); (void) g_ptr_array_remove_index(device->contexts, i); @@ -258,6 +300,30 @@ static void prv_server_unavailable_cb(GUPnPControlPoint *cp, dleyna_task_processor_cancel_queue(priv_t->queue_id); } + } else if (under_construction && construction_ctx) { + DLEYNA_LOG_WARNING( + "Device under construction. Switching context"); + + /* Cancel previous contruction task chain */ + g_hash_table_remove(priv_t->upnp->server_uc_map, priv_t->udn); + dleyna_task_queue_set_finally(priv_t->queue_id, + prv_device_context_switch_end); + dleyna_task_processor_cancel_queue(priv_t->queue_id); + + /* Create a new construction task chain */ + context = dls_device_get_context(device, NULL); + queue_id = prv_create_device_queue(&priv_t); + prv_update_device_context(priv_t, upnp, udn, device, + context->ip_address, queue_id); + + /* Start tasks from current construction step */ + dls_device_construct(device, + context, + upnp->connection, + upnp->interface_info, + upnp->property_map, + queue_id); + } else if (subscribed && !device->timeout_id) { DLEYNA_LOG_DEBUG("Subscribe on new context"); |