[libdmapsharing] Deal with name collisions when sharing given type of service



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]