summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOlli Salli <olli.salli@collabora.co.uk>2012-03-26 18:37:06 +0300
committerOlli Salli <olli.salli@collabora.co.uk>2012-03-26 18:38:19 +0300
commit8f19f6a49cc6affb7b100f6a711f41af0c90eb40 (patch)
tree44bf06338f3f993262a0c28fea75cbf32ec641ec
parenta7e8bc4c56eeab229147630b06b9ce395018bae3 (diff)
parent79b2f7bed48e64569291464dbcb7d1b42a67e709 (diff)
downloadtelepathy-salut-8f19f6a49cc6affb7b100f6a711f41af0c90eb40.tar.gz
Merge remote-tracking branch 'siraj/fix_review'
Reviewed-by: Olli Salli <olli.salli@collabora.co.uk> Reviewed-by: Jonny Lamb <jonny.lamb@collabora.co.uk>
-rw-r--r--src/Makefile.am4
-rw-r--r--src/bonjour-contact-manager.c242
-rw-r--r--src/bonjour-contact.c736
-rw-r--r--src/bonjour-contact.h75
-rw-r--r--src/bonjour-discovery-client.c100
-rw-r--r--src/bonjour-discovery-client.h8
-rw-r--r--src/bonjour-self.c41
7 files changed, 1051 insertions, 155 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
index 7968c434..8a985abd 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -17,7 +17,6 @@ noinst_PROGRAMS = write-mgr-file
CORE_SOURCES = \
symbol-hacks.c \
symbol-hacks.h \
- capability-set.c \
$(top_srcdir)/salut/capabilities.h \
$(top_srcdir)/salut/capability-set.h \
gabble_namespaces.h \
@@ -101,6 +100,8 @@ AVAHI_BACKEND_SOURCES = \
BONJOUR_BACKEND_SOURCES = \
bonjour-self.h \
bonjour-self.c \
+ bonjour-contact.h \
+ bonjour-contact.c \
bonjour-contact-manager.h \
bonjour-contact-manager.c \
bonjour-discovery-client.h \
@@ -141,6 +142,7 @@ libsalut_plugins_android_la_LDFLAGS = \
libsalut_plugins_la_LIBADD = \
@TELEPATHY_GLIB_LIBS@ \
+ @GLIB_LIBS@ \
@WOCKY_LIBS@
libsalut_plugins_la_SOURCES = \
diff --git a/src/bonjour-contact-manager.c b/src/bonjour-contact-manager.c
index 97bedf88..569f6dd8 100644
--- a/src/bonjour-contact-manager.c
+++ b/src/bonjour-contact-manager.c
@@ -22,10 +22,16 @@
#include <stdlib.h>
#include <string.h>
+#include <dns_sd.h>
+#undef interface
+
#define DEBUG_FLAG DEBUG_MUC
#include "debug.h"
+#include "bonjour-contact.h"
#include "bonjour-contact-manager.h"
+#include "plugin-connection.h"
+#include "connection.h"
G_DEFINE_TYPE (SalutBonjourContactManager, salut_bonjour_contact_manager,
SALUT_TYPE_CONTACT_MANAGER);
@@ -43,8 +49,9 @@ typedef struct _SalutBonjourContactManagerPrivate SalutBonjourContactManagerPriv
struct _SalutBonjourContactManagerPrivate
{
SalutBonjourDiscoveryClient *discovery_client;
- gpointer *presence_browser;
+ DNSServiceRef presence_browser;
+ gboolean all_for_now;
gboolean dispose_has_run;
};
@@ -55,9 +62,9 @@ struct _SalutBonjourContactManagerPrivate
static void
salut_bonjour_contact_manager_get_property (GObject *object,
- guint property_id,
- GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
{
SalutBonjourContactManager *chan = SALUT_BONJOUR_CONTACT_MANAGER (object);
SalutBonjourContactManagerPrivate *priv =
@@ -75,9 +82,9 @@ salut_bonjour_contact_manager_get_property (GObject *object,
static void
salut_bonjour_contact_manager_set_property (GObject *object,
- guint property_id,
- const GValue *value,
- GParamSpec *pspec)
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
{
SalutBonjourContactManager *chan = SALUT_BONJOUR_CONTACT_MANAGER (object);
SalutBonjourContactManagerPrivate *priv =
@@ -102,154 +109,153 @@ salut_bonjour_contact_manager_init (SalutBonjourContactManager *self)
self->priv = priv;
+ priv->all_for_now = FALSE;
priv->discovery_client = NULL;
}
static SalutContact *
salut_bonjour_contact_manager_create_contact (SalutContactManager *mgr,
- const gchar *name)
+ const gchar *name)
{
- /*
SalutBonjourContactManager *self = SALUT_BONJOUR_CONTACT_MANAGER (mgr);
SalutBonjourContactManagerPrivate *priv =
SALUT_BONJOUR_CONTACT_MANAGER_GET_PRIVATE (self);
- SALUT_CONTACT (salut_bonjour_contact_new (mgr->connection,
- name, priv->discovery_client));
- */
- return NULL;
+ return SALUT_CONTACT (salut_bonjour_contact_new (mgr->connection,
+ name, priv->discovery_client));
}
-/*
-static void
-browser_found (GaServiceBrowser *browser,
- BonjourIfIndex interface,
- BonjourProtocol protocol,
- const char *name,
- const char *type,
- const char *domain,
- GaLookupResultFlags flags,
- SalutBonjourContactManager *self)
+
+static void DNSSD_API
+_salut_bonjour_service_browse_cb (DNSServiceRef service,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType error_type,
+ const char *name,
+ const char *regtype,
+ const char *domain,
+ void *context)
{
+ SalutBonjourContactManager *self = SALUT_BONJOUR_CONTACT_MANAGER (context);
SalutContactManager *mgr = SALUT_CONTACT_MANAGER (self);
+ SalutBonjourContactManagerPrivate *priv =
+ SALUT_BONJOUR_CONTACT_MANAGER_GET_PRIVATE (self);
SalutContact *contact;
- const char *contact_name = name;
+ const char *self_contact_name;
- if (flags & BONJOUR_LOOKUP_RESULT_OUR_OWN)
- return;
-
- contact = g_hash_table_lookup (mgr->contacts, contact_name);
- if (contact == NULL)
- {
- contact = salut_bonjour_contact_manager_create_contact (mgr, contact_name);
- salut_contact_manager_contact_created (mgr, contact);
- }
- else if (!salut_bonjour_contact_has_services (SALUT_BONJOUR_CONTACT (contact)))
+ if (error_type != kDNSServiceErr_NoError)
{
- g_object_ref (contact);
+ DEBUG ("Browser Failed with : (%d)", error_type);
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ priv->presence_browser);
+ return;
}
- if (!salut_bonjour_contact_add_service (SALUT_BONJOUR_CONTACT (contact),
- interface, protocol, name, type, domain))
- {
- if (!salut_bonjour_contact_has_services (SALUT_BONJOUR_CONTACT (contact)))
- g_object_unref (contact);
- }
- else
- {
- WockyContactFactory *contact_factory;
-
- contact_factory = wocky_session_get_contact_factory (
- mgr->connection->session);
-
- wocky_contact_factory_add_ll_contact (contact_factory,
- WOCKY_LL_CONTACT (contact));
- }
-}
-
-static void
-browser_removed (GaServiceBrowser *browser,
- BonjourIfIndex interface,
- BonjourProtocol protocol,
- const char *name,
- const char *type,
- const char *domain,
- GaLookupResultFlags flags,
- SalutBonjourContactManager *self)
-{
- SalutContactManager *mgr = SALUT_CONTACT_MANAGER (self);
- SalutContact *contact;
- const char *contact_name = name;
+ self_contact_name = salut_connection_get_name (SALUT_PLUGIN_CONNECTION (
+ mgr->connection));
- DEBUG ("Browser removed for %s", name);
+ if (g_ascii_strcasecmp (name, self_contact_name) == 0)
+ return;
- contact = g_hash_table_lookup (mgr->contacts, contact_name);
- if (contact != NULL)
+ if (flags & kDNSServiceFlagsAdd)
{
- salut_bonjour_contact_remove_service (SALUT_BONJOUR_CONTACT (contact),
- interface, protocol, name, type, domain);
- if (!salut_bonjour_contact_has_services (SALUT_BONJOUR_CONTACT (contact)))
- g_object_unref (contact);
-
+ DEBUG ("New Service : %s, on iface : %u, with domain %s of type %s",
+ name, interfaceIndex, domain, regtype);
+
+ contact = g_hash_table_lookup (mgr->contacts, name);
+
+ if (contact == NULL)
+ {
+ contact = salut_bonjour_contact_manager_create_contact (mgr, name);
+ salut_contact_manager_contact_created (mgr, contact);
+ }
+ else if (!salut_bonjour_contact_has_services (SALUT_BONJOUR_CONTACT
+ (contact)))
+ {
+ g_object_ref (contact);
+ }
+
+ if (!salut_bonjour_contact_add_service (SALUT_BONJOUR_CONTACT (contact),
+ interfaceIndex, name, regtype, domain))
+ {
+ /* If we couldn't add the server check the refcounting */
+ if (!salut_bonjour_contact_has_services (SALUT_BONJOUR_CONTACT (contact)))
+ g_object_unref (contact);
+ }
+ else
+ {
+ WockyContactFactory *contact_factory;
+
+ contact_factory = wocky_session_get_contact_factory (
+ mgr->connection->session);
+ wocky_contact_factory_add_ll_contact (contact_factory,
+ WOCKY_LL_CONTACT (contact));
+ }
}
else
{
- DEBUG ("Unknown contact removed from service browser");
+ DEBUG ("Contact Removed : %s", name);
+ contact = g_hash_table_lookup (mgr->contacts, name);
+
+ if (contact != NULL)
+ {
+ salut_bonjour_contact_remove_service (SALUT_BONJOUR_CONTACT (contact),
+ interfaceIndex, name, regtype, domain);
+ if (!salut_bonjour_contact_has_services
+ (SALUT_BONJOUR_CONTACT (contact)))
+ {
+ g_object_unref (contact);
+ }
+ }
+ else
+ {
+ DEBUG ("Unknown Contact Removed from Service Browser");
+ }
}
-}
-static void
-browser_failed (GaServiceBrowser *browser,
- GError *error,
- SalutBonjourContactManager *self)
-{
- g_warning ("browser failed -> %s", error->message);
+ if (!priv->all_for_now && !(flags & kDNSServiceFlagsMoreComing))
+ {
+ g_signal_emit_by_name (self, "all-for-now");
+ priv->all_for_now = TRUE;
+ }
}
-
-static void
-browser_all_for_now (GaServiceBrowser *browser,
- SalutBonjourContactManager *self)
-{
- g_signal_emit_by_name (self, "all-for-now");
-}
-*/
static gboolean
salut_bonjour_contact_manager_start (SalutContactManager *mgr,
- GError **error)
+ GError **error)
{
-/*
SalutBonjourContactManager *self = SALUT_BONJOUR_CONTACT_MANAGER (mgr);
SalutBonjourContactManagerPrivate *priv =
SALUT_BONJOUR_CONTACT_MANAGER_GET_PRIVATE (self);
- g_signal_connect (priv->presence_browser, "new-service",
- G_CALLBACK (browser_found), mgr);
- g_signal_connect (priv->presence_browser, "removed-service",
- G_CALLBACK (browser_removed), mgr);
- g_signal_connect (priv->presence_browser, "failure",
- G_CALLBACK (browser_failed), mgr);
- g_signal_connect (priv->presence_browser, "all-for-now",
- G_CALLBACK (browser_all_for_now), mgr);
-
- if (!ga_service_browser_attach (priv->presence_browser,
- priv->discovery_client->bonjour_client, error))
+ DNSServiceErrorType error_type = kDNSServiceErr_NoError;
+ const gchar *dnssd_name =
+ salut_bonjour_discovery_client_get_dnssd_name (priv->discovery_client);
+
+ error_type = DNSServiceBrowse (&priv->presence_browser, 0,
+ kDNSServiceInterfaceIndexAny, dnssd_name, NULL,
+ _salut_bonjour_service_browse_cb, self);
+
+ if (error_type != kDNSServiceErr_NoError)
{
- DEBUG ("browser attach failed");
+ *error = g_error_new (TP_ERRORS, TP_ERROR_NOT_AVAILABLE,
+ "Service Browse Failed with : (%d)", error_type);
return FALSE;
}
-*/
+
+ salut_bonjour_discovery_client_watch_svc_ref (priv->discovery_client,
+ priv->presence_browser);
+
return TRUE;
}
static void
salut_bonjour_contact_manager_dispose_contact (SalutContactManager *mgr,
- SalutContact *contact)
+ SalutContact *contact)
{
- /*
if (salut_bonjour_contact_has_services (SALUT_BONJOUR_CONTACT (contact)))
{
+ /* We reffed this contact as it has services */
g_object_unref (contact);
}
- */
}
static void
@@ -259,11 +265,8 @@ salut_bonjour_contact_manager_close_all (SalutContactManager *mgr)
SalutBonjourContactManagerPrivate *priv =
SALUT_BONJOUR_CONTACT_MANAGER_GET_PRIVATE (self);
- if (priv->presence_browser != NULL)
- {
- g_object_unref (priv->presence_browser);
- priv->presence_browser = NULL;
- }
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ priv->presence_browser);
if (priv->discovery_client != NULL)
{
@@ -275,17 +278,6 @@ salut_bonjour_contact_manager_close_all (SalutContactManager *mgr)
static void
salut_bonjour_contact_manager_constructed (GObject *object)
{
- SalutBonjourContactManager *self = SALUT_BONJOUR_CONTACT_MANAGER (object);
- SalutBonjourContactManagerPrivate *priv =
- SALUT_BONJOUR_CONTACT_MANAGER_GET_PRIVATE (self);
- /*
- const gchar *dnssd_name = salut_bonjour_discovery_client_get_dnssd_name (
- priv->discovery_client);
-
- ga_service_browser_new ((gchar *) dnssd_name);
- */
- priv->presence_browser = NULL;
-
if (G_OBJECT_CLASS (salut_bonjour_contact_manager_parent_class)->constructed)
G_OBJECT_CLASS (salut_bonjour_contact_manager_parent_class)->constructed (object);
}
@@ -325,7 +317,7 @@ salut_bonjour_contact_manager_class_init (
SalutBonjourContactManager *
salut_bonjour_contact_manager_new (SalutConnection *connection,
- SalutBonjourDiscoveryClient *discovery_client)
+ SalutBonjourDiscoveryClient *discovery_client)
{
return g_object_new (SALUT_TYPE_BONJOUR_CONTACT_MANAGER,
"connection", connection,
diff --git a/src/bonjour-contact.c b/src/bonjour-contact.c
new file mode 100644
index 00000000..96285a76
--- /dev/null
+++ b/src/bonjour-contact.c
@@ -0,0 +1,736 @@
+/*
+ * bonjour-contact.c - Source for SalutBonjourContact
+ * Copyright (C) 2012 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <dbus/dbus-glib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#undef interface
+#include "bonjour-contact.h"
+
+#include <telepathy-glib/channel-factory-iface.h>
+#include <telepathy-glib/interfaces.h>
+
+#define DEBUG_FLAG DEBUG_MUC
+#include "debug.h"
+
+G_DEFINE_TYPE (SalutBonjourContact, salut_bonjour_contact,
+ SALUT_TYPE_CONTACT);
+
+/* properties */
+enum {
+ PROP_CLIENT = 1,
+ LAST_PROP
+};
+
+/* private structure */
+typedef struct _SalutBonjourContactPrivate SalutBonjourContactPrivate;
+
+struct _SalutBonjourContactPrivate
+{
+ SalutBonjourDiscoveryClient *discovery_client;
+ GSList *resolvers;
+
+ char *full_name;
+
+ gboolean dispose_has_run;
+};
+
+struct resolverInfo {
+ uint32_t interface;
+ const char *name;
+ const char *type;
+ const char *domain;
+};
+
+typedef struct _SalutBonjourResolveCtx
+{
+ DNSServiceRef resolve_ref;
+ DNSServiceRef address_ref;
+
+ SalutBonjourContact *contact;
+
+ char *name;
+ char *type;
+ char *domain;
+ uint32_t interface;
+ struct sockaddr *address;
+ uint16_t port;
+
+ uint16_t txt_length;
+ char *txt_record;
+} SalutBonjourResolveCtx;
+
+static void
+salut_bonjour_contact_init (SalutBonjourContact *self)
+{
+ SalutBonjourContactPrivate *priv = G_TYPE_INSTANCE_GET_PRIVATE (self,
+ SALUT_TYPE_BONJOUR_CONTACT, SalutBonjourContactPrivate);
+
+ self->priv = priv;
+
+ priv->full_name = NULL;
+ priv->resolvers = NULL;
+}
+
+static void
+_salut_bonjour_resolve_ctx_free (SalutBonjourContact *self,
+ SalutBonjourResolveCtx *ctx)
+{
+ SalutBonjourContactPrivate *priv = self->priv;
+
+ if (ctx->address_ref != NULL)
+ {
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ ctx->address_ref);
+ }
+
+ if (ctx->txt_record)
+ {
+ g_free (ctx->txt_record);
+ }
+
+ if (ctx->address)
+ g_free (ctx->address);
+
+ if (ctx->name)
+ g_free (ctx->name);
+
+ if (ctx->type)
+ g_free (ctx->type);
+
+ if (ctx->domain)
+ g_free (ctx->domain);
+
+ g_slice_free (SalutBonjourResolveCtx, ctx);
+}
+
+static void
+salut_bonjour_contact_get_property (GObject *object,
+ guint property_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ SalutBonjourContact *self = SALUT_BONJOUR_CONTACT (object);
+ SalutBonjourContactPrivate *priv = self->priv;
+
+ switch (property_id)
+ {
+ case PROP_CLIENT:
+ g_value_set_object (value, priv->discovery_client);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static void
+salut_bonjour_contact_set_property (GObject *object,
+ guint property_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ SalutBonjourContact *self = SALUT_BONJOUR_CONTACT (object);
+ SalutBonjourContactPrivate *priv = self->priv;
+
+ switch (property_id)
+ {
+ case PROP_CLIENT:
+ priv->discovery_client = g_value_dup_object (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
+ break;
+ }
+}
+
+static gchar *
+salut_bonjour_contact_dup_jid (WockyContact *contact)
+{
+ SalutContact *self = SALUT_CONTACT (contact);
+
+ return g_strdup (self->name);
+}
+
+static GList *
+salut_bonjour_contact_ll_get_addresses (WockyLLContact *contact)
+{
+ SalutBonjourContact *self = SALUT_BONJOUR_CONTACT (contact);
+ SalutBonjourContactPrivate *priv = self->priv;
+ /* omg, GQueue! */
+ GQueue queue = G_QUEUE_INIT;
+ GSList *l;
+
+ for (l = priv->resolvers; l != NULL; l = l->next)
+ {
+ SalutBonjourResolveCtx *ctx = l->data;
+ uint16_t port;
+
+ if (ctx->address)
+ {
+ GInetAddress *addr;
+ GSocketAddress *socket_address;
+
+ if (ctx->address->sa_family == AF_INET)
+ {
+ struct sockaddr_in *address = (struct sockaddr_in *) ctx->address;
+
+ port = ctx->port;
+ addr = g_inet_address_new_from_bytes (
+ (guint8 *) &(address->sin_addr), G_SOCKET_FAMILY_IPV4);
+ }
+ else if (ctx->address->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *address = (struct sockaddr_in6 *) ctx->address;
+ port = ctx->port;
+ addr = g_inet_address_new_from_bytes (
+ (uint8_t *) &(address->sin6_addr), G_SOCKET_FAMILY_IPV6);
+ }
+ else
+ g_assert_not_reached ();
+
+ socket_address = g_inet_socket_address_new (addr, port);
+ g_object_unref (addr);
+
+ g_queue_push_tail (&queue, socket_address);
+ }
+ }
+
+ return queue.head;
+}
+
+static void
+_bonjour_add_address (SalutBonjourResolveCtx *ctx,
+ GArray *addresses)
+{
+ salut_contact_address_t s_address;
+ const struct sockaddr *address = ctx->address;
+
+ if (ctx->address)
+ {
+ if (address->sa_family == AF_INET)
+ {
+ struct sockaddr_in *_addr4 =
+ (struct sockaddr_in *) &s_address.address;
+ struct sockaddr_in *address4 = (struct sockaddr_in *) ctx->address;
+
+ _addr4->sin_family = AF_INET;
+ _addr4->sin_port = address4->sin_port;
+ _addr4->sin_addr.s_addr = address4->sin_addr.s_addr;
+ }
+ else if (address->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *_addr6 =
+ (struct sockaddr_in6 *) &s_address.address;
+ struct sockaddr_in6 *address6 = (struct sockaddr_in6 *) ctx->address;
+
+ _addr6->sin6_family = AF_INET6;
+ _addr6->sin6_port = address6->sin6_port;
+ _addr6->sin6_flowinfo = 0;
+ _addr6->sin6_scope_id = address6->sin6_scope_id;
+ memcpy (_addr6->sin6_addr.s6_addr, address6->sin6_addr.s6_addr, 16);
+ }
+ else
+ g_assert_not_reached ();
+
+ g_array_append_val (addresses, s_address);
+ }
+}
+
+static GArray *
+salut_bonjour_contact_get_addresses (SalutContact *self)
+{
+ SalutBonjourContact *_self = SALUT_BONJOUR_CONTACT (self);
+ SalutBonjourContactPrivate *priv = _self->priv;
+ GArray *addresses;
+
+ addresses =
+ g_array_sized_new (TRUE, TRUE, sizeof (salut_contact_address_t),
+ g_slist_length (priv->resolvers));
+ g_slist_foreach (priv->resolvers, (GFunc) _bonjour_add_address, addresses);
+
+ return addresses;
+}
+
+static gint
+_compare_sockaddr (SalutBonjourResolveCtx *ctx,
+ struct sockaddr *b)
+{
+ const struct sockaddr *a = ctx->address;
+
+ if (a->sa_family != b->sa_family)
+ return -1;
+
+ if (a->sa_family == AF_INET)
+ {
+ struct sockaddr_in *a4 = (struct sockaddr_in *) a;
+ struct sockaddr_in *b4 = (struct sockaddr_in *) b;
+
+ return a4->sin_addr.s_addr - b4->sin_addr.s_addr;
+ }
+ else if (a->sa_family == AF_INET6)
+ {
+ struct sockaddr_in6 *a6 = (struct sockaddr_in6 *) a;
+ struct sockaddr_in6 *b6 = (struct sockaddr_in6 *) b;
+
+ return memcmp (a6->sin6_addr.s6_addr, b6->sin6_addr.s6_addr, 16);
+ }
+ else
+ g_assert_not_reached ();
+
+ return 0;
+}
+
+static gint
+compare_resolver (SalutBonjourResolveCtx *a,
+ struct resolverInfo *b)
+{
+ gint result;
+
+ if (a->interface == b->interface
+ && !tp_strdiff (a->name, b->name)
+ && !tp_strdiff (a->type, b->type)
+ && !tp_strdiff (a->domain, b->domain))
+ {
+ result = 0;
+ }
+ else
+ {
+ result = 1;
+ }
+
+ return result;
+}
+
+static SalutBonjourResolveCtx *
+find_resolver (SalutBonjourContact *contact,
+ uint32_t interface,
+ const char *name,
+ const char *type,
+ const char *domain)
+{
+ SalutBonjourContactPrivate *priv = contact->priv;
+ struct resolverInfo info;
+ GSList *ret;
+ info.interface = interface;
+ info.name = name;
+ info.type = type;
+ info.domain = domain;
+
+ ret = g_slist_find_custom (priv->resolvers, &info,
+ (GCompareFunc) compare_resolver);
+
+ return ret ? (SalutBonjourResolveCtx *) ret->data : NULL;
+}
+
+static gboolean
+salut_bonjour_contact_has_address (SalutContact *contact,
+ struct sockaddr *address,
+ guint size)
+{
+ SalutBonjourContact *_self = SALUT_BONJOUR_CONTACT (contact);
+ SalutBonjourContactPrivate *priv = _self->priv;
+
+ return (g_slist_find_custom (priv->resolvers, address,
+ (GCompareFunc) _compare_sockaddr) != NULL);
+}
+
+static void salut_bonjour_contact_dispose (GObject *object);
+
+static void
+salut_bonjour_contact_class_init (
+ SalutBonjourContactClass *salut_bonjour_contact_class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (salut_bonjour_contact_class);
+ SalutContactClass *contact_class = SALUT_CONTACT_CLASS (
+ salut_bonjour_contact_class);
+ WockyContactClass *w_contact_class = WOCKY_CONTACT_CLASS (
+ salut_bonjour_contact_class);
+ WockyLLContactClass *ll_contact_class = WOCKY_LL_CONTACT_CLASS (
+ salut_bonjour_contact_class);
+ GParamSpec *param_spec;
+
+ g_type_class_add_private (salut_bonjour_contact_class,
+ sizeof (SalutBonjourContactPrivate));
+
+ object_class->get_property = salut_bonjour_contact_get_property;
+ object_class->set_property = salut_bonjour_contact_set_property;
+
+ object_class->dispose = salut_bonjour_contact_dispose;
+
+ contact_class->get_addresses = salut_bonjour_contact_get_addresses;
+ contact_class->has_address = salut_bonjour_contact_has_address;
+ contact_class->retrieve_avatar = NULL;
+
+ w_contact_class->dup_jid = salut_bonjour_contact_dup_jid;
+ ll_contact_class->get_addresses = salut_bonjour_contact_ll_get_addresses;
+
+ param_spec = g_param_spec_object (
+ "discovery-client",
+ "SalutBonjourDiscoveryClient object",
+ "The Salut Bonjour Discovery client associated with this muc manager",
+ SALUT_TYPE_BONJOUR_DISCOVERY_CLIENT,
+ G_PARAM_CONSTRUCT_ONLY |
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+ g_object_class_install_property (object_class, PROP_CLIENT,
+ param_spec);
+}
+
+void
+salut_bonjour_contact_dispose (GObject *object)
+{
+ SalutBonjourContact *self = SALUT_BONJOUR_CONTACT (object);
+ SalutBonjourContactPrivate *priv = self->priv;
+ GSList *l;
+
+ if (priv->dispose_has_run)
+ return;
+
+ priv->dispose_has_run = TRUE;
+
+ for (l = priv->resolvers; l != NULL; l = l->next)
+ {
+ SalutBonjourResolveCtx *ctx = l->data;
+
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ ctx->resolve_ref);
+ _salut_bonjour_resolve_ctx_free (self, ctx);
+ }
+
+ g_slist_free (priv->resolvers);
+ priv->resolvers = NULL;
+
+ if (priv->discovery_client != NULL)
+ {
+ g_object_unref (priv->discovery_client);
+ priv->discovery_client = NULL;
+ }
+
+ if (priv->full_name)
+ {
+ g_free (priv->full_name);
+ priv->full_name = NULL;
+ }
+
+ if (G_OBJECT_CLASS (salut_bonjour_contact_parent_class)->dispose)
+ G_OBJECT_CLASS (salut_bonjour_contact_parent_class)->dispose (object);
+}
+
+/* public functions */
+SalutBonjourContact *
+salut_bonjour_contact_new (SalutConnection *connection,
+ const gchar *name,
+ SalutBonjourDiscoveryClient *discovery_client)
+{
+ g_assert (connection != NULL);
+ g_assert (name != NULL);
+ g_assert (discovery_client != NULL);
+
+ return g_object_new (SALUT_TYPE_BONJOUR_CONTACT,
+ "connection", connection,
+ "name", name,
+ "discovery-client", discovery_client,
+ NULL);
+}
+
+static void
+update_alias (SalutBonjourContact *self,
+ const gchar *nick)
+{
+ SalutContact *contact = SALUT_CONTACT (self);
+
+ if (!tp_str_empty (nick))
+ {
+ salut_contact_change_alias (contact, nick);
+ return;
+ }
+
+ if (!tp_str_empty (contact->full_name))
+ {
+ salut_contact_change_alias (contact, contact->full_name);
+ return;
+ }
+
+ salut_contact_change_alias (contact, NULL);
+}
+
+static void DNSSD_API
+_bonjour_getaddr_cb (DNSServiceRef service_ref,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType error_type,
+ const char *host_name,
+ const struct sockaddr *address,
+ uint32_t ttl,
+ void *context)
+{
+ SalutBonjourResolveCtx *ctx = (SalutBonjourResolveCtx *) context;
+ SalutBonjourContact *self = SALUT_BONJOUR_CONTACT (ctx->contact);
+ SalutBonjourContactPrivate *priv = self->priv;
+ SalutContact *contact = SALUT_CONTACT (self);
+ const char *txt_record = ctx->txt_record;
+ uint32_t txt_length = ctx->txt_length;
+ char *status, *status_message, *nick, *first, *last;
+ char *node, *hash, *ver;
+ char *email, *jid;
+ char *tmp;
+ uint8_t txt_len;
+
+ if (error_type != kDNSServiceErr_NoError)
+ {
+ DEBUG ("Resolver failed with : (%d)", error_type);
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ ctx->address_ref);
+ ctx->address_ref = NULL;
+ g_free (ctx->txt_record);
+ ctx->txt_record = NULL;
+ return;
+ }
+
+ if (ctx->address)
+ {
+ g_free (ctx->address);
+ ctx->address = NULL;
+ }
+
+ if (address->sa_family == AF_INET)
+ ctx->address = g_memdup (address, sizeof (struct sockaddr_in));
+ else if (address->sa_family == AF_INET6)
+ ctx->address = g_memdup (address, sizeof (struct sockaddr_in6));
+ else
+ g_assert_not_reached ();
+
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ ctx->address_ref);
+ ctx->address_ref = NULL;
+
+ salut_contact_freeze (contact);
+
+ /* status */
+ tmp = (char *) TXTRecordGetValuePtr
+ (txt_length, txt_record, "status", &txt_len);
+ status = g_strndup (tmp, txt_len);
+
+ if (status != NULL)
+ {
+ for (int i = 0; i < SALUT_PRESENCE_NR_PRESENCES; i++)
+ {
+ if (tp_strdiff (status, salut_presence_status_txt_names[i]))
+ {
+ salut_contact_change_status (contact, i);
+ break;
+ }
+ }
+ free (status);
+ }
+
+ /* status message */
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "msg", &txt_len);
+ status_message = g_strndup (tmp, txt_len);
+ salut_contact_change_status_message (contact, status_message);
+ free (status_message);
+
+ /* real name and nick */
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "nick", &txt_len);
+ nick = g_strndup (tmp, txt_len);
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "1st", &txt_len);
+ first = g_strndup (tmp, txt_len);
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "last", &txt_len);
+ last = g_strndup (tmp, txt_len);
+
+ salut_contact_change_real_name (contact, first, last);
+ update_alias (self, nick);
+
+ free (nick);
+ free (first);
+ free (last);
+
+ /* capabilities */
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "hash", &txt_len);
+ hash = g_strndup (tmp, txt_len);
+
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "node", &txt_len);
+ node = g_strndup (tmp, txt_len);
+
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "ver", &txt_len);
+ ver = g_strndup (tmp, txt_len);
+
+ salut_contact_change_capabilities (contact, hash, node, ver);
+
+ free (hash);
+ free (node);
+ free (ver);
+
+ /* email */
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "email", &txt_len);
+ email = g_strndup (tmp, txt_len);
+ tmp = (char *) TXTRecordGetValuePtr (txt_length, txt_record,
+ "jid", &txt_len);
+ jid = g_strndup (tmp, txt_len);
+
+ salut_contact_change_email (contact, email);
+ salut_contact_change_jid (contact, jid);
+
+ free (email);
+ free (jid);
+
+ DEBUG ("Announce Contact Found");
+ salut_contact_found (contact);
+ salut_contact_thaw (contact);
+
+ g_free (ctx->txt_record);
+ ctx->txt_length = 0;
+ ctx->txt_record = NULL;
+}
+
+static void DNSSD_API
+_bonjour_service_resolve_cb (DNSServiceRef service_ref,
+ DNSServiceFlags flags,
+ uint32_t interfaceIndex,
+ DNSServiceErrorType error_type,
+ const char *full_name,
+ const char *host_target,
+ uint16_t port,
+ uint16_t txt_length,
+ const unsigned char *txt_record,
+ void *context)
+{
+ SalutBonjourResolveCtx *ctx = (SalutBonjourResolveCtx *) context;
+ SalutBonjourContact *self = SALUT_BONJOUR_CONTACT (ctx->contact);
+ SalutBonjourContactPrivate *priv = self->priv;
+ DNSServiceErrorType _error_type = kDNSServiceErr_NoError;
+
+ if (ctx->address_ref != NULL)
+ {
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ ctx->address_ref);
+ ctx->address_ref = NULL;
+ }
+
+ if (ctx->txt_record != NULL)
+ {
+ g_free (ctx->txt_record);
+ ctx->txt_record = NULL;
+ }
+
+ ctx->txt_record = g_strndup ((const gchar *) txt_record, (guint) txt_length);
+ ctx->txt_length = txt_length;
+ ctx->port = ntohs (port);
+
+ _error_type = DNSServiceGetAddrInfo (&ctx->address_ref, 0,
+ interfaceIndex, kDNSServiceProtocol_IPv4 | kDNSServiceProtocol_IPv6,
+ host_target, _bonjour_getaddr_cb, ctx);
+
+ if (_error_type != kDNSServiceErr_NoError)
+ {
+ DEBUG ("Address resolving failed with : (%d)", _error_type);
+ return;
+ }
+
+ salut_bonjour_discovery_client_watch_svc_ref (priv->discovery_client,
+ ctx->address_ref);
+}
+
+void
+salut_bonjour_contact_remove_service (SalutBonjourContact *self,
+ uint32_t interface,
+ const char *name,
+ const char *type,
+ const char *domain)
+{
+ SalutBonjourContactPrivate *priv = self->priv;
+ SalutBonjourResolveCtx *ctx = NULL;
+
+ ctx = find_resolver (self, interface, name, type, domain);
+
+ if (ctx == NULL)
+ return;
+
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ ctx->resolve_ref);
+
+ priv->resolvers = g_slist_remove (priv->resolvers, ctx);
+
+ _salut_bonjour_resolve_ctx_free (self, ctx);
+
+ if (priv->resolvers == NULL)
+ salut_contact_lost (SALUT_CONTACT (self));
+}
+
+gboolean
+salut_bonjour_contact_add_service (SalutBonjourContact *self,
+ uint32_t interface,
+ const char *name,
+ const char *type,
+ const char *domain)
+{
+ SalutBonjourContactPrivate *priv = self->priv;
+ DNSServiceErrorType error_type = kDNSServiceErr_NoError;
+ SalutBonjourResolveCtx *ctx = NULL;
+
+ ctx = find_resolver (self, interface, name, type, domain);
+ if (ctx != NULL)
+ return TRUE;
+
+ ctx = g_slice_new0 (SalutBonjourResolveCtx);
+ ctx->interface = interface;
+ ctx->name = g_strdup (name);
+ ctx->type = g_strdup (type);
+ ctx->domain = g_strdup (domain);
+ ctx->contact = self;
+ ctx->address = NULL;
+ ctx->txt_length = 0;
+ ctx->txt_record = NULL;
+ ctx->address_ref = NULL;
+
+ error_type = DNSServiceResolve (&ctx->resolve_ref,
+ 0, interface, name, type, domain, _bonjour_service_resolve_cb, ctx);
+
+ if (error_type != kDNSServiceErr_NoError)
+ {
+ DEBUG ("ServiceResolve failed with : (%d)", error_type);
+ _salut_bonjour_resolve_ctx_free (self, ctx);
+ return FALSE;
+ }
+
+ salut_bonjour_discovery_client_watch_svc_ref (priv->discovery_client,
+ ctx->resolve_ref);
+
+ priv->resolvers = g_slist_prepend (priv->resolvers, ctx);
+
+ return TRUE;
+}
+
+gboolean
+salut_bonjour_contact_has_services (SalutBonjourContact *self)
+{
+ SalutBonjourContactPrivate *priv = self->priv;
+
+ return priv->resolvers != NULL;
+}
diff --git a/src/bonjour-contact.h b/src/bonjour-contact.h
new file mode 100644
index 00000000..a60c0aa8
--- /dev/null
+++ b/src/bonjour-contact.h
@@ -0,0 +1,75 @@
+/*
+ * bonjour-contact.h - Header for SalutBonjourContact
+ * Copyright (C) 2012 Collabora Ltd.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifndef __SALUT_BONJOUR_CONTACT_H__
+#define __SALUT_BONJOUR_CONTACT_H__
+
+#include <glib-object.h>
+
+#include "contact.h"
+#include "bonjour-discovery-client.h"
+
+G_BEGIN_DECLS
+
+typedef struct _SalutBonjourContact SalutBonjourContact;
+typedef struct _SalutBonjourContactClass SalutBonjourContactClass;
+
+struct _SalutBonjourContactClass {
+ SalutContactClass parent_class;
+};
+
+struct _SalutBonjourContact {
+ SalutContact parent;
+
+ gpointer priv;
+};
+
+GType salut_bonjour_contact_get_type (void);
+
+/* TYPE MACROS */
+#define SALUT_TYPE_BONJOUR_CONTACT \
+ (salut_bonjour_contact_get_type ())
+#define SALUT_BONJOUR_CONTACT(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), SALUT_TYPE_BONJOUR_CONTACT, SalutBonjourContact))
+#define SALUT_BONJOUR_CONTACT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), SALUT_TYPE_BONJOUR_CONTACT, SalutBonjourContactClass))
+#define SALUT_IS_BONJOUR_CONTACT(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), SALUT_TYPE_BONJOUR_CONTACT))
+#define SALUT_IS_BONJOUR_CONTACT_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), SALUT_TYPE_BONJOUR_CONTACT))
+#define SALUT_BONJOUR_CONTACT_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS ((obj), SALUT_TYPE_BONJOUR_CONTACT, SalutBonjourContactClass))
+
+SalutBonjourContact *
+salut_bonjour_contact_new (SalutConnection *connection, const gchar *name,
+ SalutBonjourDiscoveryClient *discovery_client);
+
+gboolean salut_bonjour_contact_add_service (SalutBonjourContact *contact,
+ uint32_t interface, const char *name,
+ const char *type, const char *domain);
+
+void salut_bonjour_contact_remove_service (SalutBonjourContact *contact,
+ uint32_t interface, const char *name,
+ const char *type, const char *domain);
+
+gboolean salut_bonjour_contact_has_services (SalutBonjourContact *contact);
+
+G_END_DECLS
+
+#endif /* #ifndef __SALUT_BONJOUR_CONTACT_H__*/
diff --git a/src/bonjour-discovery-client.c b/src/bonjour-discovery-client.c
index fb69e0cd..fc9beaeb 100644
--- a/src/bonjour-discovery-client.c
+++ b/src/bonjour-discovery-client.c
@@ -66,6 +66,9 @@ struct _SalutBonjourDiscoveryClientPrivate
gchar *dnssd_name;
+ GHashTable *svc_ref_table;
+ GHashTable *svc_source_table;
+
gboolean dispose_has_run;
};
@@ -73,6 +76,10 @@ struct _SalutBonjourDiscoveryClientPrivate
((SalutBonjourDiscoveryClientPrivate *) \
((SalutBonjourDiscoveryClient *) obj)->priv)
+static void _destroy_source_id (gpointer ptr);
+static void _destroy_channel (gpointer ptr);
+static void _destroy_service (gpointer ptr);
+
static void
salut_bonjour_discovery_client_init (SalutBonjourDiscoveryClient *self)
{
@@ -81,6 +88,11 @@ salut_bonjour_discovery_client_init (SalutBonjourDiscoveryClient *self)
self->priv = priv;
priv->dispose_has_run = FALSE;
+ priv->svc_ref_table = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, _destroy_service, _destroy_channel);
+
+ priv->svc_source_table = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal, NULL, _destroy_source_id);
priv->state = SALUT_DISCOVERY_CLIENT_STATE_DISCONNECTED;
}
@@ -109,6 +121,12 @@ salut_bonjour_discovery_client_dispose (GObject *object)
if (priv->dispose_has_run)
return;
+ g_hash_table_remove_all (priv->svc_source_table);
+ g_hash_table_remove_all (priv->svc_ref_table);
+
+ g_hash_table_unref (priv->svc_source_table);
+ g_hash_table_unref (priv->svc_ref_table);
+
priv->dispose_has_run = TRUE;
tp_clear_pointer (&priv->dnssd_name, g_free);
@@ -254,6 +272,88 @@ salut_bonjour_discovery_client_get_host_name_fqdn (SalutDiscoveryClient *clt)
return NULL;
}
+static gboolean
+_bonjour_socket_process_cb (GIOChannel *source,
+ GIOCondition condition,
+ gpointer data)
+{
+ DNSServiceRef service_ref = data;
+ DNSServiceErrorType error_type = kDNSServiceErr_NoError;
+
+ error_type = DNSServiceProcessResult (service_ref);
+
+ if (error_type != kDNSServiceErr_NoError)
+ {
+ g_warning ("Socket Processing Failed with : (%d)", error_type);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+_destroy_service (gpointer service_ptr)
+{
+ DNSServiceRef service = service_ptr;
+
+ DNSServiceRefDeallocate (service);
+}
+
+static void
+_destroy_channel (gpointer channel_ptr)
+{
+ g_io_channel_unref (channel_ptr);
+}
+
+static void
+_destroy_source_id (gpointer source_id)
+{
+ if (!g_source_remove (GPOINTER_TO_UINT (source_id)))
+ {
+ g_warning ("Error removing source");
+ }
+}
+
+void
+salut_bonjour_discovery_client_watch_svc_ref (SalutBonjourDiscoveryClient *self,
+ DNSServiceRef service)
+{
+ SalutBonjourDiscoveryClientPrivate *priv =
+ SALUT_BONJOUR_DISCOVERY_CLIENT_GET_PRIVATE (self);
+ GIOChannel *channel = NULL;
+ guint source_id;
+
+
+ channel = g_io_channel_win32_new_socket (
+ DNSServiceRefSockFD ((service)));
+
+ source_id = g_io_add_watch (channel, G_IO_IN,
+ _bonjour_socket_process_cb, service);
+
+ g_hash_table_insert (priv->svc_ref_table, service, channel);
+ g_hash_table_insert (priv->svc_source_table, channel,
+ GUINT_TO_POINTER (source_id));
+}
+
+void
+salut_bonjour_discovery_client_drop_svc_ref (SalutBonjourDiscoveryClient *self,
+ DNSServiceRef service)
+{
+ SalutBonjourDiscoveryClientPrivate *priv =
+ SALUT_BONJOUR_DISCOVERY_CLIENT_GET_PRIVATE (self);
+ gpointer channel = NULL;
+
+ if (!g_hash_table_lookup_extended (
+ priv->svc_ref_table, service, NULL, &channel))
+ return;
+
+ if (!channel)
+ return;
+
+ g_hash_table_remove (priv->svc_source_table, channel);
+ g_hash_table_remove (priv->svc_ref_table, service);
+}
+
const gchar *
salut_bonjour_discovery_client_get_dnssd_name (SalutBonjourDiscoveryClient *clt)
{
diff --git a/src/bonjour-discovery-client.h b/src/bonjour-discovery-client.h
index afe3dd12..40798674 100644
--- a/src/bonjour-discovery-client.h
+++ b/src/bonjour-discovery-client.h
@@ -48,6 +48,14 @@ GType salut_bonjour_discovery_client_get_type (void);
const gchar * salut_bonjour_discovery_client_get_dnssd_name (
SalutBonjourDiscoveryClient *self);
+void salut_bonjour_discovery_client_watch_svc_ref (
+ SalutBonjourDiscoveryClient *self,
+ DNSServiceRef service);
+
+void salut_bonjour_discovery_client_drop_svc_ref (
+ SalutBonjourDiscoveryClient *self,
+ DNSServiceRef service);
+
/* TYPE MACROS */
#define SALUT_TYPE_BONJOUR_DISCOVERY_CLIENT \
(salut_bonjour_discovery_client_get_type ())
diff --git a/src/bonjour-self.c b/src/bonjour-self.c
index 856af022..518db17b 100644
--- a/src/bonjour-self.c
+++ b/src/bonjour-self.c
@@ -267,25 +267,6 @@ _bonjour_self_init_txt_record_presence (SalutBonjourSelf *self,
return kDNSServiceErr_NoError;
}
-static gboolean
-_bonjour_socket_process_cb (GIOChannel *source,
- GIOCondition condition,
- gpointer data)
-{
- DNSServiceRef service_ref = data;
- DNSServiceErrorType error_type = kDNSServiceErr_NoError;
-
- error_type = DNSServiceProcessResult (service_ref);
-
- if (error_type != kDNSServiceErr_NoError)
- {
- DEBUG ("Socket processing failed with : (%d)", error_type);
- return FALSE;
- }
-
- return TRUE;
-}
-
static void DNSSD_API
_bonjour_service_register_cb (DNSServiceRef service_ref,
DNSServiceFlags service_flags,
@@ -304,6 +285,8 @@ _bonjour_service_register_cb (DNSServiceRef service_ref,
if (!self || error_type != kDNSServiceErr_NoError)
{
DEBUG ("Service Registration Failed with : (%d)", error_type);
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ priv->bonjour_service);
}
else
{
@@ -324,9 +307,6 @@ _bonjour_service_register_cb (DNSServiceRef service_ref,
return;
}
- _self->name = g_strdup_printf ("%s@%s", _self->published_name,
- g_get_host_name ());
-
salut_self_established (_self);
}
}
@@ -339,7 +319,6 @@ salut_bonjour_self_announce (SalutSelf *_self,
SalutBonjourSelf *self = SALUT_BONJOUR_SELF (_self);
SalutBonjourSelfPrivate *priv = self->priv;
DNSServiceErrorType error_type = kDNSServiceErr_NoError;
- GIOChannel *bonjour_service_channel = NULL;
const gchar *dnssd_name;
dnssd_name =
@@ -351,17 +330,17 @@ salut_bonjour_self_announce (SalutSelf *_self,
RETURN_ERROR_IF_FAIL (error_type, error);
+ _self->name = g_strdup_printf ("%s@%s", _self->published_name,
+ g_get_host_name ());
+
error_type = DNSServiceRegister (&priv->bonjour_service,
- kDNSServiceInterfaceIndexAny, 0, NULL,
+ kDNSServiceInterfaceIndexAny, 0, _self->name,
dnssd_name, NULL, NULL,
htons (port), 0, NULL, _bonjour_service_register_cb, self);
RETURN_ERROR_IF_FAIL (error_type, error);
- bonjour_service_channel = g_io_channel_win32_new_socket (
- DNSServiceRefSockFD (priv->bonjour_service));
-
- g_io_add_watch (bonjour_service_channel, G_IO_IN, _bonjour_socket_process_cb,
+ salut_bonjour_discovery_client_watch_svc_ref (priv->discovery_client,
priv->bonjour_service);
return TRUE;
@@ -386,7 +365,8 @@ salut_bonjour_self_set_presence (SalutSelf *self,
error_type = TXTRecordSetValue (&priv->txt_record_presence, "msg",
strlen (self->status_message), self->status_message);
}
- else
+ else if ((TXTRecordContainsKey (TXTRecordGetLength (&priv->txt_record_presence),
+ &priv->txt_record_presence, "msg")) == TRUE)
{
error_type = TXTRecordRemoveValue (&priv->txt_record_presence, "msg");
}
@@ -565,6 +545,9 @@ salut_bonjour_self_dispose (GObject *object)
priv->dispose_has_run = TRUE;
+ salut_bonjour_discovery_client_drop_svc_ref (priv->discovery_client,
+ priv->bonjour_service);
+
if (priv->discovery_client != NULL)
{
g_object_unref (priv->discovery_client);