summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRegis Merlino <regis.merlino@intel.com>2013-04-02 16:12:35 +0200
committerMark Ryan <mark.d.ryan@intel.com>2013-04-09 15:13:03 +0200
commit2022ea78c884e6b6488afcd3d409e81a531d06f1 (patch)
treee7f62e122c1bdada3ee1a477a21c16babca0b202
parentefe4c711bc1e470d77f2b5cc4cc6c75f301b1032 (diff)
downloaddleyna-server-2022ea78c884e6b6488afcd3d409e81a531d06f1.tar.gz
[Device] Fix device construction
Signed-off-by: Regis Merlino <regis.merlino@intel.com>
-rw-r--r--libdleyna/server/device.c101
-rw-r--r--libdleyna/server/device.h9
-rw-r--r--libdleyna/server/upnp.c106
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");