[glibmm] Re-enable network IO stuff (Socket, Resolver, etc)
- From: Jonathon Jongsma <jjongsma src gnome org>
- To: svn-commits-list gnome org
- Cc:
- Subject: [glibmm] Re-enable network IO stuff (Socket, Resolver, etc)
- Date: Sat, 28 Nov 2009 22:33:56 +0000 (UTC)
commit e161c51f14b5b5123dacac447d1697134ee4eadb
Author: Jonathon Jongsma <jonathon quotidian org>
Date: Sat Oct 24 00:11:18 2009 -0500
Re-enable network IO stuff (Socket, Resolver, etc)
There is a bit of a problem with some of the async stuff that is exhibited by
the included resolver example. For example, when run the example with the
following arguments:
./resolver -c domain.com
There are several critical warnings printed to the terminal, and I have not been
able to debug it to find the cause yet. I think it must have something to with
the lifetime of the enumerator object during the next_async() calls and
sigc::bind, etc. but I can't figure it out yet.
.gitignore | 2 +-
ChangeLog | 15 ++
examples/Makefile.am | 5 +-
examples/network/resolver.cc | 529 ++++++++++++++++++++++++++++++++++++++++
examples/network_io/resolve.cc | 51 ----
gio/giomm.h | 11 +
gio/src/error.hg | 1 +
gio/src/inetaddress.ccg | 5 +
gio/src/inetaddress.hg | 2 +-
gio/src/resolver.ccg | 32 +++
gio/src/resolver.hg | 6 +
11 files changed, 604 insertions(+), 55 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 9a0f053..67b7ccd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -63,7 +63,7 @@ giommconfig.h
/examples/thread/dispatcher2
/examples/thread/thread
/examples/thread/threadpool
-/examples/network_io/resolve
+/examples/network/resolver
# gio/
/gio/giomm-*.pc
diff --git a/ChangeLog b/ChangeLog
index 5208e86..8ad24ec 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,18 @@
+2009-10-23 Jonathon Jongsma <jonathon jongsma collabora co uk>
+
+ Re-enable Network IO stuff (Socket, Resolver, etc)
+
+ * .gitignore:
+ * examples/Makefile.am:
+ * examples/network/resolver.cc: Ported example from glib
+ * examples/network_io/resolve.cc: Removed.
+ * gio/giomm.h: Add network headers
+ * gio/src/error.hg: Add ResolverError
+ * gio/src/inetaddress.ccg:
+ * gio/src/inetaddress.hg: Fix broken constructor
+ * gio/src/resolver.ccg:
+ * gio/src/resolver.hg: Added a few missing free functions
+
2009-11-23 Murray Cumming <murrayc murrayc com>
Regex: Slight documentation improvement.
diff --git a/examples/Makefile.am b/examples/Makefile.am
index ea48c91..83aa5ab 100644
--- a/examples/Makefile.am
+++ b/examples/Makefile.am
@@ -23,6 +23,7 @@ check_PROGRAMS = \
iochannel_stream/example \
keyfile/example \
markup/parser \
+ network/resolver \
options/example \
properties/example \
regex/example \
@@ -67,5 +68,5 @@ thread_thread_LDADD = $(thread_ldadd)
thread_threadpool_SOURCES = thread/threadpool.cc
thread_threadpool_LDADD = $(thread_ldadd)
-network_io_resolve_SOURCES = network_io/resolve.cc
-network_io_resolve_LDADD = $(giomm_ldadd)
+network_resolver_SOURCES = network/resolver.cc
+network_resolver_LDADD = $(giomm_ldadd) $(GTHREAD_LIBS)
diff --git a/examples/network/resolver.cc b/examples/network/resolver.cc
new file mode 100644
index 0000000..625c859
--- /dev/null
+++ b/examples/network/resolver.cc
@@ -0,0 +1,529 @@
+/* GIO - GLib Input, Output and Streaming Library
+ *
+ * Copyright (C) 2008 Red Hat, Inc.
+ * Copyright (C) 2009 Jonathon Jongsma
+ *
+ * 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 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., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+#include <giomm.h>
+#include <iostream>
+
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <gio/gio.h>
+
+static Glib::RefPtr<Gio::Resolver> resolver;
+static Glib::RefPtr<Gio::Cancellable> cancellable;
+static Glib::RefPtr<Glib::MainLoop> loop;
+static int nlookups = 0;
+
+static void G_GNUC_NORETURN
+usage (void)
+{
+ std::cerr
+ << "Usage: resolver [-t] [-s] [hostname | IP | service/protocol/domain ] ...\n"
+ << " resolver [-t] [-s] -c [hostname | IP | service/protocol/domain ]\n"
+ << " Use -t to enable threading.\n"
+ << " Use -s to do synchronous lookups.\n"
+ << " Both together will result in simultaneous lookups in multiple threads\n"
+ << " Use -c (and only a single resolvable argument) to test GSocketConnectable.\n";
+ exit (1);
+}
+
+G_LOCK_DEFINE_STATIC (response);
+
+static bool
+idle_quit ()
+{
+ loop->quit ();
+ return false;
+}
+
+static void
+done_lookup (void)
+{
+ nlookups--;
+ if (nlookups == 0)
+ {
+ /* In the sync case we need to make sure we don't call
+ * g_main_loop_quit before the loop is actually running...
+ */
+ Glib::signal_idle ().connect (sigc::ptr_fun (idle_quit));
+ }
+}
+
+static void
+print_resolved_name (const Glib::ustring& phys,
+ const Glib::ustring& name)
+{
+ G_LOCK (response);
+ std::cout
+ << Glib::ustring::compose ("Address: %1\n", phys)
+ << Glib::ustring::compose ("Name: %1\n", name)
+ << std::endl;
+
+ done_lookup ();
+ G_UNLOCK (response);
+}
+
+static void
+print_resolved_addresses (const Glib::ustring& name,
+ const std::list<Glib::RefPtr<Gio::InetAddress> >& addresses)
+{
+ G_LOCK (response);
+ std::cout << Glib::ustring::compose ("Name: %1\n", name);
+ for (std::list<Glib::RefPtr<Gio::InetAddress> >::const_iterator iter = addresses.begin ();
+ iter != addresses.end (); ++iter)
+ {
+ std::cout << Glib::ustring::compose ("Address: %1\n", (*iter)->to_string ());
+ }
+ std::cout << std::endl;
+
+ done_lookup ();
+ G_UNLOCK (response);
+}
+
+static void
+print_resolved_service (const Glib::ustring& service,
+ const std::list<Gio::SrvTarget>& targets)
+{
+ G_LOCK (response);
+ std::cout << Glib::ustring::compose ("Service: %1\n", service);
+ for (std::list<Gio::SrvTarget>::const_iterator iter = targets.begin ();
+ iter != targets.end (); ++iter)
+ {
+ std::cout <<
+ Glib::ustring::compose ("%1:%u (pri %u, weight %u)\n",
+ iter->get_hostname (),
+ iter->get_port (),
+ iter->get_priority (),
+ iter->get_weight ());
+ }
+ std::cout << std::endl;
+
+ done_lookup ();
+ G_UNLOCK (response);
+}
+
+static void
+lookup_one_sync (const Glib::ustring& arg)
+{
+ if (arg.find ('/') != std::string::npos)
+ {
+ std::list<Gio::SrvTarget> targets;
+ /* service/protocol/domain */
+ std::vector<Glib::ustring> parts;
+ size_t pos = 0;
+ for (int i = 0; i < 3; ++i)
+ {
+ size_t newpos = arg.find ('/', pos);
+ if (pos == std::string::npos)
+ usage ();
+ parts.push_back (arg.substr (pos, newpos - pos));
+ pos = newpos;
+ }
+
+ try
+ {
+ targets = resolver->lookup_service (parts[0], parts[1], parts[2],
+ cancellable);
+ print_resolved_service (arg, targets);
+ }
+ catch (const Gio::ResolverError& err)
+ {
+ std::cerr << err.what () << std::endl;
+ }
+ }
+ else if (Gio::hostname_is_ip_address (arg))
+ {
+ Glib::RefPtr<Gio::InetAddress> addr = Gio::InetAddress::create (arg);
+ try
+ {
+ Glib::ustring name = resolver->lookup_by_address (addr, cancellable);
+ print_resolved_name (arg, name);
+ }
+ catch (const Gio::ResolverError& err)
+ {
+ std::cerr << err.what () << std::endl;
+ }
+ }
+ else
+ {
+ std::list<Glib::RefPtr<Gio::InetAddress> > addresses;
+
+ try
+ {
+ addresses = resolver->lookup_by_name (arg, cancellable);
+ print_resolved_addresses (arg, addresses);
+ }
+ catch (const Gio::ResolverError& err)
+ {
+ std::cerr << err.what () << std::endl;
+ }
+ }
+}
+
+static void
+lookup_thread (const Glib::ustring& arg)
+{
+ lookup_one_sync (arg);
+}
+
+static void
+start_threaded_lookups (char **argv, int argc)
+{
+ int i;
+
+ for (i = 0; i < argc; i++)
+ Glib::Thread::create (sigc::bind (sigc::ptr_fun (lookup_thread),
+ argv[i]),
+ false);
+}
+
+static void
+start_sync_lookups (char **argv, int argc)
+{
+ int i;
+
+ for (i = 0; i < argc; i++)
+ lookup_one_sync (argv[i]);
+}
+
+static void
+lookup_by_addr_callback (Glib::RefPtr<Gio::AsyncResult> result,
+ const Glib::ustring& phys)
+{
+ try
+ {
+ print_resolved_name (phys, resolver->lookup_by_address_finish (result));
+ }
+ catch (const Gio::ResolverError& err)
+ {
+ std::cerr << err.what () << std::endl;
+ done_lookup ();
+ }
+}
+
+static void
+lookup_by_name_callback (Glib::RefPtr<Gio::AsyncResult> result,
+ const Glib::ustring& name)
+{
+ try
+ {
+ print_resolved_addresses (name, resolver->lookup_by_name_finish (result));
+ }
+ catch (const Gio::ResolverError& err)
+ {
+ std::cerr << err.what () << std::endl;
+ }
+}
+
+static void
+lookup_service_callback (Glib::RefPtr<Gio::AsyncResult> result,
+ const Glib::ustring& service)
+{
+ try
+ {
+ print_resolved_service (service,
+ resolver->lookup_service_finish (result));
+ }
+ catch (const Gio::ResolverError& err)
+ {
+ std::cerr << err.what () << std::endl;
+ }
+}
+
+static void
+start_async_lookups (char **argv, int argc)
+{
+ for (int i = 0; i < argc; i++)
+ {
+ Glib::ustring arg (argv[i]);
+ if (arg.find ('/') != std::string::npos)
+ {
+ /* service/protocol/domain */
+ std::vector<Glib::ustring> parts;
+ size_t pos = 0;
+ for (int j = 0; j < 3; ++j)
+ {
+ size_t newpos = arg.find ('/', pos);
+ if (pos == std::string::npos)
+ usage ();
+ parts.push_back (arg.substr (pos, newpos - pos));
+ pos = newpos;
+ }
+
+ resolver->lookup_service_async (parts[0], parts[1], parts[2],
+ sigc::bind (sigc::ptr_fun
+ (lookup_service_callback),
+ Glib::ustring (argv[i])),
+ cancellable
+ );
+ }
+ else if (Gio::hostname_is_ip_address (argv[i]))
+ {
+ Glib::RefPtr<Gio::InetAddress> addr = Gio::InetAddress::create (argv[i]);
+
+ resolver->lookup_by_address_async (addr,
+ sigc::bind (sigc::ptr_fun
+ (lookup_by_addr_callback),
+ argv[i]),
+ cancellable);
+ }
+ else
+ {
+ resolver->lookup_by_name_async (argv[i],
+ sigc::bind (sigc::ptr_fun
+ (lookup_by_name_callback),
+ argv[i]),
+ cancellable);
+ }
+
+ /* Stress-test the reloading code */
+ //g_signal_emit_by_name (resolver, "reload");
+ }
+}
+
+static void
+print_connectable_sockaddr (Glib::RefPtr<Gio::SocketAddress> sockaddr)
+{
+ Glib::ustring phys;
+ Glib::RefPtr<Gio::InetSocketAddress> isa =
+ Glib::RefPtr<Gio::InetSocketAddress>::cast_dynamic (sockaddr);
+
+ if (!isa)
+ {
+ std::cerr <<
+ Glib::ustring::compose ("Error: Unexpected sockaddr type '%1'\n",
+ g_type_name_from_instance ((GTypeInstance *)sockaddr->gobj ()));
+ }
+ else
+ {
+ phys = isa->get_address ()->to_string ();
+ std::cout << Glib::ustring::compose ("Address: %1%2%3:%4\n",
+ phys.find (':') != std::string::npos ? "[" : "",
+ phys,
+ phys.find (':') != std::string::npos ? "]" : "",
+ isa->get_port ());
+ }
+}
+
+static void
+do_sync_connectable (Glib::RefPtr<Gio::SocketAddressEnumerator> enumerator)
+{
+ Glib::RefPtr<Gio::SocketAddress> sockaddr;
+
+ while ((sockaddr = enumerator->next (cancellable)))
+ print_connectable_sockaddr (sockaddr);
+
+ done_lookup ();
+}
+
+static void do_async_connectable (Glib::RefPtr<Gio::SocketAddressEnumerator> enumerator);
+
+static void
+got_next_async (Glib::RefPtr<Gio::AsyncResult> result,
+ Glib::RefPtr<Gio::SocketAddressEnumerator> enumerator)
+{
+ g_debug ("%s: enumerator: %p (%d)", G_STRFUNC, enumerator->gobj (), G_OBJECT (enumerator->gobj ())->ref_count);
+ try
+ {
+ Glib::RefPtr<Gio::SocketAddress> sockaddr = enumerator->next_finish (result);
+ if (sockaddr)
+ {
+ print_connectable_sockaddr (sockaddr);
+ do_async_connectable (enumerator);
+ }
+ else
+ {
+ done_lookup ();
+ }
+ }
+ catch (const Gio::ResolverError& err)
+ {
+ std::cerr << err.what () << std::endl;
+ }
+}
+
+Glib::RefPtr<Gio::SocketAddressEnumerator> global_enumerator;
+static void
+do_async_connectable (Glib::RefPtr<Gio::SocketAddressEnumerator> enumerator)
+{
+ g_debug ("%s: enumerator: %p (%d)", G_STRFUNC, enumerator->gobj (), G_OBJECT (enumerator->gobj ())->ref_count);
+ enumerator->next_async (cancellable,
+ sigc::bind (sigc::ptr_fun (got_next_async),
+ enumerator));
+}
+
+Glib::RefPtr<Gio::SocketConnectable> global_connectable;
+
+static void
+do_connectable (const std::string& arg, gboolean synchronous)
+{
+ std::vector<std::string> parts;
+ Glib::RefPtr<Gio::SocketConnectable> connectable;
+ Glib::RefPtr<Gio::SocketAddressEnumerator> enumerator;
+
+ if (arg.find ('/') != std::string::npos)
+ {
+ /* service/protocol/domain */
+ size_t pos = 0;
+ for (int i = 0; i < 3; ++i)
+ {
+ size_t newpos = arg.find ('/', pos);
+ if (pos == std::string::npos)
+ usage ();
+ parts.push_back (arg.substr (pos, newpos - pos));
+ pos = newpos;
+ }
+
+ connectable = Gio::NetworkService::create (parts[0], parts[1], parts[2]);
+ }
+ else
+ {
+ std::string host, port_str;
+ guint16 port;
+
+ size_t pos = arg.find (':');
+ if (pos != std::string::npos)
+ {
+ host = arg.substr (0, pos);
+ port_str = arg.substr(pos);
+ port = strtoul (port_str.c_str (), NULL, 10);
+ }
+ else
+ port = 0;
+
+ if (Gio::hostname_is_ip_address (host))
+ {
+ Glib::RefPtr<Gio::InetAddress> addr = Gio::InetAddress::create (host);
+ connectable = Gio::InetSocketAddress::create (addr, port);
+ }
+ else
+ connectable = Gio::NetworkAddress::create (arg, port);
+ }
+
+ enumerator = connectable->enumerate ();
+ g_debug ("%s: enumerator: %p (%d)", G_STRFUNC, enumerator->gobj (), G_OBJECT (enumerator->gobj ())->ref_count);
+
+ if (synchronous)
+ do_sync_connectable (enumerator);
+ else
+ do_async_connectable (enumerator);
+}
+
+#ifdef G_OS_UNIX
+static int cancel_fds[2];
+
+static void
+interrupted (int sig)
+{
+ signal (SIGINT, SIG_DFL);
+ write (cancel_fds[1], "x", 1);
+}
+
+static bool
+async_cancel (Glib::IOCondition /*cond*/, Glib::RefPtr<Gio::Cancellable> cancellable)
+{
+ cancellable->cancel ();
+ return false;
+}
+#endif
+
+int
+main (int argc, char **argv)
+{
+ bool threaded = false, synchronous = false;
+ bool use_connectable = false;
+#ifdef G_OS_UNIX
+ Glib::RefPtr<Glib::IOChannel> chan;
+ sigc::connection watch_conn;
+#endif
+
+ /* We can't use Glib::OptionContext because we use the arguments to
+ * decide whether or not to call g_thread_init().
+ */
+ while (argc >= 2 && argv[1][0] == '-')
+ {
+ if (!strcmp (argv[1], "-t"))
+ {
+ Glib::thread_init ();
+ threaded = true;
+ }
+ else if (!strcmp (argv[1], "-s"))
+ synchronous = true;
+ else if (!strcmp (argv[1], "-c"))
+ use_connectable = true;
+ else
+ usage ();
+
+ argv++;
+ argc--;
+ }
+ Gio::init ();
+
+ if (argc < 2 || (argc > 2 && use_connectable))
+ usage ();
+
+ resolver = Gio::Resolver::get_default ();
+
+ cancellable = Gio::Cancellable::create ();
+
+#ifdef G_OS_UNIX
+ /* Set up cancellation; we want to cancel if the user ^C's the
+ * program, but we can't cancel directly from an interrupt.
+ */
+ signal (SIGINT, interrupted);
+
+ if (pipe (cancel_fds) == -1)
+ {
+ perror ("pipe");
+ exit (1);
+ }
+ chan = Glib::IOChannel::create_from_fd (cancel_fds[0]);
+ Glib::RefPtr<Glib::IOSource> source = chan->create_watch (Glib::IO_IN);
+ watch_conn = source->connect (sigc::bind (sigc::ptr_fun (async_cancel), cancellable));
+#endif
+
+ nlookups = argc - 1;
+ loop = Glib::MainLoop::create (true);
+
+ if (use_connectable)
+ do_connectable (argv[1], synchronous);
+ else
+ {
+ if (threaded && synchronous)
+ start_threaded_lookups (argv + 1, argc - 1);
+ else if (synchronous)
+ start_sync_lookups (argv + 1, argc - 1);
+ else
+ start_async_lookups (argv + 1, argc - 1);
+ }
+
+ loop->run ();
+
+#ifdef G_OS_UNIX
+ watch_conn.disconnect ();
+#endif
+
+ return 0;
+}
diff --git a/gio/giomm.h b/gio/giomm.h
index 2e393c6..287d6d5 100644
--- a/gio/giomm.h
+++ b/gio/giomm.h
@@ -48,7 +48,10 @@
#include <giomm/filterinputstream.h>
#include <giomm/filteroutputstream.h>
#include <giomm/icon.h>
+#include <giomm/inetaddress.h>
+#include <giomm/inetsocketaddress.h>
#include <giomm/init.h>
+#include <giomm/initable.h>
#include <giomm/inputstream.h>
#include <giomm/iostream.h>
#include <giomm/loadableicon.h>
@@ -56,8 +59,16 @@
#include <giomm/memoryoutputstream.h>
#include <giomm/mount.h>
#include <giomm/mountoperation.h>
+#include <giomm/networkaddress.h>
+#include <giomm/networkservice.h>
#include <giomm/outputstream.h>
+#include <giomm/resolver.h>
#include <giomm/seekable.h>
+#include <giomm/socket.h>
+#include <giomm/socketaddress.h>
+#include <giomm/socketaddressenumerator.h>
+#include <giomm/socketconnectable.h>
+#include <giomm/srvtarget.h>
#include <giomm/themedicon.h>
#include <giomm/unixinputstream.h>
#include <giomm/unixoutputstream.h>
diff --git a/gio/src/error.hg b/gio/src/error.hg
index b7f464f..970b59b 100644
--- a/gio/src/error.hg
+++ b/gio/src/error.hg
@@ -41,6 +41,7 @@ namespace Gio
/** Exception class for giomm errors.
*/
_WRAP_GERROR(Error, GIOErrorEnum, G_IO_ERROR, NO_GTYPE)
+_WRAP_GERROR(ResolverError, GResolverError, G_RESOLVER_ERROR, NO_GTYPE)
} // namespace Gio
diff --git a/gio/src/inetaddress.ccg b/gio/src/inetaddress.ccg
index c146baa..1ed1a1d 100644
--- a/gio/src/inetaddress.ccg
+++ b/gio/src/inetaddress.ccg
@@ -22,4 +22,9 @@
namespace Gio
{
+Glib::RefPtr<InetAddress> InetAddress::create(const Glib::ustring& string)
+{
+ return Glib::wrap (g_inet_address_new_from_string (string.c_str ()));
+}
+
} //namespace Gio
diff --git a/gio/src/inetaddress.hg b/gio/src/inetaddress.hg
index b7ab6b5..ed18433 100644
--- a/gio/src/inetaddress.hg
+++ b/gio/src/inetaddress.hg
@@ -52,7 +52,7 @@ protected:
// TODO: new_loopback has the same signature as new_any
public:
- _WRAP_CREATE(const Glib::ustring& string)
+ static Glib::RefPtr<InetAddress> create(const Glib::ustring& string);
_WRAP_CREATE(const guint8 *bytes, SocketFamily family)
_WRAP_CREATE(SocketFamily family)
// TODO: create for new_loopback
diff --git a/gio/src/resolver.ccg b/gio/src/resolver.ccg
index f786bce..1ddc037 100644
--- a/gio/src/resolver.ccg
+++ b/gio/src/resolver.ccg
@@ -182,4 +182,36 @@ Resolver::lookup_service_async(const Glib::ustring& service,
slot_copy);
}
+std::string
+hostname_to_ascii (const Glib::ustring& hostname)
+{
+ Glib::convert_return_gchar_ptr_to_stdstring
+ (g_hostname_to_ascii (hostname.c_str ()));
+}
+
+Glib::ustring
+hostname_to_unicode (const Glib::ustring& hostname)
+{
+ Glib::convert_return_gchar_ptr_to_ustring
+ (g_hostname_to_unicode (hostname.c_str ()));
+}
+
+bool
+hostname_is_non_ascii (const Glib::ustring& hostname)
+{
+ return g_hostname_is_non_ascii (hostname.c_str ());
+}
+
+bool
+hostname_is_ascii_encoded (const Glib::ustring& hostname)
+{
+ return g_hostname_is_ascii_encoded (hostname.c_str ());
+}
+
+bool
+hostname_is_ip_address (const Glib::ustring& hostname)
+{
+ return g_hostname_is_ip_address (hostname.c_str ());
+}
+
} //namespace Gio
diff --git a/gio/src/resolver.hg b/gio/src/resolver.hg
index dcf5544..d4cf192 100644
--- a/gio/src/resolver.hg
+++ b/gio/src/resolver.hg
@@ -95,4 +95,10 @@ public:
_WRAP_METHOD(ListHandle_SrvTarget lookup_service_finish(const Glib::RefPtr<AsyncResult>& result), g_resolver_lookup_service_finish, errthrow)
};
+std::string hostname_to_ascii (const Glib::ustring& hostname);
+Glib::ustring hostname_to_unicode (const Glib::ustring& hostname);
+bool hostname_is_non_ascii (const Glib::ustring& hostname);
+bool hostname_is_ascii_encoded (const Glib::ustring& hostname);
+bool hostname_is_ip_address (const Glib::ustring& hostname);
+
} // namespace Gio
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]