Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
DISCONTINUED:openSUSE:11.1:Update
gnome-vfs2
gnome-vfs2-bonjour-support.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File gnome-vfs2-bonjour-support.patch of Package gnome-vfs2
Index: configure.in ================================================================================ --- configure.in +++ configure.in @@ -705,17 +705,67 @@ fi AC_ARG_ENABLE(howl, [ --disable-howl build without howl support]) -msg_howl=no +msg_zeroconf=no if test "x$msg_avahi" = "xno" -a "x$enable_howl" != "xno"; then PKG_CHECK_MODULES(HOWL, howl >= 0.9.6, [AM_CONDITIONAL(HAVE_HOWL, true) AC_DEFINE(HAVE_HOWL, [], [Set if we can use howl])] - msg_howl=yes, + msg_zeroconf=howl, [AM_CONDITIONAL(HAVE_HOWL, false)]) AC_SUBST(HOWL_CFLAGS) AC_SUBST(HOWL_LIBS) fi + dnl **************************** +dnl Bonjour +dnl **************************** + +AM_CONDITIONAL(HAVE_BONJOUR, false) +AC_ARG_ENABLE(bonjour, [ --enable-bonjour build with bonjour support]) +if test "x$enable_bonjour" = "xyes"; then + if test "x${HOWL_LIBS}" != "x"; then + AC_MSG_ERROR([*** Can't use both howl and bonjour at the same time. Please pick one only. ***]) + else + CPPFLAGS_save="$CPPFLAGS" + LDFLAGS_save="$LDFLAGS" + + AC_ARG_WITH(bonjour-includes, [ --with-bonjour-includes=PREFIX + Location of Bonjour includes.], + with_bonjour_includes="$withval", + with_bonjour_includes="/usr/include") + + CPPFLAGS="$CPPFLAGS -I$with_bonjour_includes" + AC_CHECK_HEADER(dns_sd.h, , AC_MSG_ERROR([Unable to find Bonjour includes])) + CPPFLAGS="$CPPFLAGS_save" + + if test x$with_bonjour_includes != x/usr/include; then + BONJOUR_CFLAGS="-I$with_bonjour_includes" + else + BONJOUR_CFLAGS="" + fi + + AC_ARG_WITH(bonjour-libs, [ --with-bonjour-libs=PREFIX + Location of Bonjour libs.], + with_bonjour_libs="$withval", with_bonjour_libs="/usr/lib") + + LDFLAGS="$LDFLAGS -L$with_bonjour_libs -ldns_sd" + AC_TRY_LINK_FUNC(DNSServiceResolve, , AC_MSG_ERROR([Unable to find Bonjour libs])) + LDFLAGS="$LDFLAGS_save" + + if test x$with_bonjour_libs != x/usr/lib; then + BONJOUR_LIBS="-L$with_bonjour_libs -ldns_sd" + else + BONJOUR_LIBS="-ldns_sd" + fi + + msg_zeroconf="bonjour" + AM_CONDITIONAL(HAVE_BONJOUR, true) + AC_DEFINE(HAVE_BONJOUR, 1, [Define to 1 if Bonjour is available and desired]) + AC_SUBST(BONJOUR_CFLAGS) + AC_SUBST(BONJOUR_LIBS) + fi +fi + dnl **************************** dnl HAL stuff dnl **************************** @@ -1019,8 +1069,8 @@ dnl ============================================================================== PKG_CHECK_MODULES(LIBGNOMEVFS, glib-2.0 >= $GLIB_REQUIRED gmodule-no-export-2.0 >= $GLIB_REQUIRED gthread-2.0 >= $GLIB_REQUIRED gobject-2.0 >= $GLIB_REQUIRED gconf-2.0 >= $GCONF_REQUIRED libxml-2.0 >= $XML_REQUIRED gnome-mime-data-2.0 dbus-glib-1 >= 0.60) -LIBGNOMEVFS_CFLAGS="$LIBGNOMEVFS_CFLAGS $OPENSSL_CFLAGS $LIBGNUTLS_CFLAGS $HOWL_CFLAGS $AVAHI_CFLAGS" -LIBGNOMEVFS_LIBS="$LIBGNOMEVFS_LIBS $OPENSSL_LIBS $LIBGNUTLS_LIBS $HOWL_LIBS $AVAHI_LIBS $RESOLVER_LIBS" +LIBGNOMEVFS_CFLAGS="$LIBGNOMEVFS_CFLAGS $OPENSSL_CFLAGS $LIBGNUTLS_CFLAGS $HOWL_CFLAGS $BONJOUR_CFLAGS $AVAHI_CFLAGS" +LIBGNOMEVFS_LIBS="$LIBGNOMEVFS_LIBS $OPENSSL_LIBS $LIBGNUTLS_LIBS $HOWL_LIBS $BONJOUR_LIBS $AVAHI_LIBS $RESOLVER_LIBS" AC_SUBST(LIBGNOMEVFS_CFLAGS) AC_SUBST(LIBGNOMEVFS_LIBS) @@ -1327,7 +1377,7 @@ IPv6 support: $have_ipv6 SSL support: $msg_ssl Avahi support: $msg_avahi - Howl support: $msg_howl + Zeroconf support: $msg_zeroconf HAL support: $msg_hal SELinux support: $msg_selinux File ACL backends: $acl_backends --- libgnomevfs/gnome-vfs-dns-sd.c +++ libgnomevfs/gnome-vfs-dns-sd.c @@ -52,6 +52,11 @@ #include <howl.h> #endif +/* Only one of HAVE_HOWL and HAVE_BONJOUR can be defined */ +#ifdef HAVE_BONJOUR +# include <dns_sd.h> +#endif + #define PATH_GCONF_GNOME_VFS_DNS_SD "/system/dns_sd" #define PATH_GCONF_GNOME_VFS_DNS_SD_EXTRA_DOMAINS "/system/dns_sd/extra_domains" @@ -839,6 +844,40 @@ #endif /* HAVE_HOWL */ +#ifdef HAVE_BONJOUR + +static gboolean +bonjour_input (GIOChannel *io_channel, + GIOCondition cond, + gpointer callback_data) +{ + DNSServiceRef session; + + session = callback_data; + DNSServiceProcessResult (session); + + return TRUE; +} + +static guint +set_up_bonjour_session (DNSServiceRef session) +{ + int fd; + GIOChannel *channel; + guint watch_id; + + fd = DNSServiceRefSockFD (session); + + channel = g_io_channel_unix_new (fd); + watch_id = g_io_add_watch (channel, + G_IO_IN, + bonjour_input, session); + g_io_channel_unref (channel); + return watch_id; +} + +#endif /* HAVE_BONJOUR */ + struct GnomeVFSDNSSDBrowseHandle { char *domain; char *type; @@ -858,6 +897,12 @@ #ifdef HAVE_HOWL sw_discovery_oid howl_id; #endif + +#ifdef HAVE_BONJOUR + gboolean is_bonjour; + DNSServiceRef bonjour_session; + guint bonjour_input_id; +#endif /* unicast data: */ int n_services; @@ -885,6 +930,14 @@ if (handle->callback_data_destroy_func != NULL) handle->callback_data_destroy_func (handle->callback_data); + +#ifdef HAVE_BONJOUR + if (handle->is_bonjour) { + if (handle->bonjour_input_id != 0) + g_source_remove (handle->bonjour_input_id); + DNSServiceRefDeallocate (handle->bonjour_session); + } +#endif g_free (handle); } @@ -966,9 +1019,9 @@ } #endif -#ifdef HAVE_HOWL +#if defined (HAVE_HOWL) || defined (HAVE_BONJOUR) -struct howl_browse_idle_data { +struct zc_browse_idle_data { GnomeVFSDNSSDBrowseHandle *handle; GnomeVFSDNSSDServiceStatus status; GnomeVFSDNSSDService service; @@ -977,9 +1030,9 @@ static gboolean -howl_browse_idle (gpointer data) +zc_browse_idle (gpointer data) { - struct howl_browse_idle_data *idle_data; + struct zc_browse_idle_data *idle_data; GnomeVFSDNSSDBrowseHandle *handle; idle_data = data; @@ -997,7 +1050,7 @@ } static void -browse_idle_data_free (struct howl_browse_idle_data *idle_data) +browse_idle_data_free (struct zc_browse_idle_data *idle_data) { g_free (idle_data->service.name); g_free (idle_data->service.type); @@ -1012,6 +1065,10 @@ return FALSE; } +#endif + +#ifdef HAVE_HOWL + static sw_result howl_browse_reply (sw_discovery discovery, sw_discovery_oid oid, @@ -1023,7 +1080,7 @@ sw_opaque extra) { GnomeVFSDNSSDBrowseHandle *handle; - struct howl_browse_idle_data *idle_data; + struct zc_browse_idle_data *idle_data; int len; handle = extra; @@ -1038,7 +1095,7 @@ if (handle->cancelled) return SW_OKAY; - idle_data = g_new (struct howl_browse_idle_data, 1); + idle_data = g_new (struct zc_browse_idle_data, 1); idle_data->handle = handle; if (status == SW_DISCOVERY_BROWSE_ADD_SERVICE) { @@ -1064,7 +1121,7 @@ idle_data->service.domain[len-1] = 0; g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - howl_browse_idle, + zc_browse_idle, idle_data, (GDestroyNotify) browse_idle_data_free); return SW_OKAY; @@ -1072,6 +1129,63 @@ #endif /* HAVE_HOWL */ +#ifdef HAVE_BONJOUR + +static void +bonjour_browse_reply (DNSServiceRef session, + DNSServiceFlags flags, + uint32_t interface_index, + DNSServiceErrorType error_code, + const char *name, + const char *type, + const char *domain, + void *context) +{ + GnomeVFSDNSSDBrowseHandle *handle; + struct zc_browse_idle_data *idle_data; + int len; + + handle = context; + + if (error_code != kDNSServiceErr_NoError) { + /* free in an idle to make sure the other idles are done, + and to give sane environment for destroy callback */ + g_idle_add (free_browse_handle_idle, handle); + return; + } + + if (handle->cancelled) + return; + + idle_data = g_new (struct zc_browse_idle_data, 1); + idle_data->handle = handle; + + if (flags & kDNSServiceFlagsAdd) { + idle_data->status = GNOME_VFS_DNS_SD_SERVICE_ADDED; + } else { + idle_data->status = GNOME_VFS_DNS_SD_SERVICE_REMOVED; + } + + idle_data->service.name = g_strdup (name); + idle_data->service.type = g_strdup (type); + idle_data->service.domain = g_strdup (domain); + + /* We don't want last dots in the domain or type */ + len = strlen (idle_data->service.type); + if (len > 0 && idle_data->service.type[len-1] == '.') + idle_data->service.type[len-1] = 0; + len = strlen (idle_data->service.domain); + if (len > 0 && idle_data->service.domain[len-1] == '.') + idle_data->service.domain[len-1] = 0; + + g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + zc_browse_idle, + idle_data, + (GDestroyNotify) browse_idle_data_free); +} + +#endif /* HAVE_BONJOUR */ + /** * gnome_vfs_dns_sd_browse: * @handle: pointer to a pointer to a #GnomeVFSDNSSDBrowseHandle object. @@ -1154,8 +1268,32 @@ } return GNOME_VFS_ERROR_GENERIC; #else +# ifdef HAVE_BONJOUR + DNSServiceErrorType res; + + handle->is_local = TRUE; + handle->is_bonjour = TRUE; + + res = DNSServiceBrowse (&handle->bonjour_session, + 0 /* flags (none needed) */, + 0 /* interface (-1 for local, 0 for all) */, + type, + domain, + bonjour_browse_reply, + handle); + + if (res != kDNSServiceErr_NoError) { + return GNOME_VFS_ERROR_GENERIC; + } + + handle->bonjour_input_id = set_up_bonjour_session (handle->bonjour_session); + + *handle_out = handle; + return GNOME_VFS_OK; +# else free_browse_handle (handle); return GNOME_VFS_ERROR_NOT_SUPPORTED; +# endif #endif } else { handle->is_local = FALSE; @@ -1192,6 +1330,12 @@ handle->cancelled = TRUE; sw_discovery_cancel (get_global_howl_session (), handle->howl_id); #endif +#ifdef HAVE_BONJOUR + handle->cancelled = TRUE; + g_source_remove (handle->bonjour_input_id); + handle->bonjour_input_id = 0; + g_idle_add (free_browse_handle_idle, handle); +#endif return GNOME_VFS_OK; } else { if (handle->finished) @@ -1226,6 +1370,12 @@ sw_discovery_oid howl_id; guint timeout_tag; #endif +#ifdef HAVE_BONJOUR + gboolean is_bonjour; + DNSServiceRef bonjour_session; + guint bonjour_input_id; + guint timeout_tag; +#endif /* unicast data: */ gboolean cancelled; @@ -1246,7 +1396,15 @@ if (handle->callback_data_destroy_func != NULL) handle->callback_data_destroy_func (handle->callback_data); - + +#ifdef HAVE_BONJOUR + if (handle->is_bonjour) { + if (handle->bonjour_input_id != 0) + g_source_remove (handle->bonjour_input_id); + DNSServiceRefDeallocate (handle->bonjour_session); + } +#endif + g_free (handle); } @@ -1368,10 +1526,10 @@ #endif +#if defined (HAVE_HOWL) || defined (HAVE_BONJOUR) -#ifdef HAVE_HOWL static gboolean -howl_resolve_idle (gpointer data) +zc_resolve_idle (gpointer data) { GnomeVFSDNSSDResolveHandle *handle; GnomeVFSDNSSDService service; @@ -1405,7 +1563,9 @@ return FALSE; } +#endif +#ifdef HAVE_HOWL static sw_result howl_resolve_reply (sw_discovery discovery, @@ -1438,7 +1598,7 @@ g_source_remove (handle->timeout_tag); handle->idle_tag = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, - howl_resolve_idle, + zc_resolve_idle, handle, (GDestroyNotify) NULL); return SW_OKAY; @@ -1476,6 +1636,98 @@ #endif +#ifdef HAVE_BONJOUR + +static void +bonjour_resolve_reply (DNSServiceRef session, + DNSServiceFlags flags, + uint32_t interface_index, + DNSServiceErrorType error_code, + const char *full_name, + const char *host_name, + uint16_t port, + uint16_t text_record_len, + const char *text_record, + void *context) +{ + GnomeVFSDNSSDResolveHandle *handle; + gint host_len, domain_len; + + handle = context; + + g_assert (handle->idle_tag == 0); + + handle->host = g_strdup (host_name); + handle->port = g_ntohs (port); + handle->text = g_memdup (text_record, text_record_len); + handle->text_len = text_record_len; + + domain_len = strlen (handle->domain); + host_len = strlen (handle->host); + + /* The hostname includes the .local domain and a trailing dot. Strip it. */ + + /* hostname.[domain.] */ + if (host_len > domain_len && !strcmp (handle->host + host_len - domain_len, handle->domain) && + handle->host [host_len - domain_len - 1] == '.') { + handle->host [host_len - domain_len - 1] = 0; + host_len -= domain_len - 1; + } else if (host_len > 0 && handle->host [host_len - 1] == '.') { + handle->host [host_len - 1] = 0; + host_len--; + + /* hostname.[domain] */ + if (host_len > domain_len && !strcmp (handle->host + host_len - domain_len, handle->domain) && + handle->host [host_len - domain_len - 1] == '.') { + handle->host [host_len - domain_len - 1] = 0; + host_len -= domain_len - 1; + } + } + + /* We want no more replies */ + if (handle->is_bonjour) { + if (handle->bonjour_input_id != 0) { + g_source_remove (handle->bonjour_input_id); + handle->bonjour_input_id = 0; + } + DNSServiceRefDeallocate (handle->bonjour_session); + handle->is_bonjour = FALSE; + } + + g_source_remove (handle->timeout_tag); + + handle->idle_tag = g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, + zc_resolve_idle, + handle, + (GDestroyNotify) NULL); +} + +static gboolean +bonjour_resolve_timeout (gpointer data) +{ + GnomeVFSDNSSDResolveHandle *handle; + + handle = data; + + handle->callback (handle, + GNOME_VFS_ERROR_HOST_NOT_FOUND, + NULL, + NULL, 0, + NULL, 0, NULL, + handle->callback_data); + + if (handle->idle_tag) { + /* We already resolved, but the idle hasn't run yet */ + g_source_remove (handle->idle_tag); + } + + free_resolve_handle (handle); + + return FALSE; +} + +#endif /* HAVE_BONJOUR */ + /** * gnome_vfs_dns_sd_resolve: * @handle: pointer to a pointer to a #GnomeVFSDNSSDResolveHandle object. @@ -1569,7 +1821,38 @@ } return GNOME_VFS_ERROR_GENERIC; #else +# ifdef HAVE_BONJOUR + DNSServiceErrorType res; + + handle->is_local = TRUE; + handle->is_bonjour = TRUE; + + res = DNSServiceResolve (&handle->bonjour_session, + 0 /* flags (none needed) */, + 0 /* interface (-1 for local, 0 for all) */, + name, + type, + domain, + bonjour_resolve_reply, + handle); + + if (res != kDNSServiceErr_NoError) { + return GNOME_VFS_ERROR_GENERIC; + } + + handle->bonjour_input_id = set_up_bonjour_session (handle->bonjour_session); + + if (timeout != 0) { + handle->timeout_tag = g_timeout_add (timeout, + bonjour_resolve_timeout, + handle); + } + + *handle_out = handle; + return GNOME_VFS_OK; +# else return GNOME_VFS_ERROR_NOT_SUPPORTED; +# endif #endif } else { handle->is_local = FALSE; @@ -1614,7 +1897,14 @@ handle->howl_id); } free_resolve_handle (handle); - +#endif +#ifdef HAVE_BONJOUR + g_source_remove (handle->timeout_tag); + if (handle->idle_tag) { + /* We already resolved, but the idle hasn't run yet */ + g_source_remove (handle->idle_tag); + } + free_resolve_handle (handle); #endif return GNOME_VFS_OK; } else { @@ -1623,7 +1913,7 @@ } } -#if defined(HAVE_AVAHI) || defined(HAVE_HOWL) +#if defined(HAVE_AVAHI) || defined(HAVE_HOWL) || defined (HAVE_BONJOUR) static int find_existing_service (GArray *array, const char *name, @@ -1794,6 +2084,115 @@ } #endif /* HAVE_HOWL */ +#ifdef HAVE_BONJOUR + +static void +bonjour_run_sync (DNSServiceRef session, gint timeout_msec, gboolean *stop_processing_flag) +{ + struct timeval duration_tv, end_tv, tv; + + gettimeofday (&end_tv, NULL); + tv = end_tv; + + end_tv.tv_sec += timeout_msec / 1000; + end_tv.tv_usec += (timeout_msec % 1000) * 1000; + end_tv.tv_sec += end_tv.tv_usec / 1000000; + end_tv.tv_usec %= 1000000; + + while ((end_tv.tv_sec > tv.tv_sec || + (end_tv.tv_sec == tv.tv_sec && end_tv.tv_usec > tv.tv_usec)) && + !(stop_processing_flag && *stop_processing_flag)) { + gint n_ready; + fd_set read_fds; + gint fd; + + + duration_tv.tv_sec = end_tv.tv_sec - tv.tv_sec; + if (tv.tv_usec <= end_tv.tv_usec) { + duration_tv.tv_usec = end_tv.tv_usec - tv.tv_usec; + } else { + duration_tv.tv_sec--; + duration_tv.tv_usec = end_tv.tv_usec + 1000000 - tv.tv_usec; + } + + fd = DNSServiceRefSockFD (session); + if (fd < 0) + break; + + FD_ZERO (&read_fds); + FD_SET (fd, &read_fds); + + n_ready = select (fd + 1, &read_fds, NULL, NULL, &duration_tv); + gettimeofday (&tv, NULL); + + if (n_ready < 1) + continue; + + DNSServiceProcessResult (session); + } +} + +static void +bonjour_browse_reply_sync (DNSServiceRef session, + DNSServiceFlags flags, + uint32_t interface_index, + DNSServiceErrorType error_code, + const char *name, + const char *type, + const char *domain, + void *context) +{ + GnomeVFSDNSSDService service, *existing; + GArray *array; + int i, len; + gboolean free_service; + + array = context; + if (error_code != kDNSServiceErr_NoError) + return; + + free_service = TRUE; + service.name = g_strdup (name); + service.type = g_strdup (type); + service.domain = g_strdup (domain); + + /* We don't want last dots in the domain or type */ + len = strlen (service.type); + if (len > 0 && service.type[len-1] == '.') + service.type[len-1] = 0; + len = strlen (service.domain); + if (len > 0 && service.domain[len-1] == '.') + service.domain[len-1] = 0; + + if (flags & kDNSServiceFlagsAdd) { + if (find_existing_service (array, service.name, service.type, + service.domain) == -1) { + free_service = FALSE; + g_array_append_val (array, service); + } + } else { + i = find_existing_service (array, service.name, service.type, + service.domain); + if (i != -1) { + existing = &g_array_index (array, GnomeVFSDNSSDService, + i); + g_free (existing->name); + g_free (existing->type); + g_free (existing->domain); + g_array_remove_index (array, i); + } + } + + if (free_service) { + g_free (service.name); + g_free (service.type); + g_free (service.domain); + } +} + +#endif /* HAVE_BONJOUR */ + + /** * gnome_vfs_dns_sd_browse_sync: * @domain: The dns domain to browse, or "local" for multicast DNS. @@ -1946,7 +2345,32 @@ return GNOME_VFS_OK; #else +# ifdef HAVE_BONJOUR + DNSServiceRef session; + DNSServiceErrorType error_code; + GArray *array; + + array = g_array_new (FALSE, FALSE, sizeof (GnomeVFSDNSSDService)); + error_code = DNSServiceBrowse (&session, + 0 /* flags (none needed) */, + 0 /* interface (-1 for local, 0 for all) */, + type, + domain, + bonjour_browse_reply_sync, + array); + if (error_code != kDNSServiceErr_NoError) { + g_warning ("gnome_vfs_dns_sd_browse_sync - bonjour browse failed\n"); + g_array_free (array, TRUE); + return GNOME_VFS_ERROR_GENERIC; + } + + bonjour_run_sync (session, timeout_msec, NULL); + + DNSServiceRefDeallocate (session); + return GNOME_VFS_OK; +# else return GNOME_VFS_ERROR_NOT_SUPPORTED; +# endif #endif } else { return unicast_browse_sync (domain, type, @@ -2012,14 +2436,18 @@ #endif -#ifdef HAVE_HOWL +#if defined HAVE_HOWL || defined (HAVE_BONJOUR) struct sync_resolve_data { gboolean got_data; + const char *domain; char *host; int port; char *text; int text_len; }; +#endif + +#ifdef HAVE_HOWL static sw_result howl_resolve_reply_sync (sw_discovery discovery, @@ -2048,6 +2476,55 @@ } #endif +#ifdef HAVE_BONJOUR + +static void +bonjour_resolve_reply_sync (DNSServiceRef session, + DNSServiceFlags flags, + uint32_t interface_index, + DNSServiceErrorType error_code, + const char *full_name, + const char *host_name, + uint16_t port, + uint16_t text_record_len, + const char *text_record, + void *context) +{ + struct sync_resolve_data *data; + gint host_len, domain_len; + + data = context; + data->got_data = TRUE; + + data->host = g_strdup (host_name); + data->port = g_ntohs (port); + data->text = g_memdup (text_record, text_record_len); + data->text_len = text_record_len; + + domain_len = strlen (data->domain); + host_len = strlen (data->host); + + /* The hostname includes the .local domain and a trailing dot. Strip it. */ + /* hostname.[domain.] */ + if (host_len > domain_len && !strcmp (data->host + host_len - domain_len, data->domain) && + data->host [host_len - domain_len - 1] == '.') { + data->host [host_len - domain_len - 1] = 0; + host_len -= domain_len - 1; + } else if (host_len > 0 && data->host [host_len - 1] == '.') { + data->host [host_len - 1] = 0; + host_len--; + + /* hostname.[domain] */ + if (host_len > domain_len && !strcmp (data->host + host_len - domain_len, data->domain) && + data->host [host_len - domain_len - 1] == '.') { + data->host [host_len - domain_len - 1] = 0; + host_len -= domain_len - 1; + } + } +} + +#endif /* HAVE_BONJOUR */ + /** * gnome_vfs_dns_sd_resolve_sync: * @name: name of the service to resolve in UTF-8 encoding. @@ -2211,7 +2688,49 @@ return GNOME_VFS_ERROR_HOST_NOT_FOUND; #else +# ifdef HAVE_BONJOUR + DNSServiceRef session; + DNSServiceErrorType error_code; + struct sync_resolve_data resolve_data = {0}; + + resolve_data.domain = domain; + + error_code = DNSServiceResolve (&session, + 0 /* flags (none needed) */, + 0 /* interface (-1 for local, 0 + for all) */, + name, + type, + domain, + bonjour_resolve_reply_sync, + &resolve_data); + if (error_code != kDNSServiceErr_NoError) { + g_warning ("gnome_vfs_dns_sd_resolve_sync - bonjour resolve failed\n"); + return GNOME_VFS_ERROR_GENERIC; + } + + bonjour_run_sync (session, timeout_msec, &resolve_data.got_data); + + DNSServiceRefDeallocate (session); + + if (resolve_data.got_data) { + *host = resolve_data.host; + *port = resolve_data.port; + if (text != NULL) + *text = decode_txt_record (resolve_data.text, resolve_data.text_len); + if (text_raw_len_out != NULL && text_raw_out) { + *text_raw_len_out = resolve_data.text_len; + *text_raw_out = resolve_data.text; + } else { + g_free (resolve_data.text); + } + return GNOME_VFS_OK; + } + + return GNOME_VFS_ERROR_HOST_NOT_FOUND; +# else return GNOME_VFS_ERROR_NOT_SUPPORTED; +# endif #endif } else { res = unicast_resolve_sync (name, type, domain, --- modules/Makefile.am +++ modules/Makefile.am @@ -7,6 +7,7 @@ $(MODULES_XML_GCONF_CFLAGS) \ $(MODULES_FILE_CFLAGS) \ $(HOWL_CFLAGS) \ + $(BONJOUR_CFLAGS) \ $(AVAHI_CFLAGS) \ $(LIBEFS_CFLAGS) \ $(SAMBA_CFLAGS) \ @@ -115,7 +116,7 @@ libdns_sd_la_SOURCES = dns-sd-method.c libdns_sd_la_LDFLAGS = $(module_flags) -libdns_sd_la_LIBADD = $(MODULES_LIBS) $(HOWL_LIBS) $(AVAHI_LIBS) ../libgnomevfs/libgnomevfs-2.la +libdns_sd_la_LIBADD = $(MODULES_LIBS) $(HOWL_LIBS) $(BONJOUR_LIBS) $(AVAHI_LIBS) ../libgnomevfs/libgnomevfs-2.la ### `file' method --- modules/dns-sd-method.c +++ modules/dns-sd-method.c @@ -45,6 +45,11 @@ #include <howl.h> #endif +/* Only one of HAVE_HOWL and HAVE_BONJOUR can be defined */ +#ifdef HAVE_BONJOUR +# include <dns_sd.h> +#endif + #include <libgnomevfs/gnome-vfs-ops.h> #include <libgnomevfs/gnome-vfs-directory.h> #include <libgnomevfs/gnome-vfs-module-shared.h> @@ -71,12 +76,12 @@ {"_sftp-ssh._tcp", "sftp", "gnome-fs-ssh"}, }; -#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) +#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) || defined (HAVE_BONJOUR) G_LOCK_DEFINE_STATIC (local); static gboolean started_local = FALSE; static GList *local_files = NULL; static GList *local_monitors = NULL; -#endif /* HAVE_HOWL || HAVE_AVAHI */ +#endif /* HAVE_HOWL || HAVE_AVAHI || HAVE_BONJOUR*/ typedef struct { char *data; @@ -226,7 +231,7 @@ return g_string_free (string, FALSE); } -#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) +#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) || defined (HAVE_BONJOUR) static void call_monitors (gboolean add, char *filename) { @@ -312,7 +317,7 @@ G_UNLOCK (local); } -#endif /* HAVE_HOWL || HAVE_AVAHI */ +#endif /* HAVE_HOWL || HAVE_AVAHI || HAVE_BONJOUR*/ #ifdef HAVE_AVAHI @@ -535,10 +540,130 @@ sw_discovery_fina (session); } } + #endif /* HAVE_HOWL */ +#ifdef HAVE_BONJOUR + +static void +local_browse_callback_sync (DNSServiceRef session, + DNSServiceFlags flags, + uint32_t interface_index, + DNSServiceErrorType error_code, + const char *name, + const char *type, + const char *domain, + void *context) +{ + if (flags & kDNSServiceFlagsAdd) + local_browse (TRUE, name, type, domain); + else + local_browse (FALSE, name, type, domain); +} + +static void +bonjour_run_multi_sync (DNSServiceRef *session_handles, gint n_sessions, gint timeout_msec) +{ + struct timeval duration_tv, end_tv, tv; + + gettimeofday (&end_tv, NULL); + tv = end_tv; + + end_tv.tv_sec += timeout_msec / 1000; + end_tv.tv_usec += (timeout_msec % 1000) * 1000; + end_tv.tv_sec += end_tv.tv_usec / 1000000; + end_tv.tv_usec %= 1000000; + + while (end_tv.tv_sec > tv.tv_sec || + (end_tv.tv_sec == tv.tv_sec && end_tv.tv_usec > tv.tv_usec)) { + gint n_ready; + fd_set read_fds; + gint high_fd = 0; + gint i; + + duration_tv.tv_sec = end_tv.tv_sec - tv.tv_sec; + if (tv.tv_usec <= end_tv.tv_usec) { + duration_tv.tv_usec = end_tv.tv_usec - tv.tv_usec; + } else { + duration_tv.tv_sec--; + duration_tv.tv_usec = end_tv.tv_usec + 1000000 - tv.tv_usec; + } + + FD_ZERO (&read_fds); + + for (i = 0; i < n_sessions; i++) { + gint fd; + + fd = DNSServiceRefSockFD (session_handles [i]); + if (fd < 0) + continue; + + FD_SET (fd, &read_fds); + high_fd = MAX (fd, high_fd); + } + + n_ready = select (high_fd + 1, &read_fds, NULL, NULL, &duration_tv); + gettimeofday (&tv, NULL); + + if (n_ready < 1) + continue; + for (i = 0; i < n_sessions; i++) { + gint fd; + fd = DNSServiceRefSockFD (session_handles [i]); + + if (FD_ISSET (fd, &read_fds)) + DNSServiceProcessResult (session_handles [i]); + } + } +} + +static void +init_local (void) +{ + int i; + GnomeVFSResult res; + + if (!started_local) { + DNSServiceRef *session_handles; + + started_local = TRUE; + + for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) { + GnomeVFSDNSSDBrowseHandle *handle; + res = gnome_vfs_dns_sd_browse (&handle, + "local", + dns_sd_types [i].type, + local_browse_callback, + NULL, NULL); + if (res == GNOME_VFS_OK) { + dns_sd_types [i].handle = handle; + } + } + + session_handles = g_new0 (DNSServiceRef, G_N_ELEMENTS (dns_sd_types)); + + for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) { + DNSServiceBrowse (&session_handles [i], + 0 /* flags (none needed) */, + 0 /* interface (-1 for local, 0 for all) */, + dns_sd_types [i].type, + "local", + local_browse_callback_sync, + NULL); + } + + bonjour_run_multi_sync (session_handles, G_N_ELEMENTS (dns_sd_types), + LOCAL_SYNC_BROWSE_DELAY_MSEC); + + for (i = 0; i < G_N_ELEMENTS (dns_sd_types); i++) { + DNSServiceRefDeallocate (session_handles [i]); + } + } +} + +#endif static GnomeVFSResult do_open (GnomeVFSMethod *method, @@ -827,7 +952,7 @@ } } -#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) +#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) || defined (HAVE_BONJOUR) static void directory_handle_add_filenames (DirectoryHandle *dir_handle, GList *files) { @@ -836,7 +961,7 @@ files = files->next; } } -#endif /* HAVE_HOWL || HAVE_AVAHI */ +#endif /* HAVE_HOWL || HAVE_AVAHI || HAVE_BONJOUR*/ static GnomeVFSResult do_open_directory (GnomeVFSMethod *method, @@ -866,14 +991,14 @@ dir_handle = directory_handle_new (options); if (strcmp (domain, "local") == 0) { -#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) +#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) || defined (HAVE_BONJOUR) G_LOCK (local); init_local (); directory_handle_add_filenames (dir_handle, local_files); G_UNLOCK (local); -#endif /* HAVE_HOWL || HAVE_AVAHI */ +#endif /* HAVE_HOWL || HAVE_AVAHI || HAVE_BONJOUR */ } else { for (i=0; i < G_N_ELEMENTS (dns_sd_types); i++) { int n_services; @@ -1140,7 +1265,7 @@ return GNOME_VFS_ERROR_NOT_SUPPORTED; } -#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) +#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) || defined (HAVE_BONJOUR) if (strcmp (uri->text, "") == 0 || strcmp (uri->text, "/") == 0) { int *handle; @@ -1158,7 +1283,7 @@ return GNOME_VFS_OK; } else -#endif /* HAVE_HOWL || HAVE_AVAHI */ +#endif /* HAVE_HOWL || HAVE_AVAHI || HAVE_BONJOUR */ return GNOME_VFS_ERROR_NOT_SUPPORTED; } @@ -1166,7 +1291,7 @@ do_monitor_cancel (GnomeVFSMethod *method, GnomeVFSMethodHandle *method_handle) { -#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) +#if defined (HAVE_HOWL) || defined (HAVE_AVAHI) || defined (HAVE_BONJOUR) G_LOCK (local); local_monitors = g_list_remove (local_monitors, method_handle); @@ -1177,7 +1302,7 @@ return GNOME_VFS_OK; #else return GNOME_VFS_ERROR_NOT_SUPPORTED; -#endif /* HAVE_HOWL || HAVE_AVAHI */ +#endif /* HAVE_HOWL || HAVE_AVAHI || HAVE_BONJOUR */ }
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor