2 * ga-service-resolver.c - Source for GaServiceResolver
3 * Copyright (C) 2006-2007 Collabora Ltd.
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "ga-service-resolver.h"
28 #include "signals-marshal.h"
33 #include "ga-enums-enumtypes.h"
35 #include <avahi-client/lookup.h>
37 G_DEFINE_TYPE(GaServiceResolver, ga_service_resolver, G_TYPE_OBJECT)
46 static guint signals[LAST_SIGNAL] = { 0 };
59 /* private structure */
60 typedef struct _GaServiceResolverPrivate GaServiceResolverPrivate;
62 struct _GaServiceResolverPrivate {
64 AvahiServiceResolver *resolver;
65 AvahiIfIndex interface;
66 AvahiProtocol protocol;
72 AvahiProtocol aprotocol;
73 AvahiLookupFlags flags;
74 gboolean dispose_has_run;
77 #define GA_SERVICE_RESOLVER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GA_TYPE_SERVICE_RESOLVER, GaServiceResolverPrivate))
79 static void ga_service_resolver_init(GaServiceResolver * obj) {
80 GaServiceResolverPrivate *priv = GA_SERVICE_RESOLVER_GET_PRIVATE(obj);
82 /* allocate any data required by the object here */
84 priv->resolver = NULL;
91 static void ga_service_resolver_dispose(GObject * object);
92 static void ga_service_resolver_finalize(GObject * object);
94 static void ga_service_resolver_set_property(GObject * object,
96 const GValue * value, GParamSpec * pspec) {
97 GaServiceResolver *resolver = GA_SERVICE_RESOLVER(object);
98 GaServiceResolverPrivate *priv =
99 GA_SERVICE_RESOLVER_GET_PRIVATE(resolver);
101 g_assert(priv->resolver == NULL);
102 switch (property_id) {
104 priv->protocol = g_value_get_enum(value);
107 priv->aprotocol = g_value_get_enum(value);
110 priv->interface = g_value_get_int(value);
113 priv->name = g_strdup(g_value_get_string(value));
116 priv->type = g_strdup(g_value_get_string(value));
119 priv->domain = g_strdup(g_value_get_string(value));
122 priv->flags = g_value_get_enum(value);
125 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
130 static void ga_service_resolver_get_property(GObject * object,
132 GValue * value, GParamSpec * pspec) {
133 GaServiceResolver *resolver = GA_SERVICE_RESOLVER(object);
134 GaServiceResolverPrivate *priv =
135 GA_SERVICE_RESOLVER_GET_PRIVATE(resolver);
137 switch (property_id) {
139 g_value_set_enum(value, priv->aprotocol);
142 g_value_set_enum(value, priv->protocol);
145 g_value_set_int(value, priv->interface);
148 g_value_set_string(value, priv->name);
151 g_value_set_string(value, priv->type);
154 g_value_set_string(value, priv->domain);
157 g_value_set_enum(value, priv->flags);
160 G_OBJECT_WARN_INVALID_PROPERTY_ID(object, property_id, pspec);
166 static void ga_service_resolver_class_init(GaServiceResolverClass *
167 ga_service_resolver_class) {
168 GObjectClass *object_class = G_OBJECT_CLASS(ga_service_resolver_class);
169 GParamSpec *param_spec;
171 g_type_class_add_private(ga_service_resolver_class,
172 sizeof (GaServiceResolverPrivate));
174 object_class->set_property = ga_service_resolver_set_property;
175 object_class->get_property = ga_service_resolver_get_property;
177 object_class->dispose = ga_service_resolver_dispose;
178 object_class->finalize = ga_service_resolver_finalize;
181 g_signal_new("found",
182 G_OBJECT_CLASS_TYPE(ga_service_resolver_class),
186 _ga_signals_marshal_VOID__INT_ENUM_STRING_STRING_STRING_STRING_POINTER_INT_POINTER_INT,
196 G_TYPE_POINTER, GA_TYPE_LOOKUP_RESULT_FLAGS);
199 g_signal_new("failure",
200 G_OBJECT_CLASS_TYPE(ga_service_resolver_class),
204 g_cclosure_marshal_VOID__POINTER,
205 G_TYPE_NONE, 1, G_TYPE_POINTER);
207 param_spec = g_param_spec_enum("protocol", "Avahi protocol to resolve on",
208 "Avahi protocol to resolve on",
212 G_PARAM_STATIC_NAME |
213 G_PARAM_STATIC_BLURB);
214 g_object_class_install_property(object_class, PROP_PROTOCOL, param_spec);
216 param_spec = g_param_spec_enum("aprotocol", "Address protocol",
217 "Avahi protocol of the address to be resolved",
221 G_PARAM_STATIC_NAME |
222 G_PARAM_STATIC_BLURB);
223 g_object_class_install_property(object_class, PROP_APROTOCOL, param_spec);
225 param_spec = g_param_spec_int("interface", "interface index",
226 "Interface use for resolver",
231 G_PARAM_STATIC_NAME | G_PARAM_STATIC_BLURB);
232 g_object_class_install_property(object_class, PROP_IFINDEX, param_spec);
234 param_spec = g_param_spec_string("name", "service name",
238 G_PARAM_STATIC_NAME |
239 G_PARAM_STATIC_BLURB);
240 g_object_class_install_property(object_class, PROP_NAME, param_spec);
242 param_spec = g_param_spec_string("type", "service type",
243 "Service type to browse for",
246 G_PARAM_STATIC_NAME |
247 G_PARAM_STATIC_BLURB);
248 g_object_class_install_property(object_class, PROP_TYPE, param_spec);
250 param_spec = g_param_spec_string("domain", "service domain",
251 "Domain to browse in",
254 G_PARAM_STATIC_NAME |
255 G_PARAM_STATIC_BLURB);
256 g_object_class_install_property(object_class, PROP_DOMAIN, param_spec);
258 param_spec = g_param_spec_enum("flags", "Lookup flags for the resolver",
259 "Resolver lookup flags",
260 GA_TYPE_LOOKUP_FLAGS,
263 G_PARAM_STATIC_NAME |
264 G_PARAM_STATIC_BLURB);
265 g_object_class_install_property(object_class, PROP_FLAGS, param_spec);
268 void ga_service_resolver_dispose(GObject * object) {
269 GaServiceResolver *self = GA_SERVICE_RESOLVER(object);
270 GaServiceResolverPrivate *priv = GA_SERVICE_RESOLVER_GET_PRIVATE(self);
272 if (priv->dispose_has_run)
275 priv->dispose_has_run = TRUE;
278 g_object_unref(priv->client);
282 avahi_service_resolver_free(priv->resolver);
283 priv->resolver = NULL;
285 /* release any references held by the object here */
287 if (G_OBJECT_CLASS(ga_service_resolver_parent_class)->dispose)
288 G_OBJECT_CLASS(ga_service_resolver_parent_class)->dispose(object);
291 void ga_service_resolver_finalize(GObject * object) {
292 GaServiceResolver *self = GA_SERVICE_RESOLVER(object);
293 GaServiceResolverPrivate *priv = GA_SERVICE_RESOLVER_GET_PRIVATE(self);
295 /* free any data held directly by the object here */
302 g_free(priv->domain);
305 G_OBJECT_CLASS(ga_service_resolver_parent_class)->finalize(object);
308 static void _avahi_service_resolver_cb(AVAHI_GCC_UNUSED AvahiServiceResolver * resolver,
309 AvahiIfIndex interface,
310 AvahiProtocol protocol,
311 AvahiResolverEvent event,
312 const char *name, const char *type,
313 const char *domain, const char *host_name,
314 const AvahiAddress * a,
316 AvahiStringList * txt,
317 AvahiLookupResultFlags flags, void *userdata) {
318 GaServiceResolver *self = GA_SERVICE_RESOLVER(userdata);
319 GaServiceResolverPrivate *priv = GA_SERVICE_RESOLVER_GET_PRIVATE(self);
322 case AVAHI_RESOLVER_FOUND:{
323 /* FIXME: Double check if this address is always the same */
326 g_signal_emit(self, signals[FOUND], 0,
329 domain, host_name, a, port, txt, flags);
332 case AVAHI_RESOLVER_FAILURE:{
334 int aerrno = avahi_client_errno(priv->client->avahi_client);
335 error = g_error_new(GA_ERROR, aerrno,
336 "Resolving failed: %s",
337 avahi_strerror(aerrno));
338 g_signal_emit(self, signals[FAILURE], 0, error);
346 GaServiceResolver *ga_service_resolver_new(AvahiIfIndex interface,
347 AvahiProtocol protocol,
350 const gchar * domain,
351 AvahiProtocol address_protocol,
352 GaLookupFlags flags) {
353 return g_object_new(GA_TYPE_SERVICE_RESOLVER, "interface", interface,
354 "protocol", protocol, "name", name, "type", type,
355 "domain", domain, "aprotocol", address_protocol,
356 "flags", flags, NULL);
359 gboolean ga_service_resolver_attach(GaServiceResolver * resolver,
360 GaClient * client, GError ** error) {
361 GaServiceResolverPrivate *priv =
362 GA_SERVICE_RESOLVER_GET_PRIVATE(resolver);
364 g_assert(client != NULL);
365 g_object_ref(client);
367 priv->client = client;
369 priv->resolver = avahi_service_resolver_new(client->avahi_client,
373 priv->type, priv->domain,
376 _avahi_service_resolver_cb,
378 if (priv->resolver == NULL) {
380 int aerrno = avahi_client_errno(client->avahi_client);
381 *error = g_error_new(GA_ERROR, aerrno,
382 "Attaching group failed: %s",
383 avahi_strerror(aerrno));
385 /* printf("Failed to add resolver\n"); */
391 gboolean ga_service_resolver_get_address(GaServiceResolver * resolver,
392 AvahiAddress * address, uint16_t * port) {
393 GaServiceResolverPrivate *priv =
394 GA_SERVICE_RESOLVER_GET_PRIVATE(resolver);
395 if (priv->port == 0) {
396 /* printf("PORT == 0\n"); */
400 *address = priv->address;