2
* Remmina - The GTK+ Remote Desktop Client
3
* Copyright (C) 2009-2010 Vic Lee
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program 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
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330,
18
* Boston, MA 02111-1307, USA.
23
#include "remminaavahi.h"
25
#ifdef HAVE_LIBAVAHI_CLIENT
27
#include <avahi-client/client.h>
28
#include <avahi-client/lookup.h>
29
#include <avahi-common/simple-watch.h>
30
#include <avahi-common/malloc.h>
31
#include <avahi-common/error.h>
33
struct _RemminaAvahiPriv
35
AvahiSimplePoll *simple_poll;
37
AvahiServiceBrowser *sb;
38
guint iterate_handler;
43
remmina_avahi_resolve_callback (
44
AvahiServiceResolver *r,
45
AVAHI_GCC_UNUSED AvahiIfIndex interface,
46
AVAHI_GCC_UNUSED AvahiProtocol protocol,
47
AvahiResolverEvent event,
51
const char *host_name,
52
const AvahiAddress *address,
55
AvahiLookupResultFlags flags,
56
AVAHI_GCC_UNUSED void* userdata)
58
RemminaAvahi *ga = (RemminaAvahi*) userdata;
63
ga->priv->has_event = TRUE;
67
case AVAHI_RESOLVER_FAILURE:
68
g_print ("(remmina-applet avahi-resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n",
69
name, type, domain, avahi_strerror (avahi_client_errno (avahi_service_resolver_get_client (r))));
72
case AVAHI_RESOLVER_FOUND:
73
key = g_strdup_printf ("%s,%s,%s", name, type, domain);
74
if (g_hash_table_lookup (ga->discovered_services, key))
79
value = g_strdup_printf ("[%s]:%i", host_name, port);
80
g_hash_table_insert (ga->discovered_services, key, value);
81
/* key and value will be freed with g_free when the has table is freed */
83
g_print ("(remmina-applet avahi-resolver) Added service '%s'\n", value);
88
avahi_service_resolver_free (r);
92
remmina_avahi_browse_callback (
93
AvahiServiceBrowser *b,
94
AvahiIfIndex interface,
95
AvahiProtocol protocol,
96
AvahiBrowserEvent event,
100
AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
103
RemminaAvahi *ga = (RemminaAvahi*) userdata;
108
ga->priv->has_event = TRUE;
112
case AVAHI_BROWSER_FAILURE:
113
g_print ("(remmina-applet avahi-browser) %s\n",
114
avahi_strerror (avahi_client_errno (avahi_service_browser_get_client (b))));
117
case AVAHI_BROWSER_NEW:
118
key = g_strdup_printf ("%s,%s,%s", name, type, domain);
119
if (g_hash_table_lookup (ga->discovered_services, key))
126
g_print ("(remmina-applet avahi-browser) Found service '%s' of type '%s' in domain '%s'\n", name, type, domain);
128
if (!(avahi_service_resolver_new (ga->priv->client, interface, protocol, name, type, domain,
129
AVAHI_PROTO_UNSPEC, 0, remmina_avahi_resolve_callback, ga)))
131
g_print ("(remmina-applet avahi-browser) Failed to resolve service '%s': %s\n",
132
name, avahi_strerror (avahi_client_errno (ga->priv->client)));
137
case AVAHI_BROWSER_REMOVE:
138
g_print ("(remmina-applet avahi-browser) Removed service '%s' of type '%s' in domain '%s'\n", name, type, domain);
139
key = g_strdup_printf ("%s,%s,%s", name, type, domain);
140
g_hash_table_remove (ga->discovered_services, key);
144
case AVAHI_BROWSER_ALL_FOR_NOW:
145
case AVAHI_BROWSER_CACHE_EXHAUSTED:
151
remmina_avahi_client_callback (AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata)
153
RemminaAvahi *ga = (RemminaAvahi*) userdata;
155
ga->priv->has_event = TRUE;
157
if (state == AVAHI_CLIENT_FAILURE)
159
g_print ("(remmina-applet avahi) Server connection failure: %s\n", avahi_strerror (avahi_client_errno (c)));
164
remmina_avahi_iterate (RemminaAvahi *ga)
168
/* Call the iteration until no further events */
169
ga->priv->has_event = FALSE;
170
avahi_simple_poll_iterate (ga->priv->simple_poll, 0);
171
if (!ga->priv->has_event) break;
178
remmina_avahi_new (void)
182
ga = g_new (RemminaAvahi, 1);
183
ga->discovered_services = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
185
ga->priv = g_new (RemminaAvahiPriv, 1);
186
ga->priv->simple_poll = NULL;
187
ga->priv->client = NULL;
189
ga->priv->iterate_handler = 0;
190
ga->priv->has_event = FALSE;
196
remmina_avahi_start (RemminaAvahi* ga)
200
if (ga->started) return;
204
ga->priv->simple_poll = avahi_simple_poll_new ();
205
if (!ga->priv->simple_poll)
207
g_print ("Failed to create simple poll object.\n");
211
ga->priv->client = avahi_client_new (avahi_simple_poll_get (ga->priv->simple_poll), 0,
212
remmina_avahi_client_callback, ga, &error);
213
if (!ga->priv->client)
215
g_print ("Failed to create client: %s\n", avahi_strerror (error));
219
/* TODO: Customize the default domain here */
220
ga->priv->sb = avahi_service_browser_new (ga->priv->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
221
"_rfb._tcp", NULL, 0, remmina_avahi_browse_callback, ga);
224
g_print ("Failed to create service browser: %s\n", avahi_strerror (avahi_client_errno (ga->priv->client)));
228
ga->priv->iterate_handler = g_timeout_add (5000, (GSourceFunc) remmina_avahi_iterate, ga);
232
remmina_avahi_stop (RemminaAvahi* ga)
234
g_hash_table_remove_all (ga->discovered_services);
235
if (ga->priv->iterate_handler)
237
g_source_remove (ga->priv->iterate_handler);
238
ga->priv->iterate_handler = 0;
242
avahi_service_browser_free (ga->priv->sb);
245
if (ga->priv->client)
247
avahi_client_free (ga->priv->client);
248
ga->priv->client = NULL;
250
if (ga->priv->simple_poll)
252
avahi_simple_poll_free (ga->priv->simple_poll);
253
ga->priv->simple_poll = NULL;
259
remmina_avahi_free (RemminaAvahi* ga)
261
if (ga == NULL) return;
262
remmina_avahi_stop (ga);
264
g_hash_table_destroy (ga->discovered_services);
271
remmina_avahi_new (void)
277
remmina_avahi_start (RemminaAvahi* ga)
282
remmina_avahi_stop (RemminaAvahi* ga)
287
remmina_avahi_free (RemminaAvahi* ga)