[libdmapsharing] DMAPShare objects now have two SoupServers: one with an IPv4 socket and one with an IPv6 socket Sign



commit 03eef01e25b44c49b5431cedd5899026b071d121
Author: W. Michael Petullo <mike flyn org>
Date:   Thu Jan 6 00:13:34 2011 -0600

    DMAPShare objects now have two SoupServers: one with an IPv4 socket and one with an IPv6 socket
    Signed-off-by: W. Michael Petullo <mike flyn org>

 libdmapsharing/dacp-share.c |   28 ++++++--
 libdmapsharing/dmap-share.c |  173 ++++++++++++++++++++++++++++---------------
 2 files changed, 135 insertions(+), 66 deletions(-)
---
diff --git a/libdmapsharing/dacp-share.c b/libdmapsharing/dacp-share.c
index e3fda50..fcb8fdc 100644
--- a/libdmapsharing/dacp-share.c
+++ b/libdmapsharing/dacp-share.c
@@ -538,15 +538,31 @@ static void
 dacp_share_send_playstatusupdate (DACPShare *share)
 {
 	GSList *list;
-	SoupServer *server;
-	g_object_get (share, "server", &server, NULL);
-	for (list = share->priv->update_queue; list; list = list->next) {
-		dacp_share_fill_playstatusupdate (share, (SoupMessage*) list->data);
-		soup_server_unpause_message (server, (SoupMessage*) list->data);
+	SoupServer *server = NULL;
+
+	g_object_get (share, "server-ipv4", &server, NULL);
+	if (server) {
+		for (list = share->priv->update_queue; list; list = list->next) {
+			dacp_share_fill_playstatusupdate (share, (SoupMessage*) list->data);
+			soup_server_unpause_message (server, (SoupMessage*) list->data);
+		}
 	}
+
+	g_object_unref (server);
+	server = NULL;
+
+	g_object_get (share, "server-ipv6", &server, NULL);
+	if (server) {
+		for (list = share->priv->update_queue; list; list = list->next) {
+			dacp_share_fill_playstatusupdate (share, (SoupMessage*) list->data);
+			soup_server_unpause_message (server, (SoupMessage*) list->data);
+		}
+	}
+
+	g_object_unref (server);
+
 	g_slist_free (share->priv->update_queue);
 	share->priv->update_queue = NULL;
-	g_object_unref (server);
 }
 
 static void
diff --git a/libdmapsharing/dmap-share.c b/libdmapsharing/dmap-share.c
index 6b898b6..334a499 100644
--- a/libdmapsharing/dmap-share.c
+++ b/libdmapsharing/dmap-share.c
@@ -49,7 +49,8 @@ typedef enum {
 
 enum {
 	PROP_0,
-	PROP_SERVER,
+	PROP_SERVER_IPV4,
+	PROP_SERVER_IPV6,
 	PROP_NAME,
 	PROP_PASSWORD,
 	PROP_REVISION_NUMBER,
@@ -78,7 +79,8 @@ struct DMAPSharePrivate {
 	DMAPMdnsPublisher *publisher;
 
 	/* HTTP server things */
-	SoupServer *server;
+	SoupServer *server_ipv4;
+	SoupServer *server_ipv6;
 	guint revision_number;
 
 	/* The media database */
@@ -94,6 +96,7 @@ struct DMAPSharePrivate {
 /* FIXME: name this something else, as it is more than just share/bitwise now */
 struct share_bitwise_t {
 	DMAPShare *share;
+	SoupServer *server; /* Also in share, but we need to know whether server_ipv6 or _ipv4. */
 	struct MLCL_Bits mb;
 	GSList *id_list;
 	guint32 size;
@@ -238,47 +241,10 @@ static void ctrl_int_adapter (SoupServer *server,
 	                                        context);
 }
 
-gboolean
-_dmap_share_server_start (DMAPShare *share)
+static void
+_dmap_share_server_setup_handlers (DMAPShare *share, SoupServer *server)
 {
-	SoupAddress *addr;
-	guint port = DMAP_SHARE_GET_CLASS (share)->get_desired_port (share);
-	gboolean              password_required;
-
-	addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV6, port);
-	share->priv->server = soup_server_new (SOUP_SERVER_INTERFACE, addr, NULL);
-	g_object_unref (addr);
-
-	if (share->priv->server == NULL) {
-		g_warning ("Unable to start music sharing server on port %d, trying any open port", port);
-		addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV6, SOUP_ADDRESS_ANY_PORT);
-		share->priv->server = soup_server_new (SOUP_SERVER_INTERFACE, addr, NULL);
-		g_object_unref (addr);
-	}
-
-	if (share->priv->server == NULL) {
-		g_warning ("Unable to start music sharing server, trying IPv4 only");
-		addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4, port);
-		share->priv->server = soup_server_new (SOUP_SERVER_INTERFACE, addr, NULL);
-		g_object_unref (addr);
-	}
-
-	if (share->priv->server == NULL) {
-		g_warning ("Unable to start music sharing server on port %d, trying IPv4 only, any open port", port);
-		addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4, SOUP_ADDRESS_ANY_PORT);
-		share->priv->server = soup_server_new (SOUP_SERVER_INTERFACE, addr, NULL);
-		g_object_unref (addr);
-	}
-
-	if (share->priv->server == NULL) {
-		g_warning ("Unable to start music sharing server");
-		return FALSE;
-	}
-
-	share->priv->port = (guint)soup_server_get_port (share->priv->server);
-	g_debug ("Started DMAP server on port %u", share->priv->port);
-
-	password_required = (share->priv->auth_method != DMAP_SHARE_AUTH_METHOD_NONE);
+	gboolean password_required = (share->priv->auth_method != DMAP_SHARE_AUTH_METHOD_NONE);
 
 	if (password_required) {
 		SoupAuthDomain *auth_domain;
@@ -293,31 +259,100 @@ _dmap_share_server_start (DMAPShare *share)
 							  (SoupAuthDomainBasicAuthCallback) _dmap_share_soup_auth_callback,
 							  g_object_ref (share),
 							  g_object_unref);
-		soup_server_add_auth_domain (share->priv->server, auth_domain);
+		soup_server_add_auth_domain (server, auth_domain);
 	}
 
-	soup_server_add_handler (share->priv->server, "/server-info",
+	soup_server_add_handler (server, "/server-info",
 				 (SoupServerCallback) server_info_adapter,
 				 share, NULL);
-	soup_server_add_handler (share->priv->server, "/content-codes",
+	soup_server_add_handler (server, "/content-codes",
 				 (SoupServerCallback) content_codes_adapter,
 				 share, NULL);
-	soup_server_add_handler (share->priv->server, "/login",
+	soup_server_add_handler (server, "/login",
 				 (SoupServerCallback) login_adapter,
 				 share, NULL);
-	soup_server_add_handler (share->priv->server, "/logout",
+	soup_server_add_handler (server, "/logout",
 				 (SoupServerCallback) logout_adapter,
 				 share, NULL);
-	soup_server_add_handler (share->priv->server, "/update",
+	soup_server_add_handler (server, "/update",
 				 (SoupServerCallback) update_adapter,
 				 share, NULL);
-	soup_server_add_handler (share->priv->server, "/databases",
+	soup_server_add_handler (server, "/databases",
 				 (SoupServerCallback) databases_adapter,
 				 share, NULL);
-	soup_server_add_handler (share->priv->server, "/ctrl-int",
+	soup_server_add_handler (server, "/ctrl-int",
 				 (SoupServerCallback) ctrl_int_adapter,
 				 share, NULL);
-	soup_server_run_async (share->priv->server);
+	soup_server_run_async (server);
+
+}
+
+gboolean
+_dmap_share_server_start (DMAPShare *share)
+{
+	SoupAddress *addr;
+	guint port = DMAP_SHARE_GET_CLASS (share)->get_desired_port (share);
+
+	addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV6, port);
+	share->priv->server_ipv6 = soup_server_new (SOUP_SERVER_INTERFACE, addr, NULL);
+	g_object_unref (addr);
+
+	/* NOTE: On Linux, opening a socket may give a IPv6-wrapped IPv4 address.
+	 * in this case, the server_ipv6 object will service requests from both
+	 * IPv6 and IPv4 clients.
+	 */
+	if (share->priv->server_ipv6 == NULL) {
+		g_warning ("Unable to start music sharing server on port %d, trying any open port", port);
+		addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV6, SOUP_ADDRESS_ANY_PORT);
+		share->priv->server_ipv6 = soup_server_new (SOUP_SERVER_INTERFACE, addr, NULL);
+		g_object_unref (addr);
+	}
+
+	if (share->priv->server_ipv6 != NULL) {
+		/* Use same port for IPv4 as IPv6. */
+		port = soup_server_get_port (share->priv->server_ipv6);
+	} else {
+		g_warning ("Unable to start music sharing server (IPv6)");
+	}
+
+	/* NOTE: In the case mentioned above, this will fail as the server_ipv6 is already
+	 * servicing IPv4 requests. In this case server_ipv6 handles both IPv6 and IPv4
+	 * and server_ipv4 is NULL.
+	 */
+	addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4, port);
+	share->priv->server_ipv4 = soup_server_new (SOUP_SERVER_INTERFACE, addr, NULL);
+	g_object_unref (addr);
+
+	/* Don't try any port on IPv4 unless IPv6 failed. We don't want to listen to one
+	 * port on IPv6 and another on IPv4 */
+	if (share->priv->server_ipv6 == NULL && share->priv->server_ipv4 == NULL) {
+		g_warning ("Unable to start music sharing server on port %d, trying IPv4 only, any open port", port);
+		addr = soup_address_new_any (SOUP_ADDRESS_FAMILY_IPV4, SOUP_ADDRESS_ANY_PORT);
+		share->priv->server_ipv4 = soup_server_new (SOUP_SERVER_INTERFACE, addr, NULL);
+		g_object_unref (addr);
+	}
+
+	if (share->priv->server_ipv4 == NULL) {
+		g_warning ("Unable to start music sharing server (IPv4)");
+		if (share->priv->server_ipv6 == NULL) {
+			return FALSE;
+		}
+	}
+
+	if (share->priv->server_ipv6)
+		share->priv->port = (guint) soup_server_get_port (share->priv->server_ipv6);
+	else
+		share->priv->port = (guint) soup_server_get_port (share->priv->server_ipv4);
+	g_debug ("Started DMAP server on port %u (IPv6: %s, explicit IPv4: %s)",
+		  share->priv->port,
+		  share->priv->server_ipv6 ? "yes" : "no",
+		  share->priv->server_ipv4 ? "yes" : "no");
+
+	if (share->priv->server_ipv6)
+		_dmap_share_server_setup_handlers (share, share->priv->server_ipv6);
+
+	if (share->priv->server_ipv4)
+		_dmap_share_server_setup_handlers (share, share->priv->server_ipv4);
 
 	/* using direct since there is no g_uint_hash or g_uint_equal */
 	share->priv->session_ids = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
@@ -332,10 +367,16 @@ _dmap_share_server_stop (DMAPShare *share)
 {
 	g_debug ("Stopping music sharing server on port %d", share->priv->port);
 
-	if (share->priv->server) {
-		soup_server_quit (share->priv->server);
-		g_object_unref (share->priv->server);
-		share->priv->server = NULL;
+	if (share->priv->server_ipv4) {
+		soup_server_quit (share->priv->server_ipv4);
+		g_object_unref (share->priv->server_ipv4);
+		share->priv->server_ipv4 = NULL;
+	}
+
+	if (share->priv->server_ipv6) {
+		soup_server_quit (share->priv->server_ipv6);
+		g_object_unref (share->priv->server_ipv6);
+		share->priv->server_ipv6 = NULL;
 	}
 
 	if (share->priv->session_ids) {
@@ -518,8 +559,11 @@ _dmap_share_get_property (GObject *object,
 	DMAPShare *share = DMAP_SHARE (object);
 
 	switch (prop_id) {
-	case PROP_SERVER:
-		g_value_set_object (value, share->priv->server);
+	case PROP_SERVER_IPV4:
+		g_value_set_object (value, share->priv->server_ipv4);
+		return;
+	case PROP_SERVER_IPV6:
+		g_value_set_object (value, share->priv->server_ipv6);
 		return;
 	case PROP_NAME:
 		g_value_set_string (value, share->priv->name);
@@ -614,8 +658,16 @@ dmap_share_class_init (DMAPShareClass *klass)
 	klass->ctrl_int       = _dmap_share_ctrl_int;
 
 	g_object_class_install_property (object_class,
-					 PROP_SERVER,
-					 g_param_spec_object ("server",
+					 PROP_SERVER_IPV4,
+					 g_param_spec_object ("server-ipv4",
+							      "Soup Server",
+							      "Soup server",
+							      SOUP_TYPE_SERVER,
+							      G_PARAM_READABLE));
+	
+	g_object_class_install_property (object_class,
+					 PROP_SERVER_IPV6,
+					 g_param_spec_object ("server-ipv6",
 							      "Soup Server",
 							      "Soup server",
 							      SOUP_TYPE_SERVER,
@@ -1546,7 +1598,7 @@ write_next_mlit (SoupMessage *message, struct share_bitwise_t *share_bitwise)
 		g_object_unref (record);
 	}
 
-	soup_server_unpause_message (share_bitwise->share->priv->server, message);
+	soup_server_unpause_message (share_bitwise->server, message);
 }
 
 static void
@@ -1760,6 +1812,7 @@ _dmap_share_databases (DMAPShare *share,
 		/* 1: */
 		share_bitwise = g_new (struct share_bitwise_t, 1);
 		share_bitwise->share = share;
+		share_bitwise->server = server;
 		share_bitwise->mb = mb;
 		share_bitwise->id_list = NULL;
 		share_bitwise->size = 0;



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]