add gobject-2.0 to the PKG_CHECK_MODULES call
authorDan Winship <danw@src.gnome.org>
Tue, 12 Aug 2003 17:13:53 +0000 (17:13 +0000)
committerDan Winship <danw@src.gnome.org>
Tue, 12 Aug 2003 17:13:53 +0000 (17:13 +0000)
* configure.in (GLIB): add gobject-2.0 to the PKG_CHECK_MODULES
call

* libsoup/soup-address.c: Make this a GObject.
(soup_address_ref, soup_address_unref): Gone.
(soup_address_copy): Gone. Wasn't being used anyway.

* libsoup/soup-dns.c: Move all of the DNS code and caching stuff
here from soup-address.c, so that soup-address doesn't need to
worry about trying to cache zero-ref addresses.

* libsoup/soup-socket.c: Make this a GObject. Use "guint"
consistently for port numbers.
(soup_socket_ref, soup_socket_unref): Gone.

* libsoup/soup-private.h: Change the SoupSocket definition to be
SoupSocketPrivate. (Still need to keep this here since soup-server
pokes around in its internals.)
(SOUP_MAKE_TYPE): Copied from gal's E_MAKE_TYPE.

* libsoup/soup-server.c (read_done_cb, write_done_cb): Unref the
reader/writer rather than leaking them.

* libsoup/*: Use GObject methods for socket/address refcounting

* tests/auth-test.c (main)
* tests/timeserver.c (main): Call g_type_init.

* tests/get.c (main): Call g_type_init.
(get_url, got_url): Fix some bugs that could make -r mode get into
infinite loops downloading the same files over and over. Plug some
memory leaks to make this more useful for valgrinding libsoup.

* tests/simple-httpd.c (main): Call g_type_init. Set up a signal
handler for SIGINT so we can exit cleanly, since valgrind won't
give a leak report if you don't. Plug a few memory leaks.

* tests/simple-proxy.c (main): Likewise

18 files changed:
ChangeLog
configure.in
libsoup/Makefile.am
libsoup/soup-address.c
libsoup/soup-address.h
libsoup/soup-context.c
libsoup/soup-dns.c [new file with mode: 0644]
libsoup/soup-dns.h [new file with mode: 0644]
libsoup/soup-private.h
libsoup/soup-server.c
libsoup/soup-socket.c
libsoup/soup-socket.h
libsoup/soup-socks.c
tests/auth-test.c
tests/get.c
tests/simple-httpd.c
tests/simple-proxy.c
tests/timeserver.c

index 2a7385d..8cd6c78 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,46 @@
 2003-08-12  Dan Winship  <danw@ximian.com>
 
+       * configure.in (GLIB): add gobject-2.0 to the PKG_CHECK_MODULES
+       call
+
+       * libsoup/soup-address.c: Make this a GObject.
+       (soup_address_ref, soup_address_unref): Gone.
+       (soup_address_copy): Gone. Wasn't being used anyway.
+
+       * libsoup/soup-dns.c: Move all of the DNS code and caching stuff
+       here from soup-address.c, so that soup-address doesn't need to
+       worry about trying to cache zero-ref addresses.
+
+       * libsoup/soup-socket.c: Make this a GObject. Use "guint"
+       consistently for port numbers.
+       (soup_socket_ref, soup_socket_unref): Gone.
+
+       * libsoup/soup-private.h: Change the SoupSocket definition to be
+       SoupSocketPrivate. (Still need to keep this here since soup-server
+       pokes around in its internals.)
+       (SOUP_MAKE_TYPE): Copied from gal's E_MAKE_TYPE.
+
+       * libsoup/soup-server.c (read_done_cb, write_done_cb): Unref the
+       reader/writer rather than leaking them.
+
+       * libsoup/*: Use GObject methods for socket/address refcounting
+       
+       * tests/auth-test.c (main)
+       * tests/timeserver.c (main): Call g_type_init.
+
+       * tests/get.c (main): Call g_type_init.
+       (get_url, got_url): Fix some bugs that could make -r mode get into
+       infinite loops downloading the same files over and over. Plug some
+       memory leaks to make this more useful for valgrinding libsoup.
+
+       * tests/simple-httpd.c (main): Call g_type_init. Set up a signal
+       handler for SIGINT so we can exit cleanly, since valgrind won't
+       give a leak report if you don't. Plug a few memory leaks.
+
+       * tests/simple-proxy.c (main): Likewise 
+
+2003-08-12  Dan Winship  <danw@ximian.com>
+
        Pull over some new test programs from the soup-refactoring branch,
        along with the SoupUri changes they depend on.
 
index cfb9a48..fd17602 100644 (file)
@@ -72,7 +72,7 @@ dnl ***********************
 dnl *** Checks for glib ***
 dnl ***********************
 
-PKG_CHECK_MODULES(GLIB, glib-2.0)
+PKG_CHECK_MODULES(GLIB, glib-2.0 gobject-2.0)
 AC_SUBST(GLIB_CFLAGS)
 AC_SUBST(GLIB_LIBS)
 
index c83e9e7..c7bbb65 100644 (file)
@@ -42,6 +42,8 @@ libsoup_2_2_la_SOURCES =      \
        soup-auth.h             \
        soup-auth.c             \
        soup-context.c          \
+       soup-dns.h              \
+       soup-dns.c              \
        soup-error.c            \
        soup-gnutls.h           \
        soup-gnutls.c           \
index 2fc164d..b94e81f 100644 (file)
@@ -2,14 +2,7 @@
 /*
  * soup-address.c: Internet address handing
  *
- * Authors:
- *      David Helder  (dhelder@umich.edu)
- *      Alex Graveley (alex@ximian.com)
- *
- * Original code compliments of David Helder's GNET Networking Library, and is
- * Copyright (C) 2000  David Helder & Andrew Lanoix.
- *
- * All else Copyright (C) 2000-2002, Ximian, Inc.
+ * Copyright (C) 2000-2003, Ximian, Inc.
  */
 
 #ifdef HAVE_CONFIG_H
 
 #include "soup-private.h"
 #include "soup-address.h"
+#include "soup-dns.h"
 
-struct _SoupAddress {
-       gchar*          name;
-       int             family;
+struct SoupAddressPrivate {
+       char *name;
+       int   family;
        union {
                struct in_addr  in;
 #ifdef HAVE_IPV6
                struct in6_addr in6;
 #endif
        } addr;
-
-       gint            ref_count;
-       gint            cached;
 };
 
 #include <unistd.h>
@@ -60,6 +51,42 @@ struct _SoupAddress {
 #define INADDR_NONE -1
 #endif
 
+#define PARENT_TYPE G_TYPE_OBJECT
+static GObjectClass *parent_class;
+
+static void
+init (GObject *object)
+{
+       SoupAddress *addr = SOUP_ADDRESS (object);
+
+       addr->priv = g_new0 (SoupAddressPrivate, 1);
+}
+
+static void
+finalize (GObject *object)
+{
+       SoupAddress *addr = SOUP_ADDRESS (object);
+
+       if (addr->priv->name)
+               g_free (addr->priv->name);
+
+       g_free (addr->priv);
+
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+class_init (GObjectClass *object_class)
+{
+       parent_class = g_type_class_ref (PARENT_TYPE);
+
+       /* virtual method override */
+       object_class->finalize = finalize;
+}
+
+SOUP_MAKE_TYPE (soup_address, SoupAddress, class_init, init, PARENT_TYPE)
+
+
 static void
 soup_address_new_sync_cb (SoupAddress       *addr,
                          SoupAddressStatus  status,
@@ -90,6 +117,37 @@ soup_address_new_sync (const char *name)
        return ret;
 }
 
+static SoupAddress *
+new_address (const char *name, int family, gpointer addr_data)
+{
+       SoupAddress *addr;
+
+       addr = g_object_new (SOUP_TYPE_ADDRESS, NULL);
+       if (name)
+               addr->priv->name = g_strdup (name);
+       addr->priv->family = family;
+
+       switch (family) {
+       case AF_INET:
+               memcpy (&addr->priv->addr.in, addr_data,
+                       sizeof (addr->priv->addr.in));
+               break;
+
+#ifdef HAVE_IPV6
+       case AF_INET6:
+               memcpy (&addr->priv->addr.in6, addr_data,
+                       sizeof (addr->priv->addr.in6));
+               break;
+#endif
+
+       default:
+               g_object_unref (addr);
+               addr = NULL;
+       }
+
+       return addr;
+}
+
 /**
  * soup_address_new_from_sockaddr:
  * @sa: a pointer to a sockaddr
@@ -102,24 +160,16 @@ soup_address_new_sync (const char *name)
  * Return value: a #SoupAddress, or %NULL if the lookup fails.
  **/
 SoupAddress *
-soup_address_new_from_sockaddr (struct sockaddr *sa,
-                               guint *port)
+soup_address_new_from_sockaddr (struct sockaddr *sa, guint *port)
 {
-       SoupAddress *ia;
-
-       ia = g_new0 (SoupAddress, 1);
-       ia->ref_count = 1;
-       ia->family = sa->sa_family;
-
-       switch (ia->family) {
+       switch (sa->sa_family) {
        case AF_INET:
        {
                struct sockaddr_in *sa_in = (struct sockaddr_in *)sa;
 
-               memcpy (&ia->addr.in, &sa_in->sin_addr, sizeof (ia->addr.in));
                if (port)
                        *port = g_ntohs (sa_in->sin_port);
-               break;
+               return new_address (NULL, AF_INET, &sa_in->sin_addr);
        }
 
 #ifdef HAVE_IPV6
@@ -127,20 +177,15 @@ soup_address_new_from_sockaddr (struct sockaddr *sa,
        {
                struct sockaddr_in6 *sa_in6 = (struct sockaddr_in6 *)sa;
 
-               memcpy (&ia->addr.in6, &sa_in6->sin6_addr, sizeof (ia->addr.in6));
                if (port)
                        *port = g_ntohs (sa_in6->sin6_port);
-               break;
+               return new_address (NULL, AF_INET6, &sa_in6->sin6_addr);
        }
 #endif
 
        default:
-               g_free (ia);
-               ia = NULL;
-               break;
+               return NULL;
        }
-
-       return ia;
 }
 
 /**
@@ -162,7 +207,7 @@ soup_address_ipv4_any (void)
                ipv4_any = soup_address_new_from_sockaddr ((struct sockaddr *)&sa_in, NULL);
        }
 
-       soup_address_ref (ipv4_any);
+       g_object_ref (ipv4_any);
        return ipv4_any;
 }
 
@@ -187,47 +232,11 @@ soup_address_ipv6_any (void)
                ipv6_any = soup_address_new_from_sockaddr ((struct sockaddr *)&sa_in6, NULL);
        }
 
-       soup_address_ref (ipv6_any);
+       g_object_ref (ipv6_any);
 #endif
        return ipv6_any;
 }
 
-/**
- * soup_address_ref
- * @ia: SoupAddress to reference
- *
- * Increment the reference counter of the SoupAddress.
- **/
-void
-soup_address_ref (SoupAddress* ia)
-{
-       g_return_if_fail (ia != NULL);
-
-       ++ia->ref_count;
-}
-
-/**
- * soup_address_copy
- * @ia: SoupAddress to copy
- *
- * Creates a copy of the given SoupAddress
- **/
-SoupAddress *
-soup_address_copy (SoupAddress* ia)
-{
-       SoupAddress* new_ia;
-       g_return_val_if_fail (ia != NULL, NULL);
-
-       new_ia = g_new0 (SoupAddress, 1);
-       new_ia->ref_count = 1;
-
-       new_ia->name = g_strdup (ia->name);
-       new_ia->family = ia->family;
-       memcpy (&new_ia->addr, &ia->addr, sizeof (new_ia->addr));
-
-       return new_ia;
-}
-
 static void
 soup_address_get_name_sync_cb (SoupAddress       *addr,
                               SoupAddressStatus  status,
@@ -240,17 +249,17 @@ soup_address_get_name_sync_cb (SoupAddress       *addr,
 
 /**
  * soup_address_get_name_sync:
- * @ia: a #SoupAddress
+ * @addr: a #SoupAddress
  *
- * Return value: the hostname associated with @ia, as with
+ * Return value: the hostname associated with @addr, as with
  * soup_address_get_name().
  **/
 const char *
-soup_address_get_name_sync (SoupAddress *ia)
+soup_address_get_name_sync (SoupAddress *addr)
 {
        const char *ret = (const char *) 0xdeadbeef;
 
-       soup_address_get_name (ia, soup_address_get_name_sync_cb, &ret);
+       soup_address_get_name (addr, soup_address_get_name_sync_cb, &ret);
 
        while (1) {
                g_main_iteration (TRUE);
@@ -262,7 +271,7 @@ soup_address_get_name_sync (SoupAddress *ia)
 
 /**
  * soup_address_get_canonical_name:
- * @ia: Address to get the canonical name of.
+ * @addr: Address to get the canonical name of.
  *
  * Get the "canonical" name of an address (eg, for IP4 the dotted
  * decimal name 141.213.8.59).
@@ -270,19 +279,20 @@ soup_address_get_name_sync (SoupAddress *ia)
  * Returns: %NULL if there was an error.  The caller is responsible
  * for deleting the returned string.
  **/
-char*
-soup_address_get_canonical_name (SoupAddress* ia)
+char *
+soup_address_get_canonical_name (SoupAddress *addr)
 {
-       switch (ia->family) {
+       switch (addr->priv->family) {
        case AF_INET:
        {
 #ifdef HAVE_INET_NTOP
                char buffer[INET_ADDRSTRLEN];
 
-               inet_ntop (ia->family, &ia->addr.in, buffer, sizeof (buffer));
+               inet_ntop (addr->priv->family, &addr->priv->addr.in,
+                          buffer, sizeof (buffer));
                return g_strdup (buffer);
 #else
-               return g_strdup (inet_ntoa (ia->addr.in));
+               return g_strdup (inet_ntoa (addr->priv->addr.in));
 #endif
        }
 
@@ -291,7 +301,8 @@ soup_address_get_canonical_name (SoupAddress* ia)
        {
                char buffer[INET6_ADDRSTRLEN];
 
-               inet_ntop (ia->family, &ia->addr.in6, buffer, sizeof (buffer));
+               inet_ntop (addr->priv->family, &addr->priv->addr.in6,
+                          buffer, sizeof (buffer));
                return g_strdup (buffer);
        }
 #endif
@@ -303,26 +314,27 @@ soup_address_get_canonical_name (SoupAddress* ia)
 
 /**
  * soup_address_make_sockaddr:
- * @ia: The %SoupAddress.
+ * @addr: The %SoupAddress.
  * @port: The port number
  * @sa: Pointer to struct sockaddr * to output the sockaddr into
  * @len: Pointer to int to return the size of the sockaddr into
  *
- * This creates an appropriate struct sockaddr for @ia and @port
+ * This creates an appropriate struct sockaddr for @addr and @port
  * and outputs it into *@sa. The caller must free *@sa with g_free().
  **/
 void
-soup_address_make_sockaddr (SoupAddress *ia, guint port,
+soup_address_make_sockaddr (SoupAddress *addr, guint port,
                            struct sockaddr **sa, int *len)
 {
-       switch (ia->family) {
+       switch (addr->priv->family) {
        case AF_INET:
        {
                struct sockaddr_in sa_in;
 
                memset (&sa_in, 0, sizeof (sa_in));
                sa_in.sin_family = AF_INET;
-               memcpy (&sa_in.sin_addr, &ia->addr.in, sizeof (sa_in.sin_addr));
+               memcpy (&sa_in.sin_addr, &addr->priv->addr.in,
+                       sizeof (sa_in.sin_addr));
                sa_in.sin_port = g_htons (port);
 
                *sa = g_memdup (&sa_in, sizeof (sa_in));
@@ -337,7 +349,8 @@ soup_address_make_sockaddr (SoupAddress *ia, guint port,
 
                memset (&sa_in6, 0, sizeof (sa_in6));
                sa_in6.sin6_family = AF_INET6;
-               memcpy (&sa_in6.sin6_addr, &ia->addr.in6, sizeof (sa_in6.sin6_addr));
+               memcpy (&sa_in6.sin6_addr, &addr->priv->addr.in6,
+                       sizeof (sa_in6.sin6_addr));
                sa_in6.sin6_port = g_htons (port);
 
                *sa = g_memdup (&sa_in6, sizeof (sa_in6));
@@ -362,24 +375,24 @@ soup_address_make_sockaddr (SoupAddress *ia, guint port,
 guint
 soup_address_hash (const gpointer p)
 {
-       const SoupAddress* ia;
+       const SoupAddress *addr;
 
-       g_assert(p != NULL);
+       g_return_val_if_fail (p != NULL, 0);
 
-       ia = (const SoupAddress*) p;
+       addr = (const SoupAddress*) p;
 
        /* This isn't network byte-order transparent... (Not sure how
         * that works in the v6 case.)
         */
 
-       switch (ia->family) {
+       switch (addr->priv->family) {
        case AF_INET:
-               return ia->addr.in.s_addr;
+               return addr->priv->addr.in.s_addr;
 #ifdef HAVE_IPV6
        case AF_INET6:
        {
-               guint32 *addr = (guint32 *)&(ia->addr.in6.s6_addr);
-               return (addr[0] ^ addr[1] ^ addr[2] ^ addr[3]);
+               guint32 *bytes = (guint32 *)&(addr->priv->addr.in6.s6_addr);
+               return (bytes[0] ^ bytes[1] ^ bytes[2] ^ bytes[3]);
        }
 #endif
        default:
@@ -399,405 +412,56 @@ soup_address_hash (const gpointer p)
 gint
 soup_address_equal (const gpointer p1, const gpointer p2)
 {
-       const SoupAddress* ia1 = (const SoupAddress*) p1;
-       const SoupAddress* ia2 = (const SoupAddress*) p2;
+       const SoupAddress *addr1 = (const SoupAddress*) p1;
+       const SoupAddress *addr2 = (const SoupAddress*) p2;
 
-       g_assert (p1 != NULL && p2 != NULL);
+       g_return_val_if_fail (p1 != NULL && p2 != NULL, TRUE);
 
        /* Note network byte order doesn't matter */
-       return memcmp (&ia1->addr, &ia2->addr, sizeof (ia1->addr)) == 0;
+       return memcmp (&addr1->priv->addr, &addr2->priv->addr,
+                      sizeof (addr1->priv->addr)) == 0;
 }
 
-#ifdef G_ENABLE_DEBUG
-#  include <sys/ptrace.h>
-#  ifndef PTRACE_ATTACH
-#    ifdef PT_ATTACH
-#      define SOUP_PTRACE_ATTACH PT_ATTACH
-#      define SOUP_PTRACE_DETACH PT_DETACH
-#    endif
-#  else
-#    define SOUP_PTRACE_ATTACH PTRACE_ATTACH
-#    define SOUP_PTRACE_DETACH PTRACE_DETACH
-#  endif
-#endif
-
-/* this generally causes problems, so remove from build atm */
-#ifdef SOUP_PTRACE_ATTACH
-#undef SOUP_PTRACE_ATTACH
-#endif
-
-GHashTable *address_hash = NULL, *lookup_hash = NULL;
 
 typedef struct {
-       char             *name;
-
-       GSList           *cb_list;    /* CONTAINS: SoupAddressCbData */
-       pid_t             pid;
-       int               fd;
-       guint             watch;
-       guchar            buffer [256];
-       int               len;
+       SoupDNSHandle    handle;
+       SoupAddressNewFn func;
+       gpointer         data;
 } SoupAddressLookupState;
 
 typedef struct {
-       SoupAddressLookupState *state;
-       SoupAddressNewFn        func;
-       gpointer                data;
-} SoupAddressCbData;
-
-typedef struct {
-       SoupAddress          *ia;
+       SoupAddress          *addr;
+       SoupDNSHandle         handle;
        SoupAddressGetNameFn  func;
        gpointer              data;
-
-       pid_t                 pid;
-       int                   fd;
-       guint                 watch;
-       guchar                buffer [256 + 1];
-       int                   len;
 } SoupAddressReverseState;
 
-
-/* Testing Defines */
-/*  #undef   HAVE_GETHOSTBYNAME_R_GLIBC */
-/*  #define  HAVE_GETHOSTBYNAME_R_GLIB_MUTEX */
-
-#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
-G_LOCK_DEFINE (gethostbyname);
-#endif
-
-static gboolean
-soup_gethostbyname (const char       *hostname,
-                   struct sockaddr **sa,
-                   int              *sa_len)
-{
-       struct hostent result_buf, *result = &result_buf;
-       char *buf = NULL;
-
-#if defined(HAVE_GETHOSTBYNAME_R_GLIBC)
-       {
-               size_t len;
-               int herr, res;
-
-               len = 1024;
-               buf = g_new (char, len);
-
-               while ((res = gethostbyname_r (hostname,
-                                              &result_buf,
-                                              buf,
-                                              len,
-                                              &result,
-                                              &herr)) == ERANGE) {
-                       len *= 2;
-                       buf = g_renew (char, buf, len);
-               }
-
-               if (res || result == NULL || result->h_addr_list [0] == NULL)
-                       result = NULL;
-       }
-#elif defined(HAVE_GETHOSTBYNAME_R_SOLARIS)
-       {
-               size_t len;
-               int herr;
-
-               len = 1024;
-               buf = g_new (char, len);
-
-               while ((result = gethostbyname_r (hostname,
-                                                 &result_buf,
-                                                 buf,
-                                                 len,
-                                                 &herr)) == ERANGE) {
-                       len *= 2;
-                       buf = g_renew (char, buf, len);
-               }
-       }
-#elif defined(HAVE_GETHOSTBYNAME_R_HPUX)
-       {
-               struct hostent_data hdbuf;
-
-               if (!gethostbyname_r (hostname, &result_buf, &hdbuf))
-                       result = NULL;
-       }
-#else
-       {
-#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX)
-               G_LOCK (gethostbyname);
-#endif
-               result = gethostbyname (hostname);
-       }
-#endif
-
-       if (result) {
-               switch (result->h_addrtype) {
-               case AF_INET:
-               {
-                       struct sockaddr_in *sa_in;
-
-                       sa_in = g_new0 (struct sockaddr_in, 1);
-                       sa_in->sin_family = AF_INET;
-                       memcpy (&sa_in->sin_addr, result->h_addr_list[0],
-                               sizeof (sa_in->sin_addr));
-
-                       *sa = (struct sockaddr *)sa_in;
-                       *sa_len = sizeof (struct sockaddr_in);
-                       break;
-               }
-#ifdef HAVE_IPV6
-               case AF_INET6:
-               {
-                       struct sockaddr_in6 *sa_in6;
-
-                       sa_in6 = g_new0 (struct sockaddr_in6, 1);
-                       sa_in6->sin6_family = AF_INET6;
-                       memcpy (&sa_in6->sin6_addr, result->h_addr_list[0],
-                               sizeof (sa_in6->sin6_addr));
-
-                       *sa = (struct sockaddr *)sa_in6;
-                       *sa_len = sizeof (struct sockaddr_in6);
-                       break;
-               }
-#endif
-               default:
-                       result = NULL;
-               }
-       }
-
-       if (buf)
-               g_free (buf);
-#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX)
-       G_UNLOCK (gethostbyname);
-#endif
-
-       return (result != NULL);
-}
-
-/*
- * Thread safe gethostbyaddr (we assume that gethostbyaddr_r follows
- * the same pattern as gethostbyname_r, so we don't have special
- * checks for it in configure.in.
- *
- * Returns the hostname, NULL if there was an error.
- */
-static char *
-soup_gethostbyaddr (SoupAddress *ia)
-{
-       struct hostent result_buf, *result = &result_buf;
-       char *buf = NULL, *addr;
-       int length;
-       char *rv;
-
-       switch (ia->family) {
-       case AF_INET:
-               addr = (char *)&ia->addr.in;
-               length = sizeof (ia->addr.in);
-               break;
-#ifdef HAVE_IPV6
-       case AF_INET6:
-               addr = (char *)&ia->addr.in6;
-               length = sizeof (ia->addr.in6);
-               break;
-#endif
-       default:
-               return NULL;
-       }
-
-#if defined(HAVE_GETHOSTBYNAME_R_GLIBC)
-       {
-               size_t len;
-               int herr, res;
-
-               len = 1024;
-               buf = g_new (char, len);
-
-               while ((res = gethostbyaddr_r (addr,
-                                              length,
-                                              ia->family,
-                                              &result_buf,
-                                              buf,
-                                              len,
-                                              &result,
-                                              &herr)) == ERANGE) {
-                       len *= 2;
-                       buf = g_renew (char, buf, len);
-               }
-
-               if (res || result == NULL || result->h_name == NULL)
-                       result = NULL;
-       }
-#elif defined(HAVE_GETHOSTBYNAME_R_SOLARIS)
-       {
-               size_t len;
-               int herr, res;
-
-               len = 1024;
-               buf = g_new (char, len);
-
-               while ((res = gethostbyaddr_r (addr,
-                                              length,
-                                              ia->family,
-                                              &result_buf,
-                                              buf,
-                                              len,
-                                              &herr)) == ERANGE) {
-                       len *= 2;
-                       buf = g_renew (char, buf, len);
-               }
-
-               if (res)
-                       result = NULL;
-       }
-#elif defined(HAVE_GETHOSTBYNAME_R_HPUX)
-       {
-               struct hostent_data hdbuf;
-
-               if (!gethostbyaddr_r (addr, length, ia->family, &result_buf, &hdbuf))
-                       result = NULL;
-       }
-#else
-       {
-#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX)
-               G_LOCK (gethostbyname);
-#endif
-               result = gethostbyaddr (addr, length, ia->family);
-       }
-#endif
-
-       if (result)
-               rv = g_strdup (result->h_name);
-       else
-               rv = NULL;
-       if (buf)
-               g_free (buf);
-#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX)
-       G_UNLOCK (gethostbyname);
-#endif
-
-       return rv;
-}
-
-#define NOT_CACHED 0
-#define CACHE_OK 1
-#define MARKED_FOR_DELETE 2
-
-static gboolean
-soup_address_new_cb (GIOChannel* iochannel,
-                    GIOCondition condition,
-                    gpointer data)
+static void
+soup_address_new_cb (SoupDNSHandle handle, SoupKnownErrorCode status,
+                    struct hostent *h, gpointer data)
 {
        SoupAddressLookupState *state = (SoupAddressLookupState*) data;
-       SoupAddress *ia;
-       struct sockaddr *sa;
-       int sa_len;
-       GSList *iter;
-
-       if (!(condition & G_IO_IN)) {
-               int ret;
-
-               g_source_remove (state->watch);
-               close (state->fd);
-               while (waitpid (state->pid, &ret, 0) == -1 && errno == EINTR)
-                       ;
-
-               if (WIFSIGNALED (ret) || WEXITSTATUS (ret) != 1) 
-                       goto ERROR;
-
-               /* 
-                * Exit status of one means we are inside a debugger.
-                * Resolve the name synchronously.
-                */
-               if (!soup_gethostbyname (state->name, &sa, &sa_len))
-                       g_warning ("Problem resolving host name");
-       } else {
-               int rv;
-               char* buf;
-               int length;
-
-               buf = &state->buffer [state->len];
-               length = sizeof (state->buffer) - state->len;
-               if (length == 0) goto ERROR;
-
-               rv = read (state->fd, buf, length);
-               if (rv < 0) goto ERROR;
-
-               state->len += rv;
-
-               /* Return true if there's more to read */
-               if ((state->len - 1) != state->buffer [0]) return TRUE;
-
-               if (state->len < 2) 
-                       goto ERROR;
-
-               /* Success. Copy resolved address. */
-               sa = g_malloc (state->len - 1);
-               memcpy (sa, state->buffer + 1, state->len - 1);
-
-               /* Cleanup state */
-               g_source_remove (state->watch);
-               close (state->fd);
-
-               /* FIXME: Wait for HUP signal before doing this */
-               while (waitpid (state->pid, NULL, 0) == -1 && errno == EINTR)
-                       ;
-       }
+       SoupAddress *addr = NULL;
 
-       g_hash_table_remove (lookup_hash, state->name);
+       if (status == SOUP_ERROR_OK)
+               addr = new_address (h->h_name, h->h_addrtype, h->h_addr);
 
-       ia = soup_address_new_from_sockaddr (sa, NULL);
-       g_free (sa);
-       ia->name = state->name;
-       ia->cached = CACHE_OK;
-       g_hash_table_insert (address_hash, ia->name, ia);
-
-       for (iter = state->cb_list; iter; iter = iter->next) {
-               SoupAddressCbData *cb = iter->data;
-
-               soup_address_ref (ia);
-               (*cb->func) (ia, SOUP_ADDRESS_STATUS_OK, cb->data);
-
-               g_free (cb);
-       }
-       g_slist_free (state->cb_list);
+       state->func (addr, 
+                    addr ? SOUP_ADDRESS_STATUS_OK : SOUP_ADDRESS_STATUS_ERROR,
+                    state->data);
        g_free (state);
-
-       /* Each callback got its own ref, but we still own the
-        * original ref.
-        */
-       soup_address_unref (ia);
-       return FALSE;
-
- ERROR:
-       /* Remove the watch now in case we don't return immediately */
-       g_source_remove (state->watch);
-
-       /* Error out and cancel each pending lookup. When the
-        * last one is canceled, state will be freed.
-        */
-       for (iter = state->cb_list; iter; ) {
-               SoupAddressCbData *cb_data = iter->data;
-
-               (*cb_data->func) (NULL,
-                                 SOUP_ADDRESS_STATUS_ERROR,
-                                 cb_data->data);
-
-               iter = iter->next;                
-               soup_address_new_cancel (cb_data);
-       }
-
-       return FALSE;
 }
 
 /**
  * soup_address_new:
  * @name: a nice name (eg, mofo.eecs.umich.edu) or a dotted decimal name
- *   (eg, 141.213.8.59).  You can delete the after the function is called.
+ *   (eg, 141.213.8.59).
  * @func: Callback function.
  * @data: User data passed when callback function is called.
  *
- * Create a SoupAddress from a name asynchronously.  Once the
- * structure is created, it will call the callback.  It may call the
- * callback before the function returns.  It will call the callback
- * if there is a failure.
+ * Create a SoupAddress from a name asynchronously. Once the structure
+ * is created, it will call the callback. It will call the callback if
+ * there is a failure.
  *
  * Currently this routine forks and does the lookup, which can cause
  * some problems. In general, this will work ok for most programs most
@@ -809,228 +473,22 @@ soup_address_new_cb (GIOChannel* iochannel,
  * explosion of processes.
  *
  * Returns: ID of the lookup which can be used with
- * soup_address_new_cancel() to cancel it; NULL on immediate
- * success or failure.
+ * soup_address_new_cancel() to cancel it;
  **/
 SoupAddressNewId
-soup_address_new (const gchar* name, SoupAddressNewFn func, gpointer data)
+soup_address_new (const char *name, SoupAddressNewFn func, gpointer data)
 {
-       pid_t pid = -1;
-       int pipes [2];
-       struct in_addr inaddr;
-#ifdef HAVE_IPV6
-       struct in6_addr inaddr6;
-#endif
-       struct sockaddr *sa;
-       int sa_len;
-       SoupAddress *ia;
        SoupAddressLookupState *state;
-       SoupAddressCbData *cb_data;
-       GIOChannel *chan;
-       int inaddr_ok;
 
        g_return_val_if_fail (name != NULL, NULL);
        g_return_val_if_fail (func != NULL, NULL);
 
-       /* Try to read the name as if were dotted decimal */
-       inaddr_ok = FALSE;
+       state = g_new0 (SoupAddressLookupState, 1);
+       state->func = func;
+       state->data = data;
+       state->handle = soup_gethostbyname (name, soup_address_new_cb, state);
 
-#if defined(HAVE_INET_PTON)
-#ifdef HAVE_IPV6
-       if (inet_pton (AF_INET6, name, &inaddr6) != 0)
-               inaddr_ok = AF_INET6;
-       else
-#endif
-       if (inet_pton (AF_INET, name, &inaddr) != 0)
-               inaddr_ok = AF_INET;
-#elif defined(HAVE_INET_ATON)
-       if (inet_aton (name, &inaddr) != 0)
-               inaddr_ok = AF_INET;
-#else
-       inaddr.s_addr = inet_addr (name);
-       if (inaddr.s_addr == INADDR_NONE)
-               inaddr_ok = FALSE;
-       else
-               inaddr_ok = AF_INET;
-#endif
-
-       if (inaddr_ok) {
-               ia = g_new0 (SoupAddress, 1);
-               ia->ref_count = 1;
-
-               ia->family = inaddr_ok;
-               switch (ia->family) {
-               case AF_INET:
-                       memcpy (&ia->addr.in, &inaddr, sizeof (ia->addr.in));
-                       break;
-#ifdef HAVE_IPV6
-               case AF_INET6:
-                       memcpy (&ia->addr.in6, &inaddr6, sizeof (ia->addr.in6));
-                       break;
-#endif
-               }
-
-               (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
-               return NULL;
-       }
-
-       if (!address_hash) {
-               address_hash = g_hash_table_new (soup_str_case_hash,
-                                                soup_str_case_equal);
-       } else {
-               ia = g_hash_table_lookup (address_hash, name);
-               if (ia) {
-                       soup_address_ref (ia);
-                       (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
-                       return NULL;
-               }
-       }
-
-       if (!lookup_hash) {
-               lookup_hash = g_hash_table_new (soup_str_case_hash,
-                                               soup_str_case_equal);
-       } else {
-               state = g_hash_table_lookup (lookup_hash, name);
-               if (state) {
-                       cb_data = g_new0 (SoupAddressCbData, 1);
-                       cb_data->state = state;
-                       cb_data->func = func;
-                       cb_data->data = data;
-
-                       state->cb_list = g_slist_prepend (state->cb_list,
-                                                         cb_data);
-                       return cb_data;
-               }
-       }
-
-       /* Check to see if we are doing synchronous DNS lookups */
-       if (getenv ("SOUP_SYNC_DNS")) {
-               if (!soup_gethostbyname (name, &sa, &sa_len)) {
-                       g_warning ("Problem resolving host name");
-                       (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
-                       return NULL;
-               }
-
-               ia = soup_address_new_from_sockaddr (sa, NULL);
-               g_free (sa);
-
-               (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
-               return NULL;
-       }
-
-       /* That didn't work - we need to fork */
-
-       /* Open a pipe */
-       if (pipe (pipes) == -1) {
-               (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
-               return NULL;
-       }
-
- FORK_AGAIN:
-       errno = 0;
-       pid = fork ();
-
-       switch (pid) {
-       case -1:
-               if (errno == EAGAIN) {
-                       /* Yield the processor */
-                       sleep(0);
-                       goto FORK_AGAIN;
-               }
-
-               /* Else there was a goofy error */
-               g_warning ("Fork error: %s (%d)\n",
-                          g_strerror (errno),
-                          errno);
-               close (pipes [0]);
-               close (pipes [1]);
-
-               (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
-
-               return NULL;
-       case 0:
-               close (pipes [0]);
-
-#ifdef SOUP_PTRACE_ATTACH
-               signal (SIGCHLD, SIG_IGN);
-
-               if (ptrace (SOUP_PTRACE_ATTACH, getppid (), NULL, NULL) == -1) {
-                       /* 
-                        * Attach failed; it's probably already being
-                        * debugged. 
-                        */
-                       if (errno != EPERM)
-                               g_warning ("ptrace: Unexpected error: %s",
-                                          strerror(errno));
-
-                       _exit (1);
-               }
-
-               /* 
-                * Wait for the SIGSTOP from PTRACE_ATTACH to arrive at the
-                * parent.  
-                */
-               while (waitpid (getppid (), NULL, WUNTRACED) == -1 && errno == EINTR)
-                       ;
-
-               if (ptrace (SOUP_PTRACE_DETACH, getppid (), NULL, NULL) == -1)
-                       g_warning ("ptrace: Detach failed: %s", 
-                                  strerror(errno));
-
-               kill (getppid(), SIGCONT);
-#endif /*SOUP_PTRACE_ATTACH*/
-
-               /* 
-                * Try to get the host by name (ie, DNS) 
-                */
-               if (soup_gethostbyname (name, &sa, &sa_len)) {
-                       guchar size = sa_len;
-
-                       if ((write (pipes [1], &size, sizeof(guchar)) == -1) ||
-                           (write (pipes [1], sa, sa_len) == -1))
-                               g_warning ("Problem writing to pipe\n");
-               } else {
-                       /* Write a zero */
-                       guchar zero = 0;
-
-                       if (write (pipes [1], &zero, sizeof(zero)) == -1)
-                               g_warning ("Problem writing to pipe\n");
-               }
-
-               /* Close the socket */
-               close (pipes [1]);
-
-               /* Exit (we don't want atexit called, so do _exit instead) */
-               _exit (EXIT_SUCCESS);
-       default:
-               close (pipes [1]);
-               
-               /* Create a structure for the call back */
-               state = g_new0 (SoupAddressLookupState, 1);
-               state->name = g_strdup (name);
-               state->pid = pid;
-               state->fd = pipes [0];
-
-               cb_data = g_new0 (SoupAddressCbData, 1);
-               cb_data->state = state;
-               cb_data->func = func;
-               cb_data->data = data;
-               state->cb_list = g_slist_prepend (state->cb_list, cb_data);
-
-               g_hash_table_insert (lookup_hash, state->name, state);
-
-               /* Set up a watch to read from the pipe */
-               chan = g_io_channel_unix_new (pipes [0]);
-               state->watch =
-                       g_io_add_watch(
-                               chan,
-                               G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
-                               soup_address_new_cb,
-                               state);
-               g_io_channel_unref (chan);
-
-               return cb_data;
-       }
+       return state;
 }
 
 /**
@@ -1043,310 +501,65 @@ soup_address_new (const gchar* name, SoupAddressNewFn func, gpointer data)
 void
 soup_address_new_cancel (SoupAddressNewId id)
 {
-       SoupAddressCbData *cb_data = (SoupAddressCbData *)id;
-       SoupAddressLookupState *state;
-       GSList *iter;
-
-       g_return_if_fail (cb_data != NULL);
-
-       state = cb_data->state;
-
-       for (iter = state->cb_list; iter; iter = iter->next) {
-               if (iter->data == cb_data)
-                       break;
-       }
-       g_return_if_fail (iter != NULL);
-
-       state->cb_list = g_slist_remove_link (state->cb_list, iter);
-       g_slist_free_1 (iter);
-       g_free (cb_data);
-
-       if (!state->cb_list) {
-               g_hash_table_remove (lookup_hash, state->name);
-               g_free (state->name);
-
-               g_source_remove (state->watch);
-               close (state->fd);
-               kill (state->pid, SIGKILL);
-               while (waitpid (state->pid, NULL, 0) == -1 && errno == EINTR)
-                       ;
-
-               g_free (state);
-       }
-}
-
-static gboolean 
-prune_zeroref_addresses_foreach (gchar       *hostname,
-                                SoupAddress *ia,
-                                gint        *remaining)
-{
-       /*
-        * References exist, clear mark.
-        */
-       if (ia->ref_count != 0) {
-               ia->cached = CACHE_OK;
-               return FALSE;
-       }
-
-       /*
-        * Kill if marked.  Otherwise mark.
-        */
-       if (ia->cached == MARKED_FOR_DELETE) {
-               g_free (ia->name);
-               g_free (ia);
-               return TRUE;
-       } else
-               ia->cached = MARKED_FOR_DELETE;
-
-       /*
-        * Make sure the timeout stays around
-        */
-       (*remaining)++;
+       SoupAddressLookupState *state = id;
 
-       return FALSE;
-}
-
-static guint zeroref_address_timeout_tag = 0;
-
-static gboolean 
-prune_zeroref_addresses_timeout (gpointer not_used)
-{
-       gint remaining = 0;
-
-       if (!address_hash)
-               goto REMOVE_SOURCE;
-
-       /*
-        * Remove all marked addresses, mark zero references.
-        */
-       g_hash_table_foreach_remove (address_hash, 
-                                    (GHRFunc) prune_zeroref_addresses_foreach,
-                                    &remaining);
-
-       /*
-        * No new marks, so remove timeout handler
-        */
-       if (remaining == 0) 
-               goto REMOVE_SOURCE;
-
-       return TRUE;
-
- REMOVE_SOURCE:
-       zeroref_address_timeout_tag = 0;
-       return FALSE;
+       soup_gethostby_cancel (state->handle);
+       g_free (state);
 }
 
-/**
- * soup_address_unref
- * @ia: SoupAddress to unreference
- *
- * Remove a reference from the SoupAddress.  When reference count
- * reaches 0, the address is deleted.
- **/
-void
-soup_address_unref (SoupAddress* ia)
+static void
+soup_address_get_name_cb (SoupDNSHandle handle, SoupKnownErrorCode status,
+                         struct hostent *h, gpointer data)
 {
-       g_return_if_fail (ia != NULL);
-
-       --ia->ref_count;
-
-       if (ia->ref_count == 0) {
-               if (ia->cached == NOT_CACHED) {
-                       g_free (ia->name);
-                       g_free (ia);
-               }
-               else if (!zeroref_address_timeout_tag) {
-                       /* 
-                        * Cleanup zero reference addresses every 2 minutes.
-                        *
-                        * This involves an initial sweep to mark zero reference
-                        * addresses, then on the next sweep marked addresses
-                        * still not referenced are freed.
-                        */
-                       zeroref_address_timeout_tag = 
-                               g_timeout_add (120000, 
-                                              (GSourceFunc) 
-                                              prune_zeroref_addresses_timeout,
-                                              NULL);
-               }
-       }
-}
+       SoupAddressReverseState *state = data;
 
-static gboolean
-soup_address_get_name_cb (GIOChannel* iochannel,
-                         GIOCondition condition,
-                         gpointer data)
-{
-       SoupAddressReverseState* state = data;
-
-       g_return_val_if_fail (state != NULL, FALSE);
-
-       /* Read from the pipe */
-       if (condition & G_IO_IN) {
-               int rv;
-               char* buf;
-               int length;
-
-               buf = &state->buffer [state->len];
-               length = sizeof(state->buffer) - state->len;
-
-               if ((rv = read (state->fd, buf, length)) >= 0) {
-                       state->len += rv;
-
-                       /* Return true if there's more to read */
-                       if ((state->len - 1) != state->buffer [0])
-                               return TRUE;
-
-                       /* Copy the name */
-                       state->ia->name = g_strndup (&state->buffer [1], 
-                                                    state->buffer [0]);
-
-                       /* Remove the watch now in case we don't return
-                           immediately */
-                       g_source_remove (state->watch);
-
-                       /* Call back */
-                       (*state->func) (state->ia,
-                                       SOUP_ADDRESS_STATUS_OK,
-                                       state->ia->name,
-                                       state->data);
-
-                       close (state->fd);
-                       while (waitpid (state->pid, NULL, 0) == -1 && errno == EINTR)
-                               ;
-                       g_free (state);
-                       return FALSE;
-               }
-       }
+       if (status == SOUP_ERROR_OK && !state->addr->priv->name)
+               state->addr->priv->name = g_strdup (h->h_name);
 
-       /* Remove the watch now in case we don't return immediately */
-       g_source_remove (state->watch);
+       state->func (state->addr, 
+                    state->addr->priv->name ? SOUP_ADDRESS_STATUS_OK : SOUP_ADDRESS_STATUS_ERROR,
+                    state->addr->priv->name,
+                    state->data);
 
-       /* Call back */
-       (*state->func) (state->ia,
-                       SOUP_ADDRESS_STATUS_ERROR,
-                       NULL,
-                       state->data);
-       soup_address_get_name_cancel (state);
-       return FALSE;
+       g_object_unref (state->addr);
+       g_free (state);
 }
 
 /**
  * soup_address_get_name:
- * @ia: Address to get the name of.
+ * @addr: Address to get the name of.
  * @func: Callback function.
  * @data: User data passed when callback function is called.
  *
  * Get the nice name of the address (eg, "mofo.eecs.umich.edu").
- * This function will use the callback once it knows the nice name.
- * It may even call the callback before it returns.  The callback
- * will be called if there is an error.
+ * This function will use the callback once it knows the nice name
+ * or if there is an error.
  *
  * As with soup_address_new(), this forks to do the lookup.
  *
  * Returns: ID of the lookup which can be used with
- * soup_address_get_name_cancel() to cancel it; NULL on
- * immediate success or failure.
+ * soup_address_get_name_cancel() to cancel it;
  **/
 SoupAddressGetNameId
-soup_address_get_name (SoupAddress*         ia,
-                      SoupAddressGetNameFn func,
-                      gpointer             data)
+soup_address_get_name (SoupAddress          *addr,
+                      SoupAddressGetNameFn  func,
+                      gpointer              data)
 {
-       SoupAddressReverseState* state;
-       gchar* name;
-       guchar len;
-       pid_t pid = -1;
-       int pipes [2], lenint;
+       SoupAddressReverseState *state;
 
-       g_return_val_if_fail (ia != NULL, NULL);
+       g_return_val_if_fail (SOUP_IS_ADDRESS (addr), NULL);
        g_return_val_if_fail (func != NULL, NULL);
 
-       if (ia->name) {
-               (func) (ia, SOUP_ADDRESS_STATUS_OK, ia->name, data);
-               return NULL;
-       }
-
-       /* FIXME: should check SOUP_SYNC_DNS here */
-
-       /* Open a pipe */
-       if (pipe (pipes) != 0) {
-               (func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
-               return NULL;
-       }
-
- FORK_AGAIN:
-       errno = 0;
-       pid = fork ();
-
-       switch (pid) {
-       case -1:
-               if (errno == EAGAIN) {
-                       /* Yield the processor */
-                       sleep(0);
-                       goto FORK_AGAIN;
-               }
+       state = g_new0 (SoupAddressReverseState, 1);
+       state->addr = g_object_ref (addr);
+       state->func = func;
+       state->data = data;
+       state->handle = soup_gethostbyaddr (&addr->priv->addr,
+                                           addr->priv->family,
+                                           soup_address_get_name_cb,
+                                           state);
 
-               close(pipes[0]);
-               close(pipes[1]);
-
-               /* Else there was a goofy error */
-               g_warning ("Fork error: %s (%d)\n",
-                          g_strerror(errno),
-                          errno);
-
-               (*func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
-
-               return NULL;
-       case 0:
-               close(pipes[0]);
-
-               /* Write the name to the pipe.  If we didn't get a name,
-                  we just write the canonical name. */
-               name = soup_gethostbyaddr (ia);
-               if (!name)
-                       name = soup_address_get_canonical_name (ia);
-
-               lenint = strlen (name);
-               if (lenint > 255) {
-                       g_warning ("Truncating domain name: %s\n", name);
-                       name [256] = '\0';
-                       lenint = 255;
-               }
-
-               len = lenint;
-
-               if ((write (pipes [1], &len, sizeof(len)) == -1) ||
-                   (write (pipes [1], name, len) == -1) )
-                       g_warning ("Problem writing to pipe\n");
-
-               g_free(name);
-
-               /* Close the socket */
-               close(pipes [1]);
-
-               /* Exit (we don't want atexit called, so do _exit instead) */
-               _exit(EXIT_SUCCESS);
-       default:
-               close(pipes[1]);
-
-               soup_address_ref (ia);
-
-               state = g_new0 (SoupAddressReverseState, 1);
-               state->ia = ia;
-               state->func = func;
-               state->data = data;
-               state->pid = pid;
-               state->fd = pipes [0];
-
-               /* Add a watch */
-               state->watch =
-                       g_io_add_watch(g_io_channel_unix_new (pipes [0]),
-                                      G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
-                                      soup_address_get_name_cb,
-                                      state);
-               return state;
-       }
+       return state;
 }
 
 /**
@@ -1359,18 +572,11 @@ soup_address_get_name (SoupAddress*         ia,
 void
 soup_address_get_name_cancel (SoupAddressGetNameId id)
 {
-       SoupAddressReverseState* state;
-       state = (SoupAddressReverseState*) id;
-
-       g_return_if_fail(state != NULL);
-
-       soup_address_unref (state->ia);
-       g_source_remove (state->watch);
+       SoupAddressReverseState *state = id;
 
-       close (state->fd);
-       kill (state->pid, SIGKILL);
-       while (waitpid (state->pid, NULL, 0) == -1 && errno == EINTR)
-               ;
+       g_return_if_fail (state != NULL);
 
+       soup_gethostby_cancel (state->handle);
+       g_object_unref (state->addr);
        g_free(state);
 }
index 1654e1e..1c2b9f8 100644 (file)
@@ -1,22 +1,37 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * Authors:
- *      David Helder  (dhelder@umich.edu)
- *      Alex Graveley (alex@ximian.com)
- * 
- * Original code compliments of David Helder's GNET Networking Library.
- *
- * Copyright (C) 2000-2002, Ximian, Inc.
+ * Copyright (C) 2000-2003, Ximian, Inc.
  */
 
 #ifndef SOUP_ADDRESS_H
 #define SOUP_ADDRESS_H
 
-#include <glib.h>
+#include <glib-object.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 
-typedef struct _SoupAddress SoupAddress;
+#define SOUP_TYPE_ADDRESS            (soup_address_get_type ())
+#define SOUP_ADDRESS(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_ADDRESS, SoupAddress))
+#define SOUP_ADDRESS_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_ADDRESS, SoupAddressClass))
+#define SOUP_IS_ADDRESS(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_ADDRESS))
+#define SOUP_IS_ADDRESS_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_ADDRESS))
+#define SOUP_ADDRESS_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_ADDRESS, SoupAddressClass))
+
+typedef struct SoupAddressPrivate SoupAddressPrivate;
+
+typedef struct {
+       GObject parent;
+
+       SoupAddressPrivate *priv;
+} SoupAddress;
+
+typedef struct {
+       GObjectClass parent_class;
+
+} SoupAddressClass;
+
+GType soup_address_get_type (void);
+
 
 typedef gpointer SoupAddressNewId;
 
@@ -29,53 +44,48 @@ typedef void (*SoupAddressNewFn) (SoupAddress       *inetaddr,
                                  SoupAddressStatus  status, 
                                  gpointer           user_data);
 
-SoupAddressNewId     soup_address_new                (const gchar*       name, 
+SoupAddressNewId     soup_address_new                (const char        *name, 
                                                      SoupAddressNewFn   func, 
                                                      gpointer           data);
 
 void                 soup_address_new_cancel         (SoupAddressNewId   id);
 
-SoupAddress         *soup_address_new_sync           (const gchar       *name);
+SoupAddress         *soup_address_new_sync           (const char        *name);
 
 SoupAddress         *soup_address_ipv4_any           (void);
 SoupAddress         *soup_address_ipv6_any           (void);
 
-void                 soup_address_ref                (SoupAddress*       ia);
-
-void                 soup_address_unref              (SoupAddress*       ia);
-
-SoupAddress *        soup_address_copy               (SoupAddress*       ia);
-
 
 typedef gpointer SoupAddressGetNameId;
 
 typedef void (*SoupAddressGetNameFn) (SoupAddress       *inetaddr, 
                                      SoupAddressStatus  status, 
-                                     const gchar       *name,
+                                     const char        *name,
                                      gpointer           user_data);
 
-SoupAddressGetNameId soup_address_get_name           (SoupAddress*         ia, 
-                                                     SoupAddressGetNameFn func,
-                                                     gpointer             data);
+SoupAddressGetNameId
+             soup_address_get_name           (SoupAddress          *addr, 
+                                             SoupAddressGetNameFn  func,
+                                             gpointer              data);
 
-void                 soup_address_get_name_cancel    (SoupAddressGetNameId id);
+void         soup_address_get_name_cancel    (SoupAddressGetNameId  id);
 
-const gchar         *soup_address_get_name_sync      (SoupAddress *addr);
+const char  *soup_address_get_name_sync      (SoupAddress          *addr);
 
-gchar*               soup_address_get_canonical_name (SoupAddress*         ia);
+char        *soup_address_get_canonical_name (SoupAddress          *addr);
 
 
-SoupAddress         *soup_address_new_from_sockaddr  (struct sockaddr   *sa,
-                                                     guint             *port);
+SoupAddress *soup_address_new_from_sockaddr  (struct sockaddr      *sa,
+                                             guint                *port);
 
-void                 soup_address_make_sockaddr      (SoupAddress       *ia,
-                                                     guint              port,
-                                                     struct sockaddr  **sa,
-                                                     int               *len);
+void         soup_address_make_sockaddr      (SoupAddress          *addr,
+                                             guint                 port,
+                                             struct sockaddr     **sa,
+                                             int                  *len);
 
-guint                soup_address_hash               (const gpointer     p);
+guint        soup_address_hash               (const gpointer        p);
 
-gint                 soup_address_equal              (const gpointer     p1, 
-                                                     const gpointer     p2);
+gint         soup_address_equal              (const gpointer        p1, 
+                                             const gpointer        p2);
 
 #endif /* SOUP_ADDRESS_H */
index c9418f0..6f79a04 100644 (file)
@@ -270,7 +270,7 @@ connection_free (SoupConnection *conn)
 
        g_io_channel_unref (conn->channel);
        soup_context_unref (conn->context);
-       soup_socket_unref (conn->socket);
+       g_object_unref (conn->socket);
        if (conn->death_tag)
                g_source_remove (conn->death_tag);
        g_free (conn);
diff --git a/libsoup/soup-dns.c b/libsoup/soup-dns.c
new file mode 100644 (file)
index 0000000..3520541
--- /dev/null
@@ -0,0 +1,680 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-dns.c: Async DNS code
+ *
+ * Copyright (C) 2000-2003, Ximian, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/wait.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include "soup-dns.h"
+#include "soup-private.h"
+
+#ifndef socklen_t
+#  define socklen_t int
+#endif
+
+#ifndef INET_ADDRSTRLEN
+#  define INET_ADDRSTRLEN 16
+#  define INET6_ADDRSTRLEN 46
+#endif
+
+#ifndef INADDR_NONE
+#define INADDR_NONE -1
+#endif
+
+static struct hostent *
+new_hostent (const char *name, int type, int length, gpointer addr)
+{
+       struct hostent *h;
+
+       h = g_new0 (struct hostent, 1);
+       h->h_name = g_strdup (name);
+       h->h_aliases = NULL;
+       h->h_addrtype = type;
+       h->h_length = length;
+       h->h_addr_list = g_new (char *, 2);
+       h->h_addr_list[0] = g_memdup (addr, length);
+       h->h_addr_list[1] = NULL;
+
+       return h;
+}
+
+static struct hostent *
+copy_hostent (struct hostent *h)
+{
+       return new_hostent (h->h_name, h->h_addrtype,
+                           h->h_length, h->h_addr_list[0]);
+}
+
+static void
+free_hostent (struct hostent *h)
+{
+       g_free (h->h_name);
+       g_free (h->h_addr_list[0]);
+       g_free (h->h_addr_list);
+       g_free (h);
+}
+
+static void
+write_hostent (struct hostent *h, int fd)
+{
+       guchar namelen = strlen (h->h_name) + 1;
+       guchar addrlen = h->h_length;
+       guchar addrtype = h->h_addrtype;
+       struct iovec iov[5];
+
+       iov[0].iov_base = &namelen;
+       iov[0].iov_len = 1;
+       iov[1].iov_base = h->h_name;
+       iov[1].iov_len = namelen;
+       iov[2].iov_base = &addrtype;
+       iov[2].iov_len = 1;
+       iov[3].iov_base = &addrlen;
+       iov[3].iov_len = 1;
+       iov[4].iov_base = h->h_addr_list[0];
+       iov[4].iov_len = addrlen;
+
+       if (writev (fd, iov, 5) == -1)
+               g_warning ("Problem writing to pipe");
+}
+
+static struct hostent *
+new_hostent_from_phys (const char *addr)
+{
+       struct in_addr inaddr;
+#ifdef HAVE_IPV6
+       struct in6_addr inaddr6;
+#endif
+
+#if defined(HAVE_INET_PTON)
+#ifdef HAVE_IPV6
+       if (inet_pton (AF_INET6, addr, &inaddr6) != 0)
+               return new_hostent (addr, AF_INET6, sizeof (inaddr6), &inaddr6);
+       else
+#endif
+       if (inet_pton (AF_INET, addr, &inaddr) != 0)
+               return new_hostent (addr, AF_INET, sizeof (inaddr), &inaddr);
+#elif defined(HAVE_INET_ATON)
+       if (inet_aton (addr, &inaddr) != 0)
+               return new_hostent (addr, AF_INET, sizeof (inaddr), &inaddr);
+#else
+       inaddr.s_addr = inet_addr (addr);
+       if (inaddr.s_addr != INADDR_NONE)
+               return new_hostent (addr, AF_INET, sizeof (inaddr), &inaddr);
+#endif
+
+       return NULL;
+}
+
+char *
+soup_ntop (gpointer addr, int family)
+{
+       switch (family) {
+       case AF_INET:
+       {
+#ifdef HAVE_INET_NTOP
+               char buffer[INET_ADDRSTRLEN];
+
+               inet_ntop (family, addr, buffer, sizeof (buffer));
+               return g_strdup (buffer);
+#else
+               return g_strdup (inet_ntoa (*(struct in_addr *)addr));
+#endif
+       }
+
+#ifdef HAVE_IPV6
+       case AF_INET6:
+       {
+               char buffer[INET6_ADDRSTRLEN];
+
+               inet_ntop (family, addr, buffer, sizeof (buffer));
+               return g_strdup (buffer);
+       }
+#endif
+
+       default:
+               return NULL;
+       }
+}
+
+
+/* Testing Defines */
+/*  #undef   HAVE_GETHOSTBYNAME_R_GLIBC */
+/*  #define  HAVE_GETHOSTBYNAME_R_GLIB_MUTEX */
+
+#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
+G_LOCK_DEFINE (gethostbyname);
+#endif
+
+static struct hostent *
+soup_gethostbyname_internal (const char *hostname)
+{
+       struct hostent result_buf, *result = &result_buf, *out;
+       char *buf = NULL;
+
+#if defined(HAVE_GETHOSTBYNAME_R_GLIBC)
+       {
+               size_t len;
+               int herr, res;
+
+               len = 1024;
+               buf = g_new (char, len);
+
+               while ((res = gethostbyname_r (hostname,
+                                              &result_buf,
+                                              buf,
+                                              len,
+                                              &result,
+                                              &herr)) == ERANGE) {
+                       len *= 2;
+                       buf = g_renew (char, buf, len);
+               }
+
+               if (res || result == NULL || result->h_addr_list [0] == NULL)
+                       result = NULL;
+       }
+#elif defined(HAVE_GETHOSTBYNAME_R_SOLARIS)
+       {
+               size_t len;
+               int herr, res;
+
+               len = 1024;
+               buf = g_new (char, len);
+
+               while ((res = gethostbyname_r (hostname,
+                                              &result_buf,
+                                              buf,
+                                              len,
+                                              &herr)) == ERANGE) {
+                       len *= 2;
+                       buf = g_renew (char, buf, len);
+               }
+
+               if (res)
+                       result = NULL;
+       }
+#elif defined(HAVE_GETHOSTBYNAME_R_HPUX)
+       {
+               struct hostent_data hdbuf;
+
+               if (!gethostbyname_r (hostname, &result_buf, &hdbuf))
+                       result = NULL;
+       }
+#else
+       {
+#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX)
+               G_LOCK (gethostbyname);
+#endif
+               result = gethostbyname (hostname);
+       }
+#endif
+
+       if (result)
+               out = copy_hostent (result);
+       else
+               out = NULL;
+
+       if (buf)
+               g_free (buf);
+#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX)
+       G_UNLOCK (gethostbyname);
+#endif
+
+       return out;
+}
+
+static struct hostent *
+soup_gethostbyaddr_internal (gpointer addr, int family)
+{
+       struct hostent result_buf, *result = &result_buf, *out;
+       char *buf = NULL;
+       int length;
+
+       switch (family) {
+       case AF_INET:
+               length = sizeof (struct in_addr);
+               break;
+#ifdef HAVE_IPV6
+       case AF_INET6:
+               length = sizeof (struct in6_addr);
+               break;
+#endif
+       default:
+               return NULL;
+       }
+
+#if defined(HAVE_GETHOSTBYNAME_R_GLIBC)
+       {
+               size_t len;
+               int herr, res;
+
+               len = 1024;
+               buf = g_new (char, len);
+
+               while ((res = gethostbyaddr_r (addr,
+                                              length,
+                                              family,
+                                              &result_buf,
+                                              buf,
+                                              len,
+                                              &result,
+                                              &herr)) == ERANGE) {
+                       len *= 2;
+                       buf = g_renew (char, buf, len);
+               }
+
+               if (res || result == NULL || result->h_name == NULL)
+                       result = NULL;
+       }
+#elif defined(HAVE_GETHOSTBYNAME_R_SOLARIS)
+       {
+               size_t len;
+               int herr, res;
+
+               len = 1024;
+               buf = g_new (char, len);
+
+               while ((res = gethostbyaddr_r (addr,
+                                              length,
+                                              family,
+                                              &result_buf,
+                                              buf,
+                                              len,
+                                              &herr)) == ERANGE) {
+                       len *= 2;
+                       buf = g_renew (char, buf, len);
+               }
+
+               if (res)
+                       result = NULL;
+       }
+#elif defined(HAVE_GETHOSTBYNAME_R_HPUX)
+       {
+               struct hostent_data hdbuf;
+
+               if (!gethostbyaddr_r (addr, length, family, &result_buf, &hdbuf))
+                       result = NULL;
+       }
+#else
+       {
+#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX)
+               G_LOCK (gethostbyname);
+#endif
+               result = gethostbyaddr (addr, length, family);
+       }
+#endif
+
+       if (result)
+               out = copy_hostent (result);
+       else
+               out = NULL;
+
+       if (buf)
+               g_free (buf);
+#if defined(HAVE_GETHOSTBYNAME_R_GLIB_MUTEX)
+       G_UNLOCK (gethostbyname);
+#endif
+
+       return out;
+}
+
+
+/* Cache */
+
+typedef struct {
+       char           *name;
+       struct hostent *h;
+       time_t          expires;
+
+       GSList         *lookups;
+
+       guint           source_id;
+       pid_t           lookup_pid;
+       int             fd;
+} SoupDNSEntry;
+
+static GHashTable *soup_dns_entries;
+#define SOUP_DNS_ENTRIES_MAX 20
+
+static void
+free_entry (SoupDNSEntry *entry)
+{
+       g_hash_table_remove (soup_dns_entries, entry->name);
+       g_free (entry->name);
+       free_hostent (entry->h);
+       g_free (entry);
+}
+
+static void
+prune_cache_cb (gpointer key, gpointer value, gpointer data)
+{
+       SoupDNSEntry *entry = value, **prune_entry = data; 
+
+       if (entry->lookups)
+               return;
+       if (!*prune_entry || (*prune_entry)->expires > entry->expires)
+               *prune_entry = entry;
+}
+
+static void
+cache_entry (SoupDNSEntry *entry)
+{
+       if (!soup_dns_entries) {
+               soup_dns_entries = g_hash_table_new (soup_str_case_hash,
+                                                    soup_str_case_equal);
+       } else if (g_hash_table_size (soup_dns_entries) == SOUP_DNS_ENTRIES_MAX) {
+               SoupDNSEntry *prune_entry = NULL;
+
+               g_hash_table_foreach (soup_dns_entries, prune_cache_cb,
+                                     &prune_entry);
+               if (prune_entry)
+                       free_entry (prune_entry);
+       }
+
+       entry->expires = time (0) + 60 * 60;
+       g_hash_table_insert (soup_dns_entries, entry->name, entry);
+}
+
+static SoupDNSEntry *
+lookup_entry (const char *name)
+{
+       if (!soup_dns_entries)
+               return NULL;
+       return g_hash_table_lookup (soup_dns_entries, name);
+}
+
+
+typedef struct {
+       SoupGetHostByFn  func;
+       gpointer         data;
+
+       SoupDNSEntry    *entry;
+} SoupDNSLookupInfo;
+
+static gboolean
+soup_gothost (gpointer user_data)
+{
+       SoupDNSEntry *entry = user_data;
+       SoupDNSLookupInfo *info;
+
+       if (entry->source_id) {
+               g_source_remove (entry->source_id);
+               entry->source_id = 0;
+       }
+
+       while (entry->lookups) {
+               info = entry->lookups->data;
+               entry->lookups = g_slist_remove (entry->lookups, info);
+
+               /* FIXME: add a CANT_RESOLVE error */
+               (*info->func) (info, entry->h ? SOUP_ERROR_OK : SOUP_ERROR_CANT_CONNECT, entry->h, info->data);
+               g_free (info);
+       }
+
+       return FALSE;
+}
+
+static gboolean
+soup_gethostby_cb (GIOChannel *iochannel,
+                  GIOCondition condition,
+                  gpointer data)
+{
+       SoupDNSEntry *entry = data;
+       char buf[256], *namelenp, *name, *typep, *addrlenp, *addr;
+       int nread;
+
+       if (condition & G_IO_IN)
+               nread = read (entry->fd, buf, sizeof (buf));
+       else
+               nread = 0;
+
+       close (entry->fd);
+       entry->fd = -1;
+       kill (entry->lookup_pid, SIGKILL);
+       waitpid (entry->lookup_pid, NULL, 0);
+       entry->lookup_pid = 0;
+
+       if (nread < 1)
+               return soup_gothost (entry);
+
+       namelenp = buf;
+       name = namelenp + 1;
+       typep = name + *namelenp;
+       addrlenp = typep + 1;
+       addr = addrlenp + 1;
+
+       if (addrlenp < buf + nread && (addr + *addrlenp) == buf + nread)
+               entry->h = new_hostent (name, *typep, *addrlenp, addr);
+       return soup_gothost (entry);
+}
+
+static SoupDNSLookupInfo *
+lookup_info (SoupDNSEntry *entry, SoupGetHostByFn func, gpointer data)
+{
+       SoupDNSLookupInfo *info;
+
+       info = g_new0 (SoupDNSLookupInfo, 1);
+       info->func = func;
+       info->data = data;
+       info->entry = entry;
+       entry->lookups = g_slist_prepend (entry->lookups, info);
+       if (!entry->source_id)
+               entry->source_id = g_idle_add (soup_gothost, entry);
+
+       return info;
+}
+
+/**
+ * soup_gethostbyname:
+ * @name: a nice name (eg, mofo.eecs.umich.edu) or a dotted decimal name
+ *   (eg, 141.213.8.59).
+ * @func: Callback function.
+ * @data: User data passed when @func is called.
+ *
+ * Resolves a DNS name asynchronously. @func will be called with the
+ * result (or an error).
+ *
+ * Currently this routine forks and does the lookup, which can cause
+ * some problems. In general, this will work ok for most programs most
+ * of the time. It will be slow or even fail when using operating
+ * systems that copy the entire process when forking.
+ *
+ * If you need to lookup a lot of addresses, you should call
+ * g_main_iteration(%FALSE) between calls. This will help prevent an
+ * explosion of processes.
+ *
+ * Returns: ID of the lookup which can be used with
+ * soup_gethostbyname_cancel() to cancel it.
+ **/
+SoupDNSHandle
+soup_gethostbyname (const char *name, SoupGetHostByFn func, gpointer data)
+{
+       SoupDNSEntry *entry;
+       int pipes[2];
+       GIOChannel *chan;
+
+       /* Try the cache */
+       entry = lookup_entry (name);
+       if (entry) {
+               if (entry->expires < time (0) && !entry->source_id)
+                       free_entry (entry);
+               else
+                       return lookup_info (entry, func, data);
+       }
+
+       entry = g_new0 (SoupDNSEntry, 1);
+       entry->name = g_strdup (name);
+       cache_entry (entry);
+
+       /* Try to read the name as if it were dotted decimal */
+       entry->h = new_hostent_from_phys (name);
+       if (entry->h)
+               return lookup_info (entry, func, data);
+
+       /* Check to see if we are doing synchronous DNS lookups */
+       if (getenv ("SOUP_SYNC_DNS")) {
+               entry->h = soup_gethostbyname_internal (name);
+               return lookup_info (entry, func, data);
+       }
+
+       /* Ok, we need to start a new lookup */
+
+       if (pipe (pipes) == -1)
+               return lookup_info (entry, func, data);
+
+       entry->lookup_pid = fork ();
+       switch (entry->lookup_pid) {
+       case -1:
+               g_warning ("Fork error: %s (%d)\n", g_strerror (errno), errno);
+               close (pipes[0]);
+               close (pipes[1]);
+
+               return lookup_info (entry, func, data);
+
+       case 0:
+               /* Child */
+               close (pipes[0]);
+
+               entry->h = soup_gethostbyname_internal (name);
+               if (entry->h)
+                       write_hostent (entry->h, pipes[1]);
+
+               /* Close the socket */
+               close (pipes[1]);
+
+               /* Exit (we don't want atexit called, so do _exit instead) */
+               _exit (EXIT_SUCCESS);
+
+       default:
+               /* Parent */
+               close (pipes[1]);
+
+               entry->fd = pipes[0];
+
+               /* Set up a watch to read from the pipe */
+               chan = g_io_channel_unix_new (pipes[0]);
+               entry->source_id =
+                       g_io_add_watch (
+                               chan,
+                               G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+                               soup_gethostby_cb,
+                               entry);
+               g_io_channel_unref (chan);
+
+               return lookup_info (entry, func, data);
+       }
+}
+
+SoupDNSHandle
+soup_gethostbyaddr (gpointer addr, int family,
+                   SoupGetHostByFn func, gpointer data)
+{
+       SoupDNSEntry *entry;
+       int pipes[2];
+       GIOChannel *chan;
+       char *name;
+
+       name = soup_ntop (addr, family);
+       g_return_val_if_fail (name != NULL, NULL);
+
+       /* Try the cache */
+       entry = lookup_entry (name);
+       if (entry) {
+               if (entry->expires > time (0))
+                       free_entry (entry);
+               else {
+                       g_free (name);
+                       return lookup_info (entry, func, data);
+               }
+       }
+
+       entry = g_new0 (SoupDNSEntry, 1);
+       entry->name = name;
+       cache_entry (entry);
+
+       /* Check to see if we are doing synchronous DNS lookups */
+       if (getenv ("SOUP_SYNC_DNS")) {
+               entry->h = soup_gethostbyaddr_internal (addr, family);
+               return lookup_info (entry, func, data);
+       }
+
+       if (pipe (pipes) != 0)
+               return lookup_info (entry, func, data);
+
+       entry->lookup_pid = fork ();
+       switch (entry->lookup_pid) {
+       case -1:
+               close (pipes[0]);
+               close (pipes[1]);
+
+               g_warning ("Fork error: %s (%d)\n", g_strerror(errno), errno);
+               return lookup_info (entry, func, data);
+
+       case 0:
+               /* Child */
+               close (pipes[0]);
+
+               entry->h = soup_gethostbyaddr_internal (addr, family);
+               if (entry->h)
+                       write_hostent (entry->h, pipes[1]);
+
+               /* Close the socket */
+               close (pipes[1]);
+
+               /* Exit (we don't want atexit called, so do _exit instead) */
+               _exit (EXIT_SUCCESS);
+
+       default:
+               /* Parent */
+               close (pipes[1]);
+
+               entry->fd = pipes[0];
+
+               /* Set up a watch to read from the pipe */
+               chan = g_io_channel_unix_new (pipes[0]);
+               entry->source_id =
+                       g_io_add_watch (
+                               chan,
+                               G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
+                               soup_gethostby_cb,
+                               entry);
+               g_io_channel_unref (chan);
+
+               return lookup_info (entry, func, data);
+       }
+}
+
+void
+soup_gethostby_cancel (SoupDNSHandle id)
+{
+       SoupDNSLookupInfo *info = id;
+       SoupDNSEntry *entry = info->entry;
+
+       entry->lookups = g_slist_remove (entry->lookups, info);
+       g_free (info);
+
+       if (!entry->lookups && entry->source_id) {
+               g_source_remove (entry->source_id);
+               if (entry->lookup_pid) {
+                       close (entry->fd);
+                       kill (entry->lookup_pid, SIGKILL);
+                       waitpid (entry->lookup_pid, NULL, 0);
+                       free_entry (entry);
+               }
+       }
+}
diff --git a/libsoup/soup-dns.h b/libsoup/soup-dns.h
new file mode 100644 (file)
index 0000000..4c5c420
--- /dev/null
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * Copyright (C) 2000-2003, Ximian, Inc.
+ */
+
+#ifndef SOUP_DNS_H
+#define SOUP_DNS_H
+
+#include <glib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netdb.h>
+
+#include <libsoup/soup-error.h>
+
+typedef gpointer SoupDNSHandle;
+typedef void   (*SoupGetHostByFn)          (SoupDNSHandle       handle,
+                                           SoupKnownErrorCode  status,
+                                           struct hostent     *h,
+                                           gpointer            user_data);
+
+SoupDNSHandle    soup_gethostbyname        (const char         *name, 
+                                           SoupGetHostByFn     func,
+                                           gpointer            data);
+
+SoupDNSHandle    soup_gethostbyaddr        (gpointer            addr,
+                                           int                 family,
+                                           SoupGetHostByFn     func,
+                                           gpointer            data);
+
+void             soup_gethostby_cancel     (SoupDNSHandle       id);
+
+char            *soup_ntop                 (gpointer            addr,
+                                           int                 family);
+
+#endif /* SOUP_DNS_H */
index d67535c..a65b74f 100644 (file)
@@ -53,11 +53,10 @@ typedef struct {
        GHashTable *auths;            /* KEY: scheme:realm, VALUE: SoupAuth */
 } SoupHost;
 
-struct _SoupSocket {
-       gint            sockfd;
+struct SoupSocketPrivate {
+       int             sockfd;
        SoupAddress    *addr;
        guint           port;
-       guint           ref_count;
        GIOChannel     *iochannel;
 };
 
@@ -159,6 +158,31 @@ gint      soup_substring_index (gchar         *str,
                                gint           len,
                                gchar         *substr);
 
+
+#define SOUP_MAKE_TYPE(l,t,ci,i,parent) \
+GType l##_get_type(void)\
+{\
+       static GType type = 0;                          \
+       if (!type){                                     \
+               static GTypeInfo const object_info = {  \
+                       sizeof (t##Class),              \
+                                                       \
+                       (GBaseInitFunc) NULL,           \
+                       (GBaseFinalizeFunc) NULL,       \
+                                                       \
+                       (GClassInitFunc) ci,            \
+                       (GClassFinalizeFunc) NULL,      \
+                       NULL,   /* class_data */        \
+                                                       \
+                       sizeof (t),                     \
+                       0,      /* n_preallocs */       \
+                       (GInstanceInitFunc) i,          \
+               };                                      \
+               type = g_type_register_static (parent, #t, &object_info, 0); \
+       }                                               \
+       return type;                                    \
+}
+
 #ifdef __cplusplus
 }
 #endif
index 1ce700c..6289394 100644 (file)
@@ -159,7 +159,7 @@ soup_server_unref (SoupServer *serv)
                        g_source_remove (serv->accept_tag);
 
                if (serv->listen_sock)
-                       soup_socket_unref (serv->listen_sock);
+                       g_object_unref (serv->listen_sock);
 
                if (serv->cgi_read_chan)
                        g_io_channel_unref (serv->cgi_read_chan);
@@ -262,7 +262,7 @@ destroy_message (SoupMessage *msg)
                 */
                if (check_close_connection (msg)) {
                        g_io_channel_close (chan);
-                       soup_socket_unref (server_sock);
+                       g_object_unref (server_sock);
                }
                else {
                        /*
@@ -315,6 +315,7 @@ write_done_cb (gpointer user_data)
 {
        SoupMessage *msg = user_data;
 
+       soup_transfer_write_unref (msg->priv->write_tag);
        msg->priv->write_tag = 0;
        destroy_message (msg);
 }
@@ -632,7 +633,7 @@ read_headers_cb (const GString        *headers,
                        SoupSocket *server_sock = msg->priv->server_sock;
                        gchar *host;
 
-                       host = get_server_sockname (server_sock->sockfd);
+                       host = get_server_sockname (server_sock->priv->sockfd);
                        url = 
                                g_strdup_printf (
                                        "%s%s:%d%s",
@@ -862,6 +863,7 @@ read_done_cb (const SoupDataBuffer *data,
        SoupSocket *server_sock = req->priv->server_sock;
        GIOChannel *channel;
 
+       soup_transfer_read_unref (req->priv->read_tag);
        req->priv->read_tag = 0;
 
        call_handler (req, data, soup_context_get_uri (req->context)->path);
@@ -941,12 +943,12 @@ start_another_request (GIOChannel    *serv_chan,
        if (!(condition & G_IO_IN) || 
            ioctl (fd, FIONREAD, &cnt) < 0 ||
            cnt <= 0)
-               soup_socket_unref (data->server_sock);
+               g_object_unref (data->server_sock);
        else {
                msg = message_new (data->server);
                if (!msg) {
                        g_warning ("Unable to create new incoming message\n");
-                       soup_socket_unref (data->server_sock);
+                       g_object_unref (data->server_sock);
                } else {
                        msg->priv->server_sock = data->server_sock;
                        msg->priv->read_tag = 
@@ -986,11 +988,11 @@ conn_accept (GIOChannel    *serv_chan,
        chan = soup_socket_get_iochannel (sock);
 
        if (server->proto == SOUP_PROTOCOL_HTTPS)
-               sock->iochannel = soup_ssl_get_server_iochannel (chan);
+               sock->priv->iochannel = soup_ssl_get_server_iochannel (chan);
 
        msg->priv->server_sock = sock;
        msg->priv->read_tag = 
-               soup_transfer_read (sock->iochannel,
+               soup_transfer_read (sock->priv->iochannel,
                                    FALSE,
                                    read_headers_cb,
                                    NULL,
@@ -1234,7 +1236,7 @@ soup_server_context_get_client_host (SoupServerContext *context)
 
        address = soup_server_context_get_client_address (context);
        host = g_strdup (soup_address_get_canonical_name (address));
-       soup_address_unref (address);
+       g_object_unref (address);
        
        return host;
 }
index 7e07f75..3a5a85c 100644 (file)
@@ -1,15 +1,11 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * soup-socket.c: Platform neutral socket networking code.
+ * soup-socket.c: Socket networking code.
  *
- * Authors:
- *      David Helder  (dhelder@umich.edu)
- *      Alex Graveley (alex@ximian.com)
- *
- * Original code compliments of David Helder's GNET Networking Library, and is
+ * Based on code in David Helder's GNET Networking Library,
  * Copyright (C) 2000  David Helder & Andrew Lanoix.
  *
- * All else Copyright (C) 2000-2002, Ximian, Inc.
+ * All else Copyright (C) 2000-2003, Ximian, Inc.
  */
 
 #ifdef HAVE_CONFIG_H
 #  define socklen_t size_t
 #endif
 
+#define PARENT_TYPE G_TYPE_OBJECT
+static GObjectClass *parent_class;
+
+static void
+init (GObject *object)
+{
+       SoupSocket *sock = SOUP_SOCKET (object);
+
+       sock->priv = g_new0 (SoupSocketPrivate, 1);
+       sock->priv->sockfd = -1;
+}
+
+static void
+finalize (GObject *object)
+{
+       SoupSocket *sock = SOUP_SOCKET (object);
+
+       if (sock->priv->sockfd != -1)
+               close (sock->priv->sockfd);
+
+       if (sock->priv->addr)
+               g_object_unref (sock->priv->addr);
+
+       if (sock->priv->iochannel)
+               g_io_channel_unref (sock->priv->iochannel);
+
+       g_free (sock->priv);
+
+       G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+class_init (GObjectClass *object_class)
+{
+       parent_class = g_type_class_ref (PARENT_TYPE);
+
+       /* virtual method override */
+       object_class->finalize = finalize;
+}
+
+SOUP_MAKE_TYPE (soup_socket, SoupSocket, class_init, init, PARENT_TYPE)
+
+
 typedef struct {
        SoupSocketConnectFn  func;
        gpointer             data;
@@ -39,11 +78,11 @@ typedef struct {
 } SoupSocketConnectState;
 
 static void
-soup_socket_connect_tcp_cb (SoupSocketsocket,
+soup_socket_connect_tcp_cb (SoupSocket *socket,
                            SoupSocketConnectStatus status,
                            gpointer data)
 {
-       SoupSocketConnectStatestate = (SoupSocketConnectState*) data;
+       SoupSocketConnectState *state = (SoupSocketConnectState*) data;
        SoupSocketConnectFn func = state->func;
        gpointer user_data = state->data;
 
@@ -61,17 +100,17 @@ soup_socket_connect_tcp_cb (SoupSocket* socket,
 }
 
 static void
-soup_socket_connect_inetaddr_cb (SoupAddressinetaddr,
+soup_socket_connect_inetaddr_cb (SoupAddress *inetaddr,
                                 SoupAddressStatus status,
                                 gpointer data)
 {
-       SoupSocketConnectStatestate = (SoupSocketConnectState*) data;
+       SoupSocketConnectState *state = (SoupSocketConnectState*) data;
 
        if (status == SOUP_ADDRESS_STATUS_OK) {
                state->tcp_id = soup_socket_new (inetaddr, state->port,
                                                 soup_socket_connect_tcp_cb,
                                                 state);
-               soup_address_unref (inetaddr);
+               g_object_unref (inetaddr);
        } else {
                SoupSocketConnectFn func = state->func;
                gpointer user_data = state->data;
@@ -106,12 +145,12 @@ soup_socket_connect_inetaddr_cb (SoupAddress* inetaddr,
  * or fails immediately.
  **/
 SoupSocketConnectId
-soup_socket_connect (const gchar*        hostname,
-                    const gint          port,
+soup_socket_connect (const char         *hostname,
+                    guint               port,
                     SoupSocketConnectFn func,
                     gpointer            data)
 {
-       SoupSocketConnectStatestate;
+       SoupSocketConnectState *state;
 
        g_return_val_if_fail (hostname != NULL, NULL);
        g_return_val_if_fail (func != NULL, NULL);
@@ -147,7 +186,7 @@ soup_socket_connect (const gchar*        hostname,
 void
 soup_socket_connect_cancel (SoupSocketConnectId id)
 {
-       SoupSocketConnectStatestate = (SoupSocketConnectState*) id;
+       SoupSocketConnectState *state = (SoupSocketConnectState*) id;
 
        g_return_if_fail (state != NULL);
 
@@ -169,8 +208,7 @@ soup_socket_connect_sync_cb (SoupSocket              *socket,
 }
 
 SoupSocket *
-soup_socket_connect_sync (const gchar *name,
-                         const gint   port)
+soup_socket_connect_sync (const char *name, guint port)
 {
        SoupSocket *ret = (SoupSocket *) 0xdeadbeef;
 
@@ -185,9 +223,9 @@ soup_socket_connect_sync (const gchar *name,
 }
 
 static void
-soup_socket_new_sync_cb (SoupSocket*         socket,
-                        SoupSocketNewStatus status,
-                        gpointer            data)
+soup_socket_new_sync_cb (SoupSocket          *socket,
+                        SoupSocketNewStatus  status,
+                        gpointer             data)
 {
        SoupSocket **ret = data;
        *ret = socket;
@@ -209,43 +247,6 @@ soup_socket_new_sync (SoupAddress *addr, guint port)
 }
 
 /**
- * soup_socket_ref
- * @s: SoupSocket to reference
- *
- * Increment the reference counter of the SoupSocket.
- **/
-void
-soup_socket_ref (SoupSocket* s)
-{
-       g_return_if_fail (s != NULL);
-
-       ++s->ref_count;
-}
-
-/**
- * soup_socket_unref
- * @s: #SoupSocket to unreference
- *
- * Remove a reference from the #SoupSocket.  When reference count
- * reaches 0, the socket is deleted.
- **/
-void
-soup_socket_unref (SoupSocket* s)
-{
-       g_return_if_fail(s != NULL);
-
-       --s->ref_count;
-
-       if (s->ref_count == 0) {
-               close (s->sockfd);
-               if (s->addr) soup_address_unref (s->addr);
-               if (s->iochannel) g_io_channel_unref (s->iochannel);
-
-               g_free(s);
-       }
-}
-
-/**
  * soup_socket_get_iochannel:
  * @socket: SoupSocket to get GIOChannel from.
  *
@@ -267,19 +268,19 @@ soup_socket_unref (SoupSocket* s)
  *
  **/
 GIOChannel*
-soup_socket_get_iochannel (SoupSocketsocket)
+soup_socket_get_iochannel (SoupSocket *socket)
 {
-       g_return_val_if_fail (socket != NULL, NULL);
+       g_return_val_if_fail (SOUP_IS_SOCKET (socket), NULL);
 
-       if (socket->iochannel == NULL) {
-               socket->iochannel = g_io_channel_unix_new (socket->sockfd);
-               g_io_channel_set_encoding (socket->iochannel, NULL, NULL);
-               g_io_channel_set_buffered (socket->iochannel, FALSE);
+       if (socket->priv->iochannel == NULL) {
+               socket->priv->iochannel = g_io_channel_unix_new (socket->priv->sockfd);
+               g_io_channel_set_encoding (socket->priv->iochannel, NULL, NULL);
+               g_io_channel_set_buffered (socket->priv->iochannel, FALSE);
        }
 
-       g_io_channel_ref (socket->iochannel);
+       g_io_channel_ref (socket->priv->iochannel);
 
-       return socket->iochannel;
+       return socket->priv->iochannel;
 }
 
 /**
@@ -294,14 +295,12 @@ soup_socket_get_iochannel (SoupSocket* socket)
  * Returns: #SoupAddress of socket; NULL on failure.
  **/
 SoupAddress *
-soup_socket_get_address (const SoupSocketsocket)
+soup_socket_get_address (const SoupSocket *socket)
 {
-       g_return_val_if_fail (socket != NULL, NULL);
-       g_return_val_if_fail (socket->addr != NULL, NULL);
-
-       soup_address_ref (socket->addr);
+       g_return_val_if_fail (SOUP_IS_SOCKET (socket), NULL);
+       g_return_val_if_fail (socket->priv->addr != NULL, NULL);
 
-       return socket->addr;
+       return g_object_ref (socket->priv->addr);
 }
 
 /**
@@ -312,12 +311,12 @@ soup_socket_get_address (const SoupSocket* socket)
  *
  * Returns: Port number of the socket.
  **/
-gint
-soup_socket_get_port(const SoupSocket* socket)
+guint
+soup_socket_get_port (const SoupSocket *socket)
 {
-       g_return_val_if_fail (socket != NULL, 0);
+       g_return_val_if_fail (SOUP_IS_SOCKET (socket), 0);
 
-       return socket->port;
+       return socket->priv->port;
 }
 
 /**
@@ -337,12 +336,12 @@ soup_socket_get_port(const SoupSocket* socket)
 SoupSocket *
 soup_socket_server_new (SoupAddress *local_addr, guint local_port)
 {
-       SoupSockets;
+       SoupSocket *s;
        struct sockaddr *sa = NULL;
        struct soup_sockaddr_max bound_sa;
        int sa_len;
        const int on = 1;
-       gint flags;
+       int flags;
 
        g_return_val_if_fail (local_addr != NULL, NULL);
 
@@ -350,17 +349,16 @@ soup_socket_server_new (SoupAddress *local_addr, guint local_port)
        soup_address_make_sockaddr (local_addr, local_port, &sa, &sa_len);
 
        /* Create socket */
-       s = g_new0 (SoupSocket, 1);
-       s->ref_count = 1;
+       s = g_object_new (SOUP_TYPE_SOCKET, NULL);
 
-       if ((s->sockfd = socket (sa->sa_family, SOCK_STREAM, 0)) < 0) {
-               g_free (s);
+       if ((s->priv->sockfd = socket (sa->sa_family, SOCK_STREAM, 0)) < 0) {
+               g_object_unref (s);
                g_free (sa);
                return NULL;
        }
 
        /* Set REUSEADDR so we can reuse the port */
-       if (setsockopt (s->sockfd,
+       if (setsockopt (s->priv->sockfd,
                        SOL_SOCKET,
                        SO_REUSEADDR,
                        &on,
@@ -368,31 +366,31 @@ soup_socket_server_new (SoupAddress *local_addr, guint local_port)
                g_warning("Can't set reuse on tcp socket\n");
 
        /* Get the flags (should all be 0?) */
-       flags = fcntl (s->sockfd, F_GETFL, 0);
+       flags = fcntl (s->priv->sockfd, F_GETFL, 0);
        if (flags == -1) goto SETUP_ERROR;
 
        /* Make the socket non-blocking */
-       if (fcntl (s->sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
+       if (fcntl (s->priv->sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
                goto SETUP_ERROR;
 
        /* Bind */
-       if (bind (s->sockfd, sa, sa_len) != 0)
+       if (bind (s->priv->sockfd, sa, sa_len) != 0)
                goto SETUP_ERROR;
        g_free (sa);
 
        sa_len = sizeof (bound_sa);
-       getsockname (s->sockfd, (struct sockaddr *)&bound_sa, &sa_len); 
-       s->addr = soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa,
-                                                 &s->port);
+       getsockname (s->priv->sockfd, (struct sockaddr *)&bound_sa, &sa_len); 
+       s->priv->addr =
+               soup_address_new_from_sockaddr ((struct sockaddr *)&bound_sa,
+                                               &s->priv->port);
 
        /* Listen */
-       if (listen (s->sockfd, 10) != 0) goto SETUP_ERROR;
+       if (listen (s->priv->sockfd, 10) != 0) goto SETUP_ERROR;
 
        return s;
 
  SETUP_ERROR:
-       close (s->sockfd);
-       g_free (s);
+       g_object_unref (s);
        g_free (sa);
        return NULL;
 }
@@ -402,24 +400,24 @@ soup_socket_server_new (SoupAddress *local_addr, guint local_port)
                                 G_IO_ERR | G_IO_HUP | G_IO_NVAL)
 
 typedef struct {
-       gint             sockfd;
+       int              sockfd;
        SoupAddress     *addr;
        guint            port;
        SoupSocketNewFn  func;
        gpointer         data;
-       gint             flags;
+       int              flags;
        guint            connect_watch;
 } SoupSocketState;
 
 static gboolean
-soup_socket_new_cb (GIOChanneliochannel,
+soup_socket_new_cb (GIOChannel *iochannel,
                    GIOCondition condition,
                    gpointer data)
 {
-       SoupSocketStatestate = (SoupSocketState*) data;
-       SoupSockets;
-       gint error = 0;
-       gint len = sizeof (gint);
+       SoupSocketState *state = (SoupSocketState*) data;
+       SoupSocket *s;
+       int error = 0;
+       int len = sizeof (int);
 
        /* Remove the watch now in case we don't return immediately */
        g_source_remove (state->connect_watch);
@@ -438,11 +436,10 @@ soup_socket_new_cb (GIOChannel* iochannel,
        if (fcntl (state->sockfd, F_SETFL, state->flags) != 0)
                goto ERROR;
 
-       s = g_new0 (SoupSocket, 1);
-       s->ref_count = 1;
-       s->sockfd = state->sockfd;
-       s->addr = state->addr;
-       s->port = state->port;
+       s = g_object_new (SOUP_TYPE_SOCKET, NULL);
+       s->priv->sockfd = state->sockfd;
+       s->priv->addr = state->addr;
+       s->priv->port = state->port;
 
        (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
 
@@ -451,7 +448,7 @@ soup_socket_new_cb (GIOChannel* iochannel,
        return FALSE;
 
  ERROR:
-       soup_address_unref (state->addr);
+       g_object_unref (state->addr);
        (*state->func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, state->data);
        g_free (state);
 
@@ -480,9 +477,9 @@ soup_socket_new (SoupAddress      *addr,
                 SoupSocketNewFn   func,
                 gpointer          data)
 {
-       gint sockfd;
-       gint flags;
-       SoupSocketStatestate;
+       int sockfd;
+       int flags;
+       SoupSocketState *state;
        GIOChannel *chan;
        struct sockaddr *sa;
        int len;
@@ -524,14 +521,13 @@ soup_socket_new (SoupAddress      *addr,
        g_free (sa);
 
        /* Unref in soup_socket_new_cb if failure */
-       soup_address_ref (addr);
+       g_object_ref (addr);
 
        /* Connect succeeded, return immediately */
        if (!errno) {
-               SoupSocket *s = g_new0 (SoupSocket, 1);
-               s->ref_count = 1;
-               s->sockfd = sockfd;
-               s->addr = addr;
+               SoupSocket *s = g_object_new (SOUP_TYPE_SOCKET, NULL);
+               s->priv->sockfd = sockfd;
+               s->priv->addr = addr;
 
                (*func) (s, SOUP_SOCKET_NEW_STATUS_OK, data);
                return NULL;
@@ -567,10 +563,10 @@ soup_socket_new (SoupAddress      *addr,
 void
 soup_socket_new_cancel (SoupSocketNewId id)
 {
-       SoupSocketStatestate = (SoupSocketState*) id;
+       SoupSocketState *state = (SoupSocketState*) id;
 
        g_source_remove (state->connect_watch);
-       soup_address_unref (state->addr);
+       g_object_unref (state->addr);
        g_free (state);
 }
 
@@ -582,22 +578,22 @@ server_accept_internal (SoupSocket *socket, gboolean block)
        struct soup_sockaddr_max sa;
        socklen_t n;
        fd_set fdset;
-       SoupSockets;
+       SoupSocket *s;
 
-       g_return_val_if_fail (socket != NULL, NULL);
+       g_return_val_if_fail (SOUP_IS_SOCKET (socket), NULL);
 
  try_again:
        FD_ZERO (&fdset);
-       FD_SET (socket->sockfd, &fdset);
+       FD_SET (socket->priv->sockfd, &fdset);
 
-       if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
+       if (select (socket->priv->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
                if (errno == EINTR) goto try_again;
                return NULL;
        }
 
        n = sizeof(sa);
 
-       if ((sockfd = accept (socket->sockfd, (struct sockaddr *)&sa, &n)) == -1) {
+       if ((sockfd = accept (socket->priv->sockfd, (struct sockaddr *)&sa, &n)) == -1) {
                if (!block)
                        return NULL;
                if (errno == EWOULDBLOCK ||
@@ -619,11 +615,10 @@ server_accept_internal (SoupSocket *socket, gboolean block)
        if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
                return NULL;
 
-       s = g_new0 (SoupSocket, 1);
-       s->ref_count = 1;
-       s->sockfd = sockfd;
-       s->addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa,
-                                                 &s->port);
+       s = g_object_new (SOUP_TYPE_SOCKET, NULL);
+       s->priv->sockfd = sockfd;
+       s->priv->addr = soup_address_new_from_sockaddr ((struct sockaddr *)&sa,
+                                                       &s->priv->port);
 
        return s;
 }
index 4a11863..c82cfc4 100644 (file)
@@ -1,23 +1,36 @@
 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
 /*
- * soup-socket.c: ronous Callback-based HTTP Request Queue.
- *
- * Authors:
- *      David Helder  (dhelder@umich.edu)
- *      Alex Graveley (alex@ximian.com)
- * 
- * Original code compliments of David Helder's GNET Networking Library.
- *
- * Copyright (C) 2000-2002, Ximian, Inc.
+ * Copyright (C) 2000-2003, Ximian, Inc.
  */
 
 #ifndef SOUP_SOCKET_H
 #define SOUP_SOCKET_H 1
 
-#include <glib.h>
+#include <glib-object.h>
 #include <libsoup/soup-address.h>
 
-typedef struct _SoupSocket SoupSocket;
+#define SOUP_TYPE_SOCKET            (soup_socket_get_type ())
+#define SOUP_SOCKET(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), SOUP_TYPE_SOCKET, SoupSocket))
+#define SOUP_SOCKET_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), SOUP_TYPE_SOCKET, SoupSocketClass))
+#define SOUP_IS_SOCKET(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SOUP_TYPE_SOCKET))
+#define SOUP_IS_SOCKET_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), SOUP_TYPE_SOCKET))
+#define SOUP_SOCKET_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), SOUP_TYPE_SOCKET, SoupSocketClass))
+
+typedef struct SoupSocketPrivate SoupSocketPrivate;
+
+typedef struct {
+       GObject parent;
+
+       SoupSocketPrivate *priv;
+} SoupSocket;
+
+typedef struct {
+       GObjectClass parent_class;
+
+} SoupSocketClass;
+
+GType soup_socket_get_type (void);
+
 
 typedef gpointer SoupSocketConnectId;
 
@@ -31,15 +44,15 @@ typedef void (*SoupSocketConnectFn) (SoupSocket              *socket,
                                     SoupSocketConnectStatus  status, 
                                     gpointer                 data);
 
-SoupSocketConnectId  soup_socket_connect        (const gchar*        hostname,
-                                                const gint          port, 
+SoupSocketConnectId  soup_socket_connect        (const char         *hostname,
+                                                guint               port, 
                                                 SoupSocketConnectFn func, 
                                                 gpointer            data);
 
 void                 soup_socket_connect_cancel (SoupSocketConnectId id);
 
-SoupSocket          *soup_socket_connect_sync   (const gchar        *hostname, 
-                                                const gint          port);
+SoupSocket          *soup_socket_connect_sync   (const char         *hostname, 
+                                                guint               port);
 
 
 typedef gpointer SoupSocketNewId;
@@ -64,15 +77,11 @@ SoupSocket         *soup_socket_new_sync        (SoupAddress        *addr,
                                                 guint               port);
 
 
-void                soup_socket_ref             (SoupSocket*         s);
-
-void                soup_socket_unref           (SoupSocket*         s);
-
 GIOChannel         *soup_socket_get_iochannel   (SoupSocket*         socket);
 
 SoupAddress        *soup_socket_get_address     (const SoupSocket*   socket);
 
-gint                soup_socket_get_port        (const SoupSocket*   socket);
+guint               soup_socket_get_port        (const SoupSocket*   socket);
 
 
 #define SOUP_SERVER_ANY_PORT 0
index 84ce9ef..ee8b2c0 100644 (file)
@@ -45,7 +45,7 @@ socks_data_free (SoupSocksData *sd)
                soup_context_unref (sd->dest_ctx);
 
        if (sd->dest_addr)
-               soup_address_unref (sd->dest_addr);
+               g_object_unref (sd->dest_addr);
 
        while (g_source_remove_by_user_data (sd))
                continue;
index 54b5219..10af618 100644 (file)
@@ -220,6 +220,8 @@ main (int argc, char **argv)
        char *expected;
        int i;
 
+       g_type_init ();
+
        for (i = 0; i < ntests; i++) {
                printf ("Test %d: %s\n", i + 1, tests[i].explanation);
 
index ffb402f..421aa2a 100644 (file)
@@ -109,7 +109,13 @@ got_url (SoupMessage *msg, gpointer uri)
                goto DONE;
        }
        printf ("%s: %d %s\n", name, msg->errorcode, msg->errorphrase);
+
+       name += strlen (base_uri->path);
+       if (*name == '/')
+               name++;
+
        if (SOUP_ERROR_IS_REDIRECTION (msg->errorcode)) {
+               unlink (name);
                header = soup_message_get_header (msg->response_headers, "Location");
                if (header) {
                        printf ("  -> %s\n", header);
@@ -121,10 +127,6 @@ got_url (SoupMessage *msg, gpointer uri)
        if (!SOUP_ERROR_IS_SUCCESSFUL (msg->errorcode))
                goto DONE;
 
-       name += strlen (base_uri->path);
-       if (*name == '/')
-               name++;
-
        if (recurse)
                fd = open (name, O_WRONLY | O_CREAT | O_TRUNC, 0644);
        else
@@ -146,6 +148,7 @@ got_url (SoupMessage *msg, gpointer uri)
        g_ptr_array_free (hrefs, TRUE);
 
  DONE:
+       soup_uri_free (uri);
        if (!--pending)
                g_main_quit (loop);
 }
@@ -173,6 +176,8 @@ get_url (const char *url)
                 */
 
                name = url_to_get + strlen (base);
+               if (*name == '/')
+                       name++;
                if (access (name, F_OK) == 0) {
                        g_free (url_to_get);
                        return;
@@ -205,6 +210,7 @@ main (int argc, char **argv)
 {
        int opt;
 
+       g_type_init ();
        while ((opt = getopt (argc, argv, "r")) != -1) {
                switch (opt) {
                case 'r':
@@ -245,6 +251,9 @@ main (int argc, char **argv)
 
        loop = g_main_loop_new (NULL, TRUE);
        g_main_run (loop);
+       g_main_loop_unref (loop);
+
+       soup_uri_free (base_uri);
 
        return 0;
 }
index 3c147b1..9f549e5 100644 (file)
@@ -6,6 +6,7 @@
 #include <ctype.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -47,7 +48,7 @@ server_callback (SoupServerContext *context, SoupMessage *msg, gpointer data)
                        goto DONE;
                }
        } else
-               path = "";
+               path = g_strdup ("");
 
        path_to_open = g_strdup_printf (".%s", path);
 
@@ -101,17 +102,28 @@ server_callback (SoupServerContext *context, SoupMessage *msg, gpointer data)
        soup_message_set_error (msg, SOUP_ERROR_OK);
 
  DONE:
+       g_free (path);
        printf ("  -> %d %s\n\n", msg->errorcode, msg->errorphrase);
 }
 
+static void
+quit (int sig)
+{
+       /* Exit cleanly on ^C in case we're valgrinding. */
+       exit (0);
+}
+
 int
 main (int argc, char **argv)
 {
        GMainLoop *loop;
+       SoupServer *server, *ssl_server;
        int opt;
        int port = SOUP_SERVER_ANY_PORT;
        int ssl_port = SOUP_SERVER_ANY_PORT;
-       SoupServer *server, *ssl_server;
+
+       g_type_init ();
+       signal (SIGINT, quit);
 
        while ((opt = getopt (argc, argv, "p:s:")) != -1) {
                switch (opt) {
index 821836a..92a2967 100644 (file)
@@ -6,6 +6,7 @@
 #include <ctype.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <signal.h>
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
@@ -37,6 +38,13 @@ server_callback (SoupServerContext *context, SoupMessage *msg, gpointer data)
        soup_message_send (msg);
 }
 
+static void
+quit (int sig)
+{
+       /* Exit cleanly on ^C in case we're valgrinding. */
+       exit (0);
+}
+
 int
 main (int argc, char **argv)
 {
@@ -45,6 +53,9 @@ main (int argc, char **argv)
        int port = SOUP_SERVER_ANY_PORT;
        SoupServer *server;
 
+       g_type_init ();
+       signal (SIGINT, quit);
+
        while ((opt = getopt (argc, argv, "p:s:")) != -1) {
                switch (opt) {
                case 'p':
@@ -72,6 +83,7 @@ main (int argc, char **argv)
 
        loop = g_main_loop_new (NULL, TRUE);
        g_main_loop_run (loop);
+       g_main_loop_unref (loop);
 
        return 0;
 }
index 53b49f6..9ea8d9b 100644 (file)
@@ -19,6 +19,8 @@ main (int argc, char **argv)
        GIOChannel *chan;
        gsize wrote;
 
+       g_type_init ();
+
        if (argc >=2 && !strcmp (argv[1], "-6")) {
                addr = soup_address_ipv6_any ();
                if (!addr) {
@@ -40,6 +42,7 @@ main (int argc, char **argv)
        else
                port = SOUP_SERVER_ANY_PORT;
        listener = soup_socket_server_new (addr, port);
+       g_object_unref (addr);
        if (!listener) {
                fprintf (stderr, "Could not create listening socket\n");
                exit (1);
@@ -51,6 +54,7 @@ main (int argc, char **argv)
                printf ("got connection from %s port %d\n",
                        soup_address_get_name_sync (addr),
                        soup_socket_get_port (client));
+               g_object_unref (addr);
 
                now = time (NULL);
                timebuf = ctime (&now);
@@ -59,8 +63,9 @@ main (int argc, char **argv)
                g_io_channel_write (chan, timebuf, strlen (timebuf), &wrote);
                g_io_channel_unref (chan);
 
-               soup_socket_unref (client);
+               g_object_unref (client);
        }
 
+       g_object_unref (listener);
        return 0;
 }