[libdmapsharing] Initial client-side DNS-SD work. Signed-off-by: W. Michael Petullo <mike flyn org>
- From: W. Michael Petullo <wmpetullo src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libdmapsharing] Initial client-side DNS-SD work. Signed-off-by: W. Michael Petullo <mike flyn org>
- Date: Thu, 24 Mar 2011 02:25:50 +0000 (UTC)
commit 0c91d00495e0f2a5ffede53b784cc22e6208d3a5
Author: W. Michael Petullo <mike flyn org>
Date: Wed Mar 23 21:25:21 2011 -0500
Initial client-side DNS-SD work.
Signed-off-by: W. Michael Petullo <mike flyn org>
libdmapsharing/dmap-mdns-browser-dnssd.c | 641 +++++++++++++++++++++++++++++-
1 files changed, 626 insertions(+), 15 deletions(-)
---
diff --git a/libdmapsharing/dmap-mdns-browser-dnssd.c b/libdmapsharing/dmap-mdns-browser-dnssd.c
index f652f84..ceca1ab 100644
--- a/libdmapsharing/dmap-mdns-browser-dnssd.c
+++ b/libdmapsharing/dmap-mdns-browser-dnssd.c
@@ -16,33 +16,644 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA*
*/
-#include "config.h"
+#include <stdlib.h>
#include <stdio.h>
-#include <glib.h>
#include <dns_sd.h>
+#include <string.h>
+#include <assert.h>
+#include <time.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <arpa/inet.h>
+
+#include <sys/time.h>
+#include <sys/types.h>
+#include <sys/select.h>
+
+#include <glib.h>
+#include <glib-object.h>
+#include "config.h"
#include "dmap-mdns-browser.h"
-DMAPMdnsBrowser *
-dmap_mdns_browser_new (DMAPMdnsBrowserServiceType type)
+#define LONG_TIME 10000000
+
+
+
+static volatile int stopNow = 0;
+static volatile int timeOut = LONG_TIME;
+
+
+
+struct
+_DMAPMdnsBrowserPrivate
+{
+ DMAPMdnsBrowserServiceType service_type;
+
+ DNSServiceFlags flags;
+
+ uint16_t port;
+ uint32_t interfaceIndex;
+
+ char regtype[100];
+ char domain[100];
+ char serviceName[100];
+ char fullname[100];
+ char hosttarget[100];
+
+ GSList *services;
+ GSList *resolvers;
+};
+
+enum
{
- g_error ("Not implemented");
- return NULL;
+ SERVICE_ADDED,
+ SERVICE_REMOVED,
+ LAST_SIGNAL
+};
+
+
+static void
+print_browser (DMAPMdnsBrowser *browser);
+
+static gboolean
+dnssd_resolve_services (DMAPMdnsBrowser *browser, DNSServiceRef sdRef);
+
+static void
+dmap_mdns_browser_class_init (DMAPMdnsBrowserClass *klass);
+
+static void
+dmap_mdns_browser_init (DMAPMdnsBrowser *browser);
+
+static void
+dmap_mdns_browser_dispose (GObject *object);
+
+static void
+dmap_mdns_browser_finalize (GObject *object);
+
+static void
+dnssd_browser_init (DMAPMdnsBrowser *browser);
+
+static void
+free_service (DMAPMdnsBrowserService *service);
+
+static void
+browser_add_service (
+ DMAPMdnsBrowser *browser,
+ const gchar *service_name,
+ const gchar *domain);
+
+static gboolean
+dmap_mdns_browser_resolve (
+ DMAPMdnsBrowser *browser,
+ const gchar *name,
+ const gchar *domain);
+
+void
+dnsServiceBrowseReply (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *serviceName,
+ const char *regtype,
+ const char *replyDomain,
+ void *context);
+
+void
+dnsServiceResolveReply (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ const char *hosttarget,
+ uint16_t port,
+ uint16_t txtLen,
+ const char *txtRecord,
+ void *context);
+
+gboolean
+dmap_mdns_browser_stop (
+ DMAPMdnsBrowser *browser,
+ GError **error);
+
+static const char*
+service_type_name[] =
+{
+ NULL,
+ "_daap._tcp",
+ "_dpap._tcp",
+ "_touch-remote._tcp"
+};
+
+
+#define DMAP_MDNS_BROWSER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DMAP_TYPE_MDNS_BROWSER, DMAPMdnsBrowserPrivate))
+
+static guint
+dmap_mdns_browser_signals [LAST_SIGNAL] = { 0, };
+
+G_DEFINE_TYPE (DMAPMdnsBrowser, dmap_mdns_browser, G_TYPE_OBJECT)
+
+static void
+dmap_mdns_browser_init (DMAPMdnsBrowser *browser)
+{
+ printf ("dmap_mdns_browser_init ()\n");
+
+ browser->priv = DMAP_MDNS_BROWSER_GET_PRIVATE (browser);
+ dnssd_browser_init (browser);
+
+ printf ("\n");
}
+
gboolean
-dmap_mdns_browser_start (DMAPMdnsBrowser *browser,
- GError **error)
+dnssd_resolve_services (DMAPMdnsBrowser *browser, DNSServiceRef sdRef)
+{
+ printf ("dnssd_resolve_services ()\n");
+
+ int dns_sd_fd = DNSServiceRefSockFD (sdRef);
+ int nFDs = dns_sd_fd + 1;
+ int result = 0;
+
+ struct timeval tv;
+ fd_set readfds;
+
+ stopNow = 0;
+
+ gboolean isSuccess = FALSE;
+
+ print_browser (browser);
+
+ while (!stopNow)
+ {
+ printf ("*** Loop: processing ****\n");
+
+ FD_ZERO (&readfds);
+ FD_SET (dns_sd_fd, &readfds);
+
+ tv.tv_sec = timeOut;
+ tv.tv_usec = 0;
+
+ result = select (nFDs, &readfds, (fd_set*) NULL, (fd_set*) NULL, &tv);
+
+ if (result > 0)
+ {
+ printf ("*** Loop: (result > 0) ****\n");
+
+ DNSServiceErrorType err = kDNSServiceErr_NoError;
+
+ if (FD_ISSET (dns_sd_fd, &readfds))
+ {
+ printf ("*** Loop: reading daemon response ****\n");
+ err = DNSServiceProcessResult (sdRef);
+ }
+
+ if (err)
+ {
+ printf ("*** Loop: error reading daemon ****\n");
+ stopNow = 1;
+ }
+ else
+ {
+ printf ("*** Loop: success reading daemon ****\n");
+ isSuccess = TRUE;
+ stopNow = 1;
+ }
+ }
+ else if (0 == result)
+ {
+ printf ("*** Loop: waiting ****\n");
+ }
+ else
+ {
+ printf ("select () returned %d errno %d %s\n",
+ result, errno, strerror (errno));
+
+ if (errno == EBADF)
+ {
+ printf ("*** Loop - EBADF ****\n");
+ }
+ else if (errno == EINTR)
+ {
+ printf ("*** Loop - EINTR ****\n");
+ }
+ else if (errno == EISDIR)
+ {
+ printf ("*** Loop - EISDIR ****\n");
+ }
+ else if (errno == EINVAL)
+ {
+ printf ("*** Loop - EINVAL ****\n");
+ }
+
+ stopNow = 1;
+ }
+ }
+
+ printf ("\n");
+
+ FD_CLR (dns_sd_fd, &readfds);
+
+ return isSuccess;
+}
+
+
+
+void
+dnsServiceBrowseReply (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *serviceName,
+ const char *regtype,
+ const char *replyDomain,
+ void *context)
{
- g_error ("Not implemented");
- return FALSE;
+ if (errorCode == kDNSServiceErr_NoError)
+ {
+ printf("dnsServiceBrowserReply (): success\n");
+
+ // Cast the context pointer to a DMAPMdnsBrowser
+ DMAPMdnsBrowser *browser = (DMAPMdnsBrowser *) context;
+
+ browser->priv->flags = flags;
+ browser->priv->interfaceIndex = interfaceIndex;
+
+ strcpy (browser->priv->serviceName, serviceName);
+ strcpy (browser->priv->regtype, regtype);
+ strcpy (browser->priv->domain, replyDomain);
+ }
+ else
+ {
+ printf("dnsServiceBrowserReply (): fail\n");
+ }
+
+ printf("\n");
}
-gboolean
-dmap_mdns_browser_stop (DMAPMdnsBrowser *browser,
- GError **error)
+
+
+void
+dnsServiceResolveReply (
+ DNSServiceRef sdRef,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType errorCode,
+ const char *fullname,
+ const char *hosttarget,
+ uint16_t port,
+ uint16_t txtLen,
+ const char *txtRecord,
+ void *context)
{
- g_error ("Not implemented");
- return FALSE;
+ printf ("dnsServiceResolveReply ()\n");
+
+ // Cast the context pointer to a DMAPMdnsBrowser
+ DMAPMdnsBrowser *browser = (DMAPMdnsBrowser *) context;
+
+ if (kDNSServiceErr_NoError == errorCode)
+ {
+
+ browser->priv->flags = flags;
+ browser->priv->interfaceIndex = interfaceIndex;
+ browser->priv->port = htons (port);
+
+ strcpy (browser->priv->fullname, fullname);
+ strcpy (browser->priv->hosttarget, hosttarget);
+ }
+}
+
+
+
+static void
+dnssd_browser_init (DMAPMdnsBrowser *browser)
+{
+ printf ("dnssd_browser_init()\n");
+
+ browser->priv->flags = kDNSServiceFlagsDefault;
+ browser->priv->port = 0;
+ browser->priv->interfaceIndex = 0;
+
+ strcpy (browser->priv->regtype, service_type_name[1]);
+ strcpy (browser->priv->domain, "");
+ strcpy (browser->priv->serviceName, "");
+ strcpy (browser->priv->fullname, "");
+ strcpy (browser->priv->hosttarget, "");
+
+ print_browser (browser);
+
+ printf ("\n");
}
+
+
+
+static void
+dmap_mdns_browser_class_init (DMAPMdnsBrowserClass *klass)
+{
+ printf ("dmap_mdns_browser_class_init()\n\n");
+
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ dmap_mdns_browser_parent_class = g_type_class_peek_parent (klass);
+
+ object_class->dispose = dmap_mdns_browser_dispose;
+ object_class->finalize = dmap_mdns_browser_finalize;
+
+ g_type_class_add_private (klass, sizeof (DMAPMdnsBrowserPrivate));
+
+ // Signal makeup
+ dmap_mdns_browser_signals [SERVICE_ADDED] =
+ g_signal_new ("service-added",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DMAPMdnsBrowserClass, service_added),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__POINTER,
+ G_TYPE_NONE,
+ 1, G_TYPE_POINTER);
+
+ dmap_mdns_browser_signals [SERVICE_REMOVED] =
+ g_signal_new ("service-removed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (DMAPMdnsBrowserClass, service_removed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+}
+
+
+
+DMAPMdnsBrowser*
+dmap_mdns_browser_new (DMAPMdnsBrowserServiceType type)
+{
+ printf ("dmap_mdns_browser_new ()\n\n");
+
+ DMAPMdnsBrowser *browser_object = 0;
+
+ g_return_val_if_fail (type >= DMAP_MDNS_BROWSER_SERVICE_TYPE_INVALID &&
+ type <= DMAP_MDNS_BROWSER_SERVICE_TYPE_LAST, NULL);
+
+ browser_object =
+ DMAP_MDNS_BROWSER (g_object_new (DMAP_TYPE_MDNS_BROWSER, NULL));
+ browser_object->priv->service_type = type;
+
+ return browser_object;
+}
+
+
+
+static gboolean
+dmap_mdns_browser_resolve (
+ DMAPMdnsBrowser *browser,
+ const gchar *name,
+ const gchar *domain)
+{
+ printf ("dmap_mdns_browser_resolve ()\n");
+
+ DMAPMdnsBrowserService *service;
+ service = g_new (DMAPMdnsBrowserService, 1);
+
+ service->service_name = g_strdup (browser->priv->regtype);
+ service->name = name;
+ service->host = g_strdup (browser->priv->hosttarget);
+ service->port = browser->priv->port;
+ service->pair = NULL;
+ service->password_protected = FALSE;
+
+ // add to the services list
+ browser->priv->services =
+ g_slist_append (browser->priv->services, service);
+
+ // notify all listeners
+ g_signal_emit (
+ browser,
+ dmap_mdns_browser_signals [SERVICE_ADDED],
+ 0,
+ service);
+
+ printf ("\n");
+
+ return TRUE;
+}
+
+
+
+static void
+browser_add_service (
+ DMAPMdnsBrowser *browser,
+ const gchar *service_name,
+ const gchar *domain)
+{
+ printf ("browser_add_service ()\n");
+
+ dmap_mdns_browser_resolve (browser, service_name, domain);
+
+ printf ("\n");
+}
+
+
+
+gboolean
+dmap_mdns_browser_start (DMAPMdnsBrowser *browser, GError **error)
+{
+ printf ("dmap_mdns_browser_start ()\n");
+
+ gboolean isSuccess = FALSE;
+ gboolean canBrowse = FALSE;
+ gboolean canResolve = FALSE;
+
+ DNSServiceRef sdBrowseRef;
+ DNSServiceRef sdServiceRef;
+
+ DNSServiceErrorType browseErr = kDNSServiceErr_Unknown;
+ DNSServiceErrorType resolveErr = kDNSServiceErr_Unknown;
+
+ print_browser (browser);
+
+ browseErr = DNSServiceBrowse (
+ &(sdBrowseRef),
+ browser->priv->flags,
+ browser->priv->interfaceIndex,
+ browser->priv->regtype,
+ browser->priv->domain,
+ (DNSServiceBrowseReply) dnsServiceBrowseReply,
+ (void *) browser);
+
+ if (kDNSServiceErr_NoError == browseErr)
+ {
+ printf ("*** Browse Success ****\n");
+ canBrowse = dnssd_resolve_services (browser, sdBrowseRef);
+ DNSServiceRefDeallocate (sdBrowseRef);
+ }
+
+ if (canBrowse)
+ {
+ printf ("*** Browser read from daemon ****\n");
+ resolveErr = DNSServiceResolve (
+ &(sdServiceRef),
+ browser->priv->flags,
+ browser->priv->interfaceIndex,
+ browser->priv->serviceName,
+ browser->priv->regtype,
+ browser->priv->domain,
+ (DNSServiceResolveReply) dnsServiceResolveReply,
+ (void *) browser);
+ }
+
+ if (kDNSServiceErr_NoError == resolveErr)
+ {
+ printf ("*** Service Resolve Success ****\n");
+ canResolve = dnssd_resolve_services (browser, sdServiceRef);
+ DNSServiceRefDeallocate (sdServiceRef);
+ }
+
+ if (canResolve)
+ {
+ printf ("*** Service read from daemon ****\n");
+
+ print_browser (browser);
+
+ // Add the successful browsed service
+ browser_add_service (
+ browser,
+ (gchar *) browser->priv->serviceName,
+ (gchar *) browser->priv->domain);
+
+ isSuccess = TRUE;
+ }
+
+ printf ("\n");
+
+ return isSuccess;
+}
+
+
+
+/**
+ * Note that you must terminate the connection with the daemon and
+ * free any memory associated with DNSServiceRef
+ */
+gboolean
+dmap_mdns_browser_stop (DMAPMdnsBrowser *browser, GError **error)
+{
+ return TRUE;
+}
+
+
+
+GQuark
+dmap_mdns_browser_error_quark (void)
+{
+ static GQuark quark = 0;
+
+ if (!quark)
+ {
+ // Create a unique quark from the specified string
+ quark = g_quark_from_static_string
+ ("DNS-SD: dmap_mdns_browser_error_quark");
+ }
+
+ return quark;
+}
+
+
+
+G_CONST_RETURN GSList*
+dmap_mdns_browser_get_services (DMAPMdnsBrowser *browser)
+{
+ g_return_val_if_fail (browser != NULL, NULL);
+ return browser->priv->services;
+}
+
+
+
+DMAPMdnsBrowserServiceType
+dmap_mdns_browser_get_service_type (DMAPMdnsBrowser *browser)
+{
+ g_return_val_if_fail (
+ browser != NULL,
+ DMAP_MDNS_BROWSER_SERVICE_TYPE_INVALID);
+ return browser->priv->service_type;
+}
+
+
+
+static void
+dmap_mdns_browser_dispose (GObject *object)
+{
+ DMAPMdnsBrowser *browser = DMAP_MDNS_BROWSER (object);
+ GSList *walk;
+ DMAPMdnsBrowserService *service;
+
+ for (walk = browser->priv->services; walk; walk = walk->next)
+ {
+ service = (DMAPMdnsBrowserService *) walk->data;
+ free_service (service);
+ }
+
+ g_slist_free (browser->priv->services);
+
+ /*
+ if (browser->priv->resolvers)
+ {
+ g_slist_foreach (
+ browser->priv->resolvers,
+ DNSServiceRefDeallocate,
+ NULL);
+
+ g_slist_free (browser->priv->resolvers);
+ }
+ */
+
+ G_OBJECT_CLASS (dmap_mdns_browser_parent_class)->dispose (object);
+}
+
+
+
+static void
+dmap_mdns_browser_finalize (GObject *object)
+{
+ g_signal_handlers_destroy (object);
+ G_OBJECT_CLASS (dmap_mdns_browser_parent_class)->finalize (object);
+}
+
+
+
+static void
+free_service (DMAPMdnsBrowserService *service)
+{
+ g_free (service->service_name);
+ g_free (service->name);
+ g_free (service->host);
+ g_free (service->pair);
+ g_free (service);
+}
+
+
+static void
+print_browser (DMAPMdnsBrowser *browser)
+{
+ printf ("\n======= Browser Fields =======\n");
+
+ printf (" regtype: %s\n", browser->priv->regtype);
+ printf ("service_name: %s\n", browser->priv->serviceName);
+ printf (" fullname: %s\n", browser->priv->fullname);
+ printf (" host target: %s\n", browser->priv->hosttarget);
+ printf (" domain: %s\n", browser->priv->domain);
+
+ printf (" port: %d\n", browser->priv->port);
+ printf (" iface index: %d\n", browser->priv->interfaceIndex);
+ printf (" flags: %d\n", browser->priv->flags);
+ printf ("==============================\n");
+
+ printf ("\n");
+}
+
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]