[libdmapsharing] Deal with name collisions when sharing given type of service
- From: W. Michael Petullo <wmpetullo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdmapsharing] Deal with name collisions when sharing given type of service
- Date: Sun, 11 Mar 2018 17:33:13 +0000 (UTC)
commit 31fee798eb9ba8e0dde6d7fa5e180c581b915d1e
Author: W. Michael Petullo <mike flyn org>
Date: Sun Mar 11 13:32:52 2018 -0400
Deal with name collisions when sharing given type of service
Signed-off-by: W. Michael Petullo <mike flyn org>
README-Porting | 23 +++--
libdmapsharing/dmap-av-share.c | 141 +++++++++++++++++++++------
libdmapsharing/dmap-control-share.c | 34 +++----
libdmapsharing/dmap-image-share.c | 29 +++---
libdmapsharing/dmap-mdns-publisher-avahi.c | 29 +++++-
libdmapsharing/dmap-share.c | 29 ++----
libdmapsharing/dmap-share.h | 21 ++++
7 files changed, 205 insertions(+), 101 deletions(-)
---
diff --git a/README-Porting b/README-Porting
index e79b823..62a1322 100644
--- a/README-Porting
+++ b/README-Porting
@@ -3,7 +3,10 @@ versions. The primary reason for these changes is to better support
GObject introspection and thus languages such as Python. The following
are the key differences between the new and old APIs:
-(1) All symbols now exist in the DMAP/Dmap/dmap namespace.
+(1) A program which shares a DMAP service must explicitly call
+dmap_share_serve() and dmap_share_publish().
+
+(2) All symbols now exist in the DMAP/Dmap/dmap namespace.
(a) For example, DMAPDb is now DmapDb.
@@ -17,10 +20,10 @@ are the key differences between the new and old APIs:
(e) DACPPlayer is now DmapControlPlayer.
-(2) The interface names exported by libdmapsharing now end in "Interface"
+(3) The interface names exported by libdmapsharing now end in "Interface"
instead of "Iface".
-(3) The new API renames the following symbols as indicated:
+(4) The new API renames the following symbols as indicated:
DMAP_TYPE_DMAP_MDNS_BROWSER_TRANSPORT_PROTOCOL became
DMAP_TYPE_DMAP_MDNS_SERVICE_TRANSPORT_PROTOCOL.
@@ -47,17 +50,17 @@ instead of "Iface".
DACPPlayState became DmapControlPlayState.
-(4) The new API replaces the use of GHFunc with DMAPIdRecordFunc and
+(5) The new API replaces the use of GHFunc with DMAPIdRecordFunc and
DMAPContainerIdFunc.
-(5) Setting an object property using g_object_set causes the object to
+(6) Setting an object property using g_object_set causes the object to
duplicate the passed value. Thus the caller maintains control of the
original value.
-(6) Getting an object property using g_object_set returns a duplicate
+(7) Getting an object property using g_object_set returns a duplicate
of the value. Thus the caller should free or unref the obtained value.
-(7) The "hash" property in the DAAPRecord interface and the "hash"
+(8) The "hash" property in the DAAPRecord interface and the "hash"
and "thumbnail" properties in the DPAPRecord interface are now boxed
types. The true type of each of these properties is a GArray. Thus
implementations of these interfaces should now:
@@ -68,11 +71,11 @@ implementations of these interfaces should now:
(c) use GArray instead of GByteArray.
-(8) The "base-uri" property in the DMAPConnection class is now a boxed
+(9) The "base-uri" property in the DMAPConnection class is now a boxed
type. The real type is SoupURI.
-(9) The "db" and "container-db" properties in DMAPShare are now handled
+(10) The "db" and "container-db" properties in DMAPShare are now handled
as object types instead of pointer types.
-(10) The properties contained in a DMAPMdnsService must now be accessed
+(11) The properties contained in a DMAPMdnsService must now be accessed
using g_object_get.
diff --git a/libdmapsharing/dmap-av-share.c b/libdmapsharing/dmap-av-share.c
index 3ecd84c..69cfd91 100644
--- a/libdmapsharing/dmap-av-share.c
+++ b/libdmapsharing/dmap-av-share.c
@@ -97,37 +97,21 @@ dmap_av_share_init (DmapAvShare * share)
DmapAvShare *
dmap_av_share_new (const char *name,
- const char *password,
- DmapDb * db,
- DmapContainerDb * container_db, gchar * transcode_mimetype)
+ const char *password,
+ DmapDb * db,
+ DmapContainerDb * container_db,
+ gchar * transcode_mimetype)
{
- DmapAvShare *share;
-
g_object_ref (db);
g_object_ref (container_db);
- share = DMAP_AV_SHARE (g_object_new (DMAP_TYPE_AV_SHARE,
- "name", name,
- "password", password,
- "db", db,
- "container-db", container_db,
- "transcode-mimetype",
- transcode_mimetype, NULL));
-
- if (!dmap_share_server_start (DMAP_SHARE (share))) {
- g_object_unref(share);
- share = NULL;
- goto done;
- }
-
- if (!dmap_share_publish_start (DMAP_SHARE (share))) {
- g_object_unref(share);
- share = NULL;
- goto done;
- }
-
-done:
- return share;
+ return DMAP_AV_SHARE (g_object_new (DMAP_TYPE_AV_SHARE,
+ "name", name,
+ "password", password,
+ "db", db,
+ "container-db", container_db,
+ "transcode-mimetype",
+ transcode_mimetype, NULL));
}
void
@@ -1090,11 +1074,11 @@ START_TEST(dmap_av_share_new_test)
dmap_db_add(db, record);
- share = DMAP_SHARE(dmap_av_share_new("name",
- "password",
- db,
- container_db,
- "audio/mp3"));
+ share = DMAP_SHARE(dmap_av_share_new("name",
+ "password",
+ db,
+ container_db,
+ "audio/mp3"));
g_object_get(share, "name", &str, NULL);
ck_assert_str_eq("name", str);
@@ -1115,6 +1099,99 @@ START_TEST(dmap_av_share_new_test)
}
END_TEST
+START_TEST(dmap_av_share_serve_publish_test)
+{
+ DmapDb *db;
+ gboolean ok;
+ DmapContainerRecord *container_record;
+ DmapContainerDb *container_db;
+ DmapRecord *record;
+ DmapShare *share;
+
+ db = DMAP_DB(test_dmap_db_new());
+ container_record = DMAP_CONTAINER_RECORD (test_dmap_container_record_new ());
+ container_db = DMAP_CONTAINER_DB(test_dmap_container_db_new(container_record));
+
+
+ record = DMAP_RECORD(test_dmap_av_record_new());
+ g_object_set(record, "songgenre", "genre1", NULL);
+ g_object_set(record, "songartist", "artist1", NULL);
+ g_object_set(record, "songalbum", "album1", NULL);
+
+ dmap_db_add(db, record);
+
+ share = DMAP_SHARE(dmap_av_share_new("name",
+ "password",
+ db,
+ container_db,
+ "audio/mp3"));
+
+ ok = dmap_share_serve(share);
+ ck_assert(ok);
+
+ ok = dmap_share_publish(share);
+ ck_assert(ok);
+
+ g_object_unref(db);
+ g_object_unref(container_record);
+ g_object_unref(container_db);
+ g_object_unref(share);
+}
+END_TEST
+
+START_TEST(dmap_av_share_serve_publish_collision_test)
+{
+ DmapDb *db;
+ gboolean ok;
+ DmapContainerRecord *container_record;
+ DmapContainerDb *container_db;
+ DmapRecord *record;
+ DmapShare *share1, *share2;
+
+ db = DMAP_DB(test_dmap_db_new());
+ container_record = DMAP_CONTAINER_RECORD (test_dmap_container_record_new ());
+ container_db = DMAP_CONTAINER_DB(test_dmap_container_db_new(container_record));
+
+
+ record = DMAP_RECORD(test_dmap_av_record_new());
+ g_object_set(record, "songgenre", "genre1", NULL);
+ g_object_set(record, "songartist", "artist1", NULL);
+ g_object_set(record, "songalbum", "album1", NULL);
+
+ dmap_db_add(db, record);
+
+ share1 = DMAP_SHARE(dmap_av_share_new("name",
+ "password",
+ db,
+ container_db,
+ "audio/mp3"));
+
+ ok = dmap_share_serve(share1);
+ ck_assert(ok);
+
+ ok = dmap_share_publish(share1);
+ ck_assert(ok);
+
+ share2 = DMAP_SHARE(dmap_av_share_new("name",
+ "password",
+ db,
+ container_db,
+ "audio/mp3"));
+
+ ok = dmap_share_serve(share2);
+ ck_assert(ok);
+
+ ok = dmap_share_publish(share2);
+ ck_assert(ok);
+
+ g_object_unref(db);
+ g_object_unref(container_record);
+ g_object_unref(container_db);
+ g_object_unref(share1);
+ g_object_unref(share2);
+}
+END_TEST
+
static void
_tabulator_test(char *property,
void (*tabulator) (gpointer id, DmapRecord * record, GHashTable * ht))
diff --git a/libdmapsharing/dmap-control-share.c b/libdmapsharing/dmap-control-share.c
index 82ac684..180cddb 100644
--- a/libdmapsharing/dmap-control-share.c
+++ b/libdmapsharing/dmap-control-share.c
@@ -436,26 +436,22 @@ _mdns_remote_removed (DmapMdnsBrowser * browser,
}
DmapControlShare *
-dmap_control_share_new (const gchar * library_name,
- DmapControlPlayer * player,
- DmapDb * db, DmapContainerDb * container_db)
+dmap_control_share_new (const gchar *library_name,
+ DmapControlPlayer *player,
+ DmapDb *db,
+ DmapContainerDb *container_db)
{
- DmapControlShare *share;
-
- share = DMAP_CONTROL_SHARE (g_object_new (DMAP_TYPE_CONTROL_SHARE,
- "name", _get_dbid (),
- "library-name", library_name,
- "password", NULL,
- "db", db,
- "container-db", container_db,
- "player", G_OBJECT (player),
- "transcode-mimetype", NULL, NULL));
-
- g_debug ("Starting DACP server");
- dmap_share_server_start (DMAP_SHARE (share));
- dmap_share_publish_start (DMAP_SHARE (share));
-
- return share;
+ g_object_ref (db);
+ g_object_ref (container_db);
+
+ return DMAP_CONTROL_SHARE (g_object_new (DMAP_TYPE_CONTROL_SHARE,
+ "name", _get_dbid (),
+ "library-name", library_name,
+ "password", NULL,
+ "db", db,
+ "container-db", container_db,
+ "player", G_OBJECT (player),
+ "transcode-mimetype", NULL, NULL));
}
void
diff --git a/libdmapsharing/dmap-image-share.c b/libdmapsharing/dmap-image-share.c
index 1ca2355..7cad7ac 100644
--- a/libdmapsharing/dmap-image-share.c
+++ b/libdmapsharing/dmap-image-share.c
@@ -163,23 +163,20 @@ dmap_image_share_dispose (GObject * object)
*/
DmapImageShare *
dmap_image_share_new (const char *name,
- const char *password,
- gpointer db,
- gpointer container_db, gchar * transcode_mimetype)
+ const char *password,
+ gpointer db,
+ gpointer container_db,
+ gchar * transcode_mimetype)
{
- DmapImageShare *share;
-
- share = DMAP_IMAGE_SHARE (g_object_new (DMAP_TYPE_IMAGE_SHARE,
- "name", name,
- "password", password,
- "db", db,
- "container-db", container_db,
- NULL));
-
- dmap_share_server_start (DMAP_SHARE (share));
- dmap_share_publish_start (DMAP_SHARE (share));
-
- return share;
+ g_object_ref (db);
+ g_object_ref (container_db);
+
+ return DMAP_IMAGE_SHARE (g_object_new (DMAP_TYPE_IMAGE_SHARE,
+ "name", name,
+ "password", password,
+ "db", db,
+ "container-db", container_db,
+ NULL));
}
void
diff --git a/libdmapsharing/dmap-mdns-publisher-avahi.c b/libdmapsharing/dmap-mdns-publisher-avahi.c
index 1ca1657..2dc9e33 100644
--- a/libdmapsharing/dmap-mdns-publisher-avahi.c
+++ b/libdmapsharing/dmap-mdns-publisher-avahi.c
@@ -140,7 +140,8 @@ create_service (struct DmapMdnsPublisherService *service,
ret = avahi_entry_group_add_service_strlst (publisher->
priv->entry_group,
AVAHI_IF_UNSPEC,
- AVAHI_PROTO_UNSPEC, 0,
+ AVAHI_PROTO_UNSPEC,
+ 0,
service->name,
service->type_of_service,
NULL, NULL, service->port,
@@ -164,7 +165,10 @@ create_service (struct DmapMdnsPublisherService *service,
static gboolean
create_services (DmapMdnsPublisher * publisher, GError ** error)
{
- GSList *ptr;
+ static int suffix = 0;
+ gchar *name;
+ GSList *ptr1, *ptr2;
+ struct DmapMdnsPublisherService *service1, *service2;
int ret;
if (publisher->priv->entry_group == NULL) {
@@ -190,8 +194,25 @@ create_services (DmapMdnsPublisher * publisher, GError ** error)
avahi_entry_group_reset (publisher->priv->entry_group);
}
- for (ptr = publisher->priv->service; ptr; ptr = g_slist_next (ptr)) {
- if (!create_service (ptr->data, publisher, error)) {
+ for (ptr1 = publisher->priv->service; ptr1; ptr1 = g_slist_next (ptr1)) {
+ service1 = ptr1->data;
+ name = service1->name;
+ for (ptr2 = publisher->priv->service; ptr2; ptr2 = g_slist_next (ptr2)) {
+ if (ptr1 == ptr2) {
+ continue;
+ }
+ service2 = ptr2->data;
+ if (!strcmp(service1->name, service2->name)
+ && !strcmp(service1->type_of_service, service2->type_of_service)) {
+ name = g_strdup_printf("%s-%d", service1->name, suffix++);
+ }
+ }
+ if (strcmp(name, service1->name)) {
+ g_free(service1->name);
+ service1->name = name;
+ g_signal_emit (publisher, signals[NAME_COLLISION], 0, name);
+ }
+ if (!create_service (service1, publisher, error)) {
return FALSE;
}
}
diff --git a/libdmapsharing/dmap-share.c b/libdmapsharing/dmap-share.c
index b8db9e2..479297e 100644
--- a/libdmapsharing/dmap-share.c
+++ b/libdmapsharing/dmap-share.c
@@ -220,7 +220,7 @@ _ctrl_int_adapter (SoupServer * server,
}
gboolean
-dmap_share_server_start (DmapShare *share)
+dmap_share_serve (DmapShare *share)
{
guint desired_port = DMAP_SHARE_GET_CLASS (share)->get_desired_port (share);
gboolean password_required, ok = FALSE;
@@ -342,7 +342,7 @@ _server_stop (DmapShare * share)
}
gboolean
-dmap_share_publish_start (DmapShare * share)
+dmap_share_publish (DmapShare * share)
{
GError *error;
gboolean ok;
@@ -411,10 +411,10 @@ _restart (DmapShare * share)
gboolean res;
_server_stop (share);
- res = dmap_share_server_start (share);
+ res = dmap_share_serve (share);
if (res) {
/* To update information just publish again */
- dmap_share_publish_start (share);
+ dmap_share_publish (share);
} else {
_publish_stop (share);
}
@@ -456,12 +456,8 @@ _set_name (DmapShare * share, const char *name)
static void
_set_password (DmapShare * share, const char *password)
{
- if (NULL != share) {
- goto done;
- }
-
if (share->priv->password && password &&
- strcmp (password, share->priv->password) == 0) {
+ 0 == strcmp (password, share->priv->password)) {
goto done;
}
@@ -978,20 +974,13 @@ void
dmap_share_name_collision (DmapShare * share,
DmapMdnsPublisher * publisher, const char *name)
{
- char *new_name = g_strdup("FIXME");
-
- if (share->priv->name == NULL || name == NULL) {
- goto done;
- }
+ g_assert(NULL != name);
+ g_assert(NULL != share->priv->name);
- if (strcmp (share->priv->name, name) == 0) {
- g_warning ("Duplicate share name on mDNS");
+ g_warning ("Duplicate share name on mDNS; renaming share to %s", name);
- _set_name (DMAP_SHARE (share), new_name);
- g_free (new_name);
- }
+ _set_name (DMAP_SHARE (share), name);
-done:
return;
}
diff --git a/libdmapsharing/dmap-share.h b/libdmapsharing/dmap-share.h
index c2dbda6..c2d489e 100644
--- a/libdmapsharing/dmap-share.h
+++ b/libdmapsharing/dmap-share.h
@@ -192,6 +192,27 @@ struct DmapMlclBits
GType dmap_share_get_type (void);
/**
+ * dmap_share_serve:
+ * @share: a #DmapShare instance.
+ *
+ * Begin serving the service defined by share. A program will normally also
+ * call dmap_share_publish.
+ *
+ * Returns: TRUE if serving succeeds, else FALSE.
+ */
+gboolean dmap_share_serve(DmapShare *share);
+
+/**
+ * dmap_share_publish:
+ * @share: a #DmapShare instance.
+ *
+ * Publish the availability of the given share using mDNS-SD.
+ *
+ * Returns: TRUE if publishing succeeds, else FALSE.
+ */
+gboolean dmap_share_publish(DmapShare *share);
+
+/**
* dmap_share_free_filter:
* @filter: (element-type GSList): The filter list to free.
*
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]