Add files that were not added during the last commit
authorChristian Kellner <gicmo@gnome.org>
Sat, 19 Jan 2008 12:15:04 +0000 (13:15 +0100)
committerChristian Kellner <gicmo@gnome.org>
Sat, 19 Jan 2008 12:15:04 +0000 (13:15 +0100)
gnio/gnio.h [new file with mode: 0644]
gnio/gnioerror.h [new file with mode: 0644]
gnio/gresolver.c [new file with mode: 0644]
gnio/gresolver.h [new file with mode: 0644]

diff --git a/gnio/gnio.h b/gnio/gnio.h
new file mode 100644 (file)
index 0000000..de14013
--- /dev/null
@@ -0,0 +1,37 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * 
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __GNIO_H__
+#define __GNIO_H__
+
+#define __GNIO_GNIO_H_INSIDE__
+
+#include <gnio/ginetaddress.h>
+#include <gnio/ginet4address.h>
+#include <gnio/ginet6address.h>
+#include <gnio/ginetsocketaddress.h>
+#include <gnio/gsocketaddress.h>
+#include <gnio/gresolver.h>
+
+#undef __GNIO_GNIO_H_INSIDE__
+
+#endif /* __GNIO_H__ */
diff --git a/gnio/gnioerror.h b/gnio/gnioerror.h
new file mode 100644 (file)
index 0000000..d188fdb
--- /dev/null
@@ -0,0 +1,40 @@
+/* GIO - GLib Input, Output and Streaming Library
+ * 
+ * Copyright (C) 2006-2007 Red Hat, Inc.
+ *
+ * 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.
+ *
+ * Author: Alexander Larsson <alexl@redhat.com>
+ */
+
+#ifndef __GNIO_ERROR_H__
+#define __GNIO_ERROR_H__
+
+#include <glib/gerror.h>
+
+G_BEGIN_DECLS
+
+/**
+ * This would ideally be in gioerror.h's GIOErrorEnum, some extra error codes are needed.
+ * Just use defines for now.
+ **/
+
+#define G_IO_ERROR_RESOLVER_NOT_FOUND 31
+#define G_IO_ERROR_RESOLVER_NO_DATA 32
+
+G_END_DECLS
+
+#endif /* __G_IO_ERROR_H__ */
diff --git a/gnio/gresolver.c b/gnio/gresolver.c
new file mode 100644 (file)
index 0000000..af46ae9
--- /dev/null
@@ -0,0 +1,379 @@
+/* GNIO - GLib Network Layer of GIO
+ * 
+ * Copyright (C) 2008 Christian Kellner 
+ *
+ * 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.
+ *
+ * Author: Christian Kellner <gicmo@gnome.org>
+ */
+
+#include <config.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#include <string.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <errno.h>
+
+#include "ginetaddress.h"
+#include "ginet4address.h"
+#include "ginet6address.h"
+#include "gresolver.h"
+#include "gnioerror.h"
+
+G_DEFINE_TYPE (GResolver, g_resolver, G_TYPE_OBJECT);
+
+#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX) || defined(HAVE_GETADDRINFO_GLIB_MUTEX)
+# ifndef G_THREADS_ENABLED
+#  error Using GLib Mutex but thread are not enabled.
+# endif
+G_LOCK_DEFINE (dnslock);
+#endif
+
+#if !defined(HAVE_GETADDRINFO)
+static GList *
+hostent2list (const struct hostent *he)
+{
+  GList *list = NULL;
+  int i;
+
+  g_return_val_if_fail (he != NULL, NULL);
+
+  for (i = 0; he->h_addr_list[i]; i++)
+    {
+      GInetAddress *address = NULL;
+
+      if (he->h_addrtype == AF_INET)
+        address = G_INET_ADDRESS (g_inet4_address_from_bytes ((guint8 *) he->h_addr_list[i]));
+      else if (he->h_addrtype == AF_INET6)
+        address = G_INET_ADDRESS (g_inet6_address_from_bytes ((guint8 *) he->h_addr_list[i]));
+
+      list = g_list_prepend (list, address);
+    }
+
+  return list;
+}
+#endif
+
+#if defined(HAVE_GETADDRINFO)
+static void
+g_io_error_from_addrinfo (GError** error, int err)
+{
+  GIOErrorEnum code = G_IO_ERROR_FAILED;
+  const gchar *message = NULL;
+
+  if (error == NULL)
+    return;
+
+  switch (err)
+    {
+      case EAI_NONAME:
+        code = G_IO_ERROR_RESOLVER_NOT_FOUND;
+        break;
+      case EAI_NODATA:
+        code = G_IO_ERROR_RESOLVER_NO_DATA;
+        break;
+      default:
+        g_warning ("unknown getaddrinfo() error code encountered");
+    }
+
+  if (message == NULL)
+    {
+      /* FIXME: is gai_strerror() thread-safe? */
+      message = gai_strerror (err);
+    }
+
+  *error = g_error_new_literal (G_IO_ERROR, code, message);
+}
+#endif
+
+static GList *
+g_resolver_get_host_by_name (GResolver *resolver, const gchar *hostname, GError **error)
+{
+  GList *list = NULL;
+
+#if defined(HAVE_GETADDRINFO)
+  {
+    struct addrinfo hints;
+    struct addrinfo *res = NULL, *i;
+    int rv;
+
+    memset (&hints, 0, sizeof (hints));
+    hints.ai_socktype = SOCK_STREAM;
+
+#ifdef HAVE_GETADDRINFO_GLIB_MUTEX
+    G_LOCK (dnslock);
+#endif
+
+    if ((rv = getaddrinfo (hostname, NULL, &hints, &res)))
+      g_io_error_from_addrinfo (error, rv);
+    else
+      for (i = res; i != NULL; i = i->ai_next)
+        {
+          if (i->ai_family == PF_INET)
+            list = g_list_prepend (list, g_inet4_address_from_bytes ((guint8 *) &(((struct sockaddr_in *) i->ai_addr)->sin_addr.s_addr)));
+          else if (i->ai_family == PF_INET6)
+            list = g_list_prepend (list, g_inet6_address_from_bytes ((guint8 *) &(((struct sockaddr_in *) i->ai_addr)->sin_addr.s_addr)));
+        }
+
+    if (res)
+      freeaddrinfo (res);
+
+#ifdef HAVE_GETADDRINFO_GLIB_MUTEX
+    G_UNLOCK (dnslock);
+#endif
+  }
+#elif defined(HAVE_GETHOSTBYNAME_THREADSAFE)
+  {
+    struct hostent *he = gethostbyname (hostname);
+
+    if (!he)
+      g_io_error_from_errno (error);
+    else
+      list = hostent2list (he);
+  }
+#elif defined(HAVE_GETHOSTBYNAME_R_GLIBC)
+  {
+    struct hostent result, *he;
+    gsize len = 1024;
+    gchar *buf = g_new (gchar, len);
+    gint rv, herr;
+
+    while ((rv = gethostbyname_r (hostname, &result, buf, len, &he, &herr)) == ERANGE)
+      {
+        len *= 2;
+        buf = g_renew (gchar, buf, len);
+      }
+
+    if (!rv)
+      list = hostent2list (he);
+
+    g_free (buf);
+  }
+#elif defined(HAVE_GETHOSTBYNAME_R_SOLARIS)
+  {
+    struct hostent result, *he;
+    gsize len = 8192;
+    char *buf = NULL;
+
+    do
+      {
+        buf = g_renew (gchar, buf, len);
+        errno = 0;
+        he = gethostbyname_r (hostname, &result, buf, len, &h_errno);
+        len += 1024;
+      }
+    while (errno == ERANGE);
+
+    if (he)
+      list = hostent2list (&result);
+
+    g_free (buf);
+  }
+#elif defined(HAVE_GETHOSTBYNAME_R_HPUX)
+  {
+    struct hostent he;
+    struct hostent_data buf;
+    int rv;
+
+    rv = gethostbyname_r (hostname, &he, &buf);
+
+    if (!rv)
+      list = hostent2list (&he);
+  }
+#else
+  {
+    struct hostent *he;
+
+#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
+    G_LOCK (dnslock);
+#endif
+
+    he = gethostbyname (hostname);
+    list = hostent2list (he);
+
+#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
+    G_UNLOCK (dnslock);
+#endif
+  }
+#endif
+
+  if (list)
+    list = g_list_reverse (list);
+
+  return list;
+}
+
+static void
+g_resolver_class_init (GResolverClass *klass)
+{
+  GObjectClass *gobject_class G_GNUC_UNUSED = G_OBJECT_CLASS (klass);
+}
+
+static void
+g_resolver_init (GResolver *address)
+{
+
+}
+
+typedef struct {
+  GList *list;
+  const gchar *host;
+} ResolveListData;
+
+static void
+resolve_list_thread (GSimpleAsyncResult *res,
+                     GObject            *object,
+                     GCancellable       *cancellable)
+{
+  ResolveListData *op;
+  GError *error = NULL;
+
+  op = g_simple_async_result_get_op_res_gpointer (res);
+
+  op->list = g_resolver_resolve_list (G_RESOLVER (object), op->host, cancellable, &error);
+
+  if (op->list == NULL)
+    {
+      g_simple_async_result_set_from_error (res, error);
+      g_error_free (error);
+    }
+}
+
+GInetAddress *
+g_resolver_resolve (GResolver     *resolver,
+                    const char    *host,
+                    GCancellable  *cancellable,
+                    GError       **error)
+{
+  GList *list;
+  GInetAddress *address;
+
+  list = g_resolver_get_host_by_name (resolver, host, error);
+
+  if (!list)
+    return NULL;
+
+  address = G_INET_ADDRESS (g_object_ref (g_list_first (list)->data));
+
+  g_list_foreach (list, (GFunc) g_object_unref, NULL);
+
+  g_list_free (list);
+
+  return address;
+}
+
+void
+g_resolver_resolve_async (GResolver           *resolver,
+                          const char          *host,
+                          GCancellable        *cancellable,
+                          GAsyncReadyCallback  callback,
+                          gpointer             user_data)
+{
+  GSimpleAsyncResult *res;
+  ResolveListData *op;
+
+  op = g_new (ResolveListData, 1);
+
+  res = g_simple_async_result_new (G_OBJECT (resolver), callback, user_data, g_resolver_resolve_list_async);
+
+  g_simple_async_result_set_op_res_gpointer (res, op, g_free);
+
+  op->host = host;
+
+  g_simple_async_result_run_in_thread (res, resolve_list_thread, G_PRIORITY_DEFAULT, cancellable);
+
+  g_object_unref (res);
+}
+
+GInetAddress *
+g_resolver_resolve_finish (GResolver     *resolver,
+                           GAsyncResult  *result,
+                           GError       **error)
+{
+  GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (result);
+  ResolveListData *op;
+  GInetAddress *address;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (res) == g_resolver_resolve_list_async);
+
+  op = g_simple_async_result_get_op_res_gpointer (res);
+
+  g_simple_async_result_propagate_error (res, error);
+
+  if (op->list == NULL)
+    return NULL;
+
+  address = G_INET_ADDRESS (g_object_ref (g_list_first (op->list)->data));
+
+  g_list_foreach (op->list, (GFunc) g_object_unref, NULL);
+
+  g_list_free (op->list);
+
+  return address;
+}
+
+GList *
+g_resolver_resolve_list (GResolver     *resolver,
+                         const char    *host,
+                         GCancellable  *cancellable,
+                         GError       **error)
+{
+  return g_resolver_get_host_by_name (resolver, host, error);
+}
+
+void
+g_resolver_resolve_list_async (GResolver           *resolver,
+                               const char          *host,
+                               GCancellable        *cancellable,
+                               GAsyncReadyCallback  callback,
+                               gpointer             user_data)
+{
+  GSimpleAsyncResult *res;
+  ResolveListData *op;
+
+  op = g_new (ResolveListData, 1);
+
+  res = g_simple_async_result_new (G_OBJECT (resolver), callback, user_data, g_resolver_resolve_list_async);
+
+  g_simple_async_result_set_op_res_gpointer (res, op, g_free);
+
+  op->host = host;
+
+  g_simple_async_result_run_in_thread (res, resolve_list_thread, G_PRIORITY_DEFAULT, cancellable);
+
+  g_object_unref (res);
+}
+
+GList *
+g_resolver_resolve_list_finish (GResolver     *resolver,
+                                GAsyncResult  *result,
+                                GError       **error)
+{
+  GSimpleAsyncResult *res = G_SIMPLE_ASYNC_RESULT (result);
+  ResolveListData *op;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (res) == g_resolver_resolve_list_async);
+
+  op = g_simple_async_result_get_op_res_gpointer (res);
+
+  g_simple_async_result_propagate_error (res, error);
+
+  return op->list;
+}
+
diff --git a/gnio/gresolver.h b/gnio/gresolver.h
new file mode 100644 (file)
index 0000000..33e935e
--- /dev/null
@@ -0,0 +1,66 @@
+#ifndef G_RESOLVER_H
+#define G_RESOLVER_H
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#include "ginetaddress.h"
+
+G_BEGIN_DECLS
+
+#define G_TYPE_RESOLVER         (g_resolver_get_type ())
+#define G_RESOLVER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_RESOLVER, GResolver))
+#define G_RESOLVER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_RESOLVER, GResolverClass))
+#define G_IS_RESOLVER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_RESOLVER))
+#define G_IS_RESOLVER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_RESOLVER))
+#define G_RESOLVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_RESOLVER, GResolver))
+
+typedef struct _GResolver        GResolver;
+typedef struct _GResolverClass   GResolverClass;
+
+struct _GResolver
+{
+  GObject parent;
+};
+
+struct _GResolverClass
+{
+  GObjectClass parent_class;
+};
+
+GType          g_resolver_get_type (void) G_GNUC_CONST;
+
+GInetAddress * g_resolver_resolve                   (GResolver     *resolver,
+                                                     const char    *host,
+                                                     GCancellable  *cancellable,
+                                                     GError       **error);
+
+void           g_resolver_resolve_async             (GResolver           *resolver,
+                                                     const char          *host,
+                                                     GCancellable        *cancellable,
+                                                     GAsyncReadyCallback  callback,
+                                                     gpointer             user_data);
+
+GInetAddress * g_resolver_resolve_finish            (GResolver     *resolver,
+                                                     GAsyncResult  *result,
+                                                     GError       **error);
+
+GList *        g_resolver_resolve_list              (GResolver     *resolver,
+                                                     const char    *host,
+                                                     GCancellable  *cancellable,
+                                                     GError       **error);
+
+void           g_resolver_resolve_list_async        (GResolver           *resolver,
+                                                     const char          *host,
+                                                     GCancellable        *cancellable,
+                                                     GAsyncReadyCallback  callback,
+                                                     gpointer             user_data);
+
+GList *        g_resolver_resolve_list_finish       (GResolver     *resolver,
+                                                     GAsyncResult  *result,
+                                                     GError       **error);
+
+G_END_DECLS
+
+#endif /* G_RESOLVER_H */
+