summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libsoup/Makefile.am1
-rw-r--r--libsoup/soup-server.c2
-rw-r--r--libsoup/soup-socket-unix.c1328
-rw-r--r--libsoup/soup-socket.c2053
-rw-r--r--libsoup/soup-socket.h9
5 files changed, 1356 insertions, 2037 deletions
diff --git a/libsoup/Makefile.am b/libsoup/Makefile.am
index 5a74253f..a9d48b52 100644
--- a/libsoup/Makefile.am
+++ b/libsoup/Makefile.am
@@ -59,6 +59,7 @@ libsoup_la_SOURCES = \
soup-serializer.c \
soup-server.c \
soup-socket.c \
+ soup-socket-unix.c \
soup-socks.h \
soup-socks.c \
soup-ssl.h \
diff --git a/libsoup/soup-server.c b/libsoup/soup-server.c
index 4bfb8fcb..62331563 100644
--- a/libsoup/soup-server.c
+++ b/libsoup/soup-server.c
@@ -45,7 +45,7 @@ SoupServer *
soup_server_new (SoupProtocol proto, guint port)
{
SoupServer *serv;
- SoupSocket *sock;
+ SoupSocket *sock = NULL;
if (proto != SOUP_PROTOCOL_CGI) {
sock = soup_socket_server_new (port);
diff --git a/libsoup/soup-socket-unix.c b/libsoup/soup-socket-unix.c
new file mode 100644
index 00000000..6cdf07b3
--- /dev/null
+++ b/libsoup/soup-socket-unix.c
@@ -0,0 +1,1328 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
+/*
+ * soup-socket.c: Asyncronous Callback-based SOAP Request Queue.
+ *
+ * Authors:
+ * David Helder (dhelder@umich.edu)
+ * Alex Graveley (alex@helixcode.com)
+ *
+ * Original code compliments of David Helder's GNET Networking Library.
+ *
+ * Copyright (C) 2000, Helix Code, Inc.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <errno.h>
+#include <fcntl.h>
+#include <glib.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/types.h>
+
+#ifdef HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+
+#include "soup-private.h"
+#include "soup-socket.h"
+
+#include <netdb.h>
+#include <resolv.h>
+#include <unistd.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/ioctl.h>
+#include <sys/ptrace.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/utsname.h>
+#include <sys/wait.h>
+
+#ifdef HAVE_SYS_POLL_H
+#include <sys/poll.h>
+#endif
+
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+
+#ifndef socklen_t
+#define socklen_t size_t
+#endif
+
+/*
+ * Maintains a list of all currently valid SoupAddresses or active
+ * SoupAddressState lookup requests.
+ */
+GHashTable *active_address_hash = NULL;
+
+#ifndef INET_ADDRSTRLEN
+#define INET_ADDRSTRLEN 16
+#define INET6_ADDRSTRLEN 46
+#endif
+
+#define SOUP_SOCKADDR_IN(s) (*((struct sockaddr_in*) &s))
+#define SOUP_ANY_IO_CONDITION (G_IO_IN | G_IO_OUT | G_IO_PRI | \
+ G_IO_ERR | G_IO_HUP | G_IO_NVAL)
+
+typedef struct {
+ SoupAddressNewFn func;
+ gpointer data;
+} SoupAddressCbData;
+
+typedef struct {
+ SoupAddress ia;
+ SoupAddressNewFn func;
+ gpointer data;
+
+ GSList *cb_list; /* CONTAINS: SoupAddressCbData */
+ pid_t pid;
+ int fd;
+ guint watch;
+ guchar buffer [16];
+ int len;
+} SoupAddressState;
+
+typedef struct {
+ SoupAddress *ia;
+ SoupAddressGetNameFn func;
+ gpointer data;
+
+ pid_t pid;
+ int fd;
+ guint watch;
+ guchar buffer [256 + 1];
+ int len;
+} SoupAddressReverseState;
+
+typedef struct {
+ gint sockfd;
+ SoupAddress *addr;
+ SoupSocketNewFn func;
+ gpointer data;
+ gint flags;
+ guint connect_watch;
+} SoupSocketState;
+
+/* Testing Defines */
+/* #undef HAVE_GETHOSTBYNAME_R_GLIBC */
+/* #define HAVE_GETHOSTBYNAME_R_GLIB_MUTEX */
+
+#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
+G_LOCK_DEFINE (gethostbyname);
+#endif
+
+/**
+ * soup_gethostbyname:
+ *
+ * Thread safe gethostbyname. The only valid fields are sin_len,
+ * sin_family, and sin_addr.
+ */
+gboolean
+soup_gethostbyname(const char* hostname,
+ struct sockaddr_in* sa,
+ gchar** nicename)
+{
+ gboolean rv = FALSE;
+
+#ifdef HAVE_GETHOSTBYNAME_R_GLIBC
+ {
+ struct hostent result_buf, *result;
+ size_t len;
+ char* buf;
+ int herr;
+ int res;
+
+ len = 1024;
+ buf = g_new (gchar, len);
+
+ while ((res = gethostbyname_r (hostname,
+ &result_buf,
+ buf,
+ len,
+ &result,
+ &herr)) == ERANGE) {
+ len *= 2;
+ buf = g_renew (gchar, buf, len);
+ }
+
+ if (res || result == NULL || result->h_addr_list [0] == NULL)
+ goto done;
+
+ if (sa) {
+ sa->sin_family = result->h_addrtype;
+ memcpy (&sa->sin_addr,
+ result->h_addr_list [0],
+ result->h_length);
+ }
+
+ if (nicename && result->h_name)
+ *nicename = g_strdup (result->h_name);
+
+ rv = TRUE;
+
+ done:
+ g_free(buf);
+ }
+#else
+#ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
+ {
+ struct hostent result;
+ size_t len;
+ char* buf;
+ int herr;
+ int res;
+
+ len = 1024;
+ buf = g_new (gchar, len);
+
+ while ((res = gethostbyname_r (hostname,
+ &result,
+ buf,
+ len,
+ &herr)) == ERANGE) {
+ len *= 2;
+ buf = g_renew (gchar, buf, len);
+ }
+
+ if (res || hp == NULL || hp->h_addr_list [0] == NULL)
+ goto done;
+
+ if (sa) {
+ sa->sin_family = result->h_addrtype;
+ memcpy (&sa->sin_addr,
+ result->h_addr_list [0],
+ result->h_length);
+ }
+
+ if (nicename && result->h_name)
+ *nicename = g_strdup (result->h_name);
+
+ rv = TRUE;
+
+ done:
+ g_free(buf);
+ }
+#else
+#ifdef HAVE_GETHOSTBYNAME_R_HPUX
+ {
+ struct hostent result;
+ struct hostent_data buf;
+ int res;
+
+ res = gethostbyname_r (hostname, &result, &buf);
+
+ if (res == 0) {
+ if (sa) {
+ sa->sin_family = result.h_addrtype;
+ memcpy (&sa->sin_addr,
+ result.h_addr_list [0],
+ result.h_length);
+ }
+
+ if (nicename && result.h_name)
+ *nicename = g_strdup(result.h_name);
+
+ rv = TRUE;
+ }
+ }
+#else
+#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
+ {
+ struct hostent* he;
+
+ G_LOCK (gethostbyname);
+ he = gethostbyname (hostname);
+ G_UNLOCK (gethostbyname);
+
+ if (he != NULL && he->h_addr_list [0] != NULL) {
+ if (sa) {
+ sa->sin_family = he->h_addrtype;
+ memcpy (&sa->sin_addr,
+ he->h_addr_list [0],
+ he->h_length);
+ }
+
+ if (nicename && he->h_name)
+ *nicename = g_strdup (he->h_name);
+
+ rv = TRUE;
+ }
+ }
+#else
+ {
+ struct hostent* he;
+
+ he = gethostbyname (hostname);
+ if (he != NULL && he->h_addr_list [0] != NULL) {
+ if (sa) {
+ sa->sin_family = he->h_addrtype;
+ memcpy (&sa->sin_addr,
+ he->h_addr_list [0],
+ he->h_length);
+ }
+
+ if (nicename && he->h_name)
+ *nicename = g_strdup (he->h_name);
+
+ rv = TRUE;
+ }
+ }
+#endif
+#endif
+#endif
+#endif
+
+ return rv;
+}
+
+/*
+ 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.
+*/
+
+gchar *
+soup_gethostbyaddr (const char* addr, size_t length, int type)
+{
+ gchar* rv = NULL;
+
+#ifdef HAVE_GETHOSTBYNAME_R_GLIBC
+ {
+ struct hostent result_buf, *result;
+ size_t len;
+ char* buf;
+ int herr;
+ int res;
+
+ len = 1024;
+ buf = g_new (gchar, len);
+
+ while ((res = gethostbyaddr_r (addr,
+ length,
+ type,
+ &result_buf,
+ buf,
+ len,
+ &result,
+ &herr)) == ERANGE) {
+ len *= 2;
+ buf = g_renew (gchar, buf, len);
+ }
+
+ if (res || result == NULL || result->h_name == NULL)
+ goto done;
+
+ rv = g_strdup(result->h_name);
+
+ done:
+ g_free(buf);
+ }
+#else
+#ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
+ {
+ struct hostent result;
+ size_t len;
+ char* buf;
+ int herr;
+ int res;
+
+ len = 1024;
+ buf = g_new (gchar, len);
+
+ while ((res = gethostbyaddr_r (addr,
+ length,
+ type,
+ &result,
+ buf,
+ len,
+ &herr)) == ERANGE) {
+ len *= 2;
+ buf = g_renew (gchar, buf, len);
+ }
+
+ if (res || hp == NULL || hp->h_name == NULL)
+ goto done;
+
+ rv = g_strdup(result->h_name);
+
+ done:
+ g_free(buf);
+ }
+#else
+#ifdef HAVE_GETHOSTBYNAME_R_HPUX
+ {
+ struct hostent result;
+ struct hostent_data buf;
+ int res;
+
+ res = gethostbyaddr_r (addr, length, type, &result, &buf);
+
+ if (res == 0) rv = g_strdup (result.h_name);
+ }
+#else
+#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
+ {
+ struct hostent* he;
+
+ G_LOCK (gethostbyname);
+ he = gethostbyaddr (addr, length, type);
+ G_UNLOCK (gethostbyname);
+ if (he != NULL && he->h_name != NULL)
+ rv = g_strdup (he->h_name);
+ }
+#else
+ {
+ struct hostent* he;
+
+ he = gethostbyaddr (addr, length, type);
+ if (he != NULL && he->h_name != NULL)
+ rv = g_strdup (he->h_name);
+ }
+#endif
+#endif
+#endif
+#endif
+
+ return rv;
+}
+
+static gboolean
+soup_address_new_cb (GIOChannel* iochannel,
+ GIOCondition condition,
+ gpointer data)
+{
+ SoupAddressState* state = (SoupAddressState*) data;
+ struct sockaddr_in* sa_in;
+ GSList *cb_list, *iter;
+ SoupAddressNewFn cb_func;
+ gpointer cb_data;
+
+ if (!(condition & G_IO_IN)) {
+ int ret;
+
+ g_source_remove (state->watch);
+ close (state->fd);
+ waitpid (state->pid, &ret, 0);
+
+ if (WIFSIGNALED (ret) || WEXITSTATUS (ret) != 1) goto ERROR;
+
+ /*
+ * Exit status of one means we are inside a debugger.
+ * Resolve the name synchronously.
+ */
+ sa_in = (struct sockaddr_in*) &state->ia.sa;
+
+ if (!soup_gethostbyname (state->ia.name, sa_in, NULL))
+ g_warning ("Problem resolving host name");
+ } else {
+ int rv;
+ char* buf;
+ int length;
+
+ buf = &state->buffer [state->len];
+ length = sizeof (state->buffer) - state->len;
+
+ 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_in = (struct sockaddr_in*) &state->ia.sa;
+ memcpy (&sa_in->sin_addr, &state->buffer [1], (state->len - 1));
+
+ /* Cleanup state */
+ g_source_remove (state->watch);
+ close (state->fd);
+ waitpid (state->pid, NULL, WNOHANG);
+ }
+
+ /* Get state data before realloc */
+ cb_list = iter = state->cb_list;
+ cb_func = state->func;
+ cb_data = state->data;
+
+ /* Invert resolved address reference count */
+ state->ia.ref_count = ~state->ia.ref_count + 1;
+
+ /*
+ * Realloc state to size of SoupAddress, and reinsert to resolved
+ * address table.
+ */
+ state = g_realloc (state, sizeof (SoupAddress));
+ g_hash_table_insert (active_address_hash, state->ia.name, state);
+
+ (*cb_func) (&state->ia, SOUP_ADDRESS_STATUS_OK, cb_data);
+
+ while (iter) {
+ SoupAddressCbData *cb = iter->data;
+
+ (*cb->func) (&state->ia, SOUP_ADDRESS_STATUS_OK, cb->data);
+
+ g_free (cb);
+ iter = iter->next;
+ }
+
+ g_slist_free (cb_list);
+
+ return FALSE;
+
+ ERROR:
+ /* Remove the watch now in case we don't return immediately */
+ g_source_remove (state->watch);
+
+ (*state->func) (NULL, SOUP_ADDRESS_STATUS_ERROR, state->data);
+
+ for (cb_list = state->cb_list; cb_list; cb_list = cb_list->next) {
+ SoupAddressCbData *cb_data = cb_list->data;
+ (*cb_data->func) (NULL,
+ SOUP_ADDRESS_STATUS_ERROR,
+ cb_data->data);
+ }
+
+ /* Force cancel */
+ state->ia.ref_count = -1;
+ soup_address_new_cancel (state);
+
+ 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.
+ * @port: port number (0 if the port doesn't matter)
+ * @func: Callback function.
+ * @data: User data passed when callback function is called.
+ *
+ * Create a SoupAddress from a name and port 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.
+ *
+ * The Unix version 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, we recommend calling
+ * g_main_iteration(FALSE) between calls. This will help prevent an
+ * explosion of processes.
+ *
+ * If you need a more robust library for Unix, look at <ulink
+ * url="http://www.gnu.org/software/adns/adns.html">GNU ADNS</ulink>.
+ * GNU ADNS is under the GNU GPL.
+ *
+ * The Windows version should work fine. Windows has an asynchronous
+ * DNS lookup function.
+ *
+ * Returns: ID of the lookup which can be used with
+ * soup_address_new_cancel() to cancel it; NULL on immediate
+ * success or failure.
+ **/
+SoupAddressNewId
+soup_address_new (const gchar* name,
+ const gint port,
+ SoupAddressNewFn func,
+ gpointer data)
+{
+ pid_t pid = -1;
+ int pipes [2];
+ struct in_addr inaddr;
+ struct sockaddr_in sa;
+ struct sockaddr_in* sa_in;
+ SoupAddress* ia;
+ SoupAddressState* state;
+ GIOChannel *chan;
+
+ 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 */
+ if (inet_aton (name, &inaddr) != 0) {
+ ia = g_new0 (SoupAddress, 1);
+ ia->ref_count = 1;
+
+ sa_in = (struct sockaddr_in*) &ia->sa;
+ sa_in->sin_family = AF_INET;
+ sa_in->sin_port = g_htons(port);
+ memcpy (&sa_in->sin_addr,
+ (char*) &inaddr,
+ sizeof(struct in_addr));
+
+ (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
+ return NULL;
+ }
+
+ if (!active_address_hash)
+ active_address_hash = g_hash_table_new (soup_str_case_hash,
+ soup_str_case_equal);
+ else {
+ ia = g_hash_table_lookup (active_address_hash, name);
+
+ if (ia && ia->ref_count > 0) {
+ /*
+ * Existing valid request, use it.
+ */
+ if (soup_address_get_port (ia) == port) {
+ soup_address_ref (ia);
+ } else {
+ /*
+ * We can reuse the address, but we have to
+ * change port
+ */
+ SoupAddress *new_ia = soup_address_copy (ia);
+ soup_address_set_port (new_ia, port);
+ ia = new_ia;
+ }
+
+ (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
+ return NULL;
+ } else if (ia && soup_address_get_port (ia) == port) {
+ /*
+ * Lookup currently in progress.
+ * Add func to list of callbacks in state.
+ * Note that if it's not the same port, we have to do
+ * the lookup again, since there's no way to communicate
+ * the port change.
+ */
+ SoupAddressCbData *cb_data;
+
+ cb_data = g_new0 (SoupAddressCbData, 1);
+ cb_data->func = func;
+ cb_data->data = data;
+
+ state = (SoupAddressState *) ia;
+ state->cb_list = g_slist_prepend (state->cb_list,
+ cb_data);
+
+ state->ia.ref_count--;
+
+ return state;
+ }
+ }
+
+ /* Check to see if we are doing synchronous DNS lookups */
+ if (getenv ("SOUP_SYNC_DNS")) {
+ if (!soup_gethostbyname (name, &sa, NULL)) {
+ g_warning ("Problem resolving host name");
+ (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
+ return NULL;
+ }
+
+ sa_in = (struct sockaddr_in*) &sa;
+ sa_in->sin_family = AF_INET;
+ sa_in->sin_port = g_htons (port);
+
+ ia = g_new0(SoupAddress, 1);
+ ia->name = g_strdup (name);
+ ia->ref_count = 1;
+ ia->sa = *((struct sockaddr *) &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 PTRACE_ATTACH
+ signal (SIGCHLD, SIG_IGN);
+
+ if (ptrace (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.
+ */
+ waitpid (getppid (), NULL, 0);
+
+ if (ptrace (PTRACE_DETACH, getppid (), NULL, NULL) == -1)
+ g_warning ("ptrace: Detach failed: %s",
+ strerror(errno));
+
+ kill (getppid(), SIGCONT);
+#endif
+
+ /*
+ * Try to get the host by name (ie, DNS)
+ */
+ if (soup_gethostbyname (name, &sa, NULL)) {
+ guchar size = 4; /* FIX for IPv6 */
+
+ if ((write (pipes [1], &size, sizeof(guchar)) == -1) ||
+ (write (pipes [1], &sa.sin_addr, size) == -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 (SoupAddressState, 1);
+ state->ia.name = g_strdup (name);
+ state->ia.ref_count = -1;
+ state->func = func;
+ state->data = data;
+ state->pid = pid;
+ state->fd = pipes [0];
+
+ sa_in = (struct sockaddr_in*) &state->ia.sa;
+ sa_in->sin_family = AF_INET;
+ sa_in->sin_port = g_htons (port);
+
+ g_hash_table_insert (active_address_hash,
+ state->ia.name,
+ state);
+
+ chan = g_io_channel_unix_new (pipes [0]);
+
+ /* Set up an watch to read from the pipe */
+ 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 state;
+ }
+}
+
+/**
+ * soup_address_new_cancel:
+ * @id: ID of the lookup
+ *
+ * Cancel an asynchronous SoupAddress creation that was started with
+ * soup_address_new().
+ */
+void
+soup_address_new_cancel (SoupAddressNewId id)
+{
+ SoupAddressState* state = (SoupAddressState*) id;
+ GSList *cb_list;
+
+ g_return_if_fail (state != NULL);
+
+ state->ia.ref_count++;
+
+ if (state->ia.ref_count == 0) {
+ g_hash_table_remove (active_address_hash, state->ia.name);
+ g_free (state->ia.name);
+
+ for (cb_list = state->cb_list; cb_list; cb_list = cb_list->next)
+ g_free (cb_list->data);
+ g_slist_free (state->cb_list);
+
+ g_source_remove (state->watch);
+
+ close (state->fd);
+ kill (state->pid, SIGKILL);
+ waitpid (state->pid, NULL, 0);
+
+ g_free (state);
+ }
+}
+
+static gboolean
+soup_address_get_name_cb (GIOChannel* iochannel,
+ GIOCondition condition,
+ gpointer data)
+{
+ SoupAddressReverseState* state;
+ gchar* name = NULL;
+
+ state = (SoupAddressReverseState*) 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 */
+ name = g_new (gchar, state->buffer [0] + 1);
+ strncpy (name, &state->buffer [1], state->buffer [0]);
+ name [state->buffer [0]] = '\0';
+
+ state->ia->name = name;
+
+ /* 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,
+ name,
+ state->data);
+
+ close (state->fd);
+ waitpid (state->pid, NULL, 0);
+ g_free (state);
+ return FALSE;
+ }
+ }
+
+ /* 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_ERROR,
+ NULL,
+ state->data);
+ soup_address_get_name_cancel (state);
+ return FALSE;
+}
+
+/**
+ * soup_address_get_name:
+ * @ia: 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.
+ *
+ * The Unix version forks and does the reverse lookup. This has
+ * problems. See the notes for soup_address_new(). The
+ * Windows version should work fine.
+ *
+ * Returns: ID of the lookup which can be used with
+ * soup_addressr_get_name_cancel() to cancel it; NULL on
+ * immediate success or failure.
+ **/
+SoupAddressGetNameId
+soup_address_get_name (SoupAddress* ia,
+ SoupAddressGetNameFn func,
+ gpointer data)
+{
+ SoupAddressReverseState* state;
+ gchar* name;
+ guchar len;
+ pid_t pid = -1;
+ int pipes [2];
+
+ g_return_val_if_fail (ia != NULL, NULL);
+ g_return_val_if_fail (func != NULL, NULL);
+
+ if (ia->name) {
+ (func) (ia, SOUP_ADDRESS_STATUS_OK, ia->name, data);
+ return NULL;
+ }
+
+ /* 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;
+ }
+
+ 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 (
+ (char*) &((struct sockaddr_in*)&ia->sa)->sin_addr,
+ sizeof (struct in_addr),
+ AF_INET);
+
+ if (name) {
+ guint 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);
+ } else {
+ /* defined in netinet/in.h */
+ gchar buffer [INET_ADDRSTRLEN];
+ guchar* p;
+ p = (guchar*) &(SOUP_SOCKADDR_IN (ia->sa).sin_addr);
+
+ g_snprintf(buffer,
+ sizeof (buffer),
+ "%d.%d.%d.%d",
+ p [0],
+ p [1],
+ p [2],
+ p [3]);
+ len = strlen (buffer);
+
+ if ((write (pipes [1], &len, sizeof(len)) == -1) ||
+ (write (pipes [1], buffer, len) == -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]);
+
+ 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;
+ }
+}
+
+/**
+ * soup_address_get_name_cancel:
+ * @id: ID of the lookup
+ *
+ * Cancel an asynchronous nice name lookup that was started with
+ * soup_address_get_name().
+ */
+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);
+
+ close (state->fd);
+ kill (state->pid, SIGKILL);
+ waitpid (state->pid, NULL, 0);
+
+ g_free(state);
+}
+
+/**
+ * soup_address_gethostname:
+ *
+ * Get the primary host's name.
+ *
+ * Returns: the name of the host; NULL if there was an error. The
+ * caller is responsible for deleting the returned string.
+ **/
+gchar*
+soup_address_gethostname (void)
+{
+ gchar* name = NULL;
+ struct utsname myname;
+
+ if (uname (&myname) < 0) return NULL;
+
+ if (!soup_gethostbyname (myname.nodename, NULL, &name)) return NULL;
+
+ return name;
+}
+
+static gboolean
+soup_socket_new_cb (GIOChannel* iochannel,
+ GIOCondition condition,
+ gpointer data)
+{
+ SoupSocketState* state = (SoupSocketState*) data;
+ SoupSocket* s;
+ gint error = 0;
+ gint len = sizeof (gint);
+
+ /* Remove the watch now in case we don't return immediately */
+ g_source_remove (state->connect_watch);
+
+ if (condition & ~(G_IO_IN | G_IO_OUT)) goto ERROR;
+
+ errno = 0;
+ if (getsockopt (state->sockfd,
+ SOL_SOCKET,
+ SO_ERROR,
+ &error,
+ &len) != 0) goto ERROR;
+
+ if (error) goto ERROR;
+
+ 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;
+
+ (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
+
+ g_free (state);
+
+ return FALSE;
+
+ ERROR:
+ soup_address_unref (state->addr);
+ (*state->func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, state->data);
+ g_free (state);
+
+ return FALSE;
+}
+
+/**
+ * soup_socket_new:
+ * @addr: Address to connect to.
+ * @func: Callback function.
+ * @data: User data passed when callback function is called.
+ *
+ * Connect to a specifed address asynchronously. When the connection
+ * is complete or there is an error, it will call the callback. It
+ * may call the callback before the function returns. It will call
+ * the callback if there is a failure.
+ *
+ * Returns: ID of the connection which can be used with
+ * soup_socket_connect_cancel() to cancel it; NULL on
+ * failure.
+ **/
+SoupSocketNewId
+soup_socket_new (SoupAddress *addr,
+ SoupSocketNewFn func,
+ gpointer data)
+{
+ gint sockfd;
+ gint flags;
+ SoupSocketState* state;
+ GIOChannel *chan;
+
+ g_return_val_if_fail(addr != NULL, NULL);
+ g_return_val_if_fail(func != NULL, NULL);
+
+ /* Create socket */
+ sockfd = socket (AF_INET, SOCK_STREAM, 0);
+ if (sockfd < 0) {
+ (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
+ return NULL;
+ }
+
+ /* Get the flags (should all be 0?) */
+ flags = fcntl (sockfd, F_GETFL, 0);
+ if (flags == -1) {
+ (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
+ return NULL;
+ }
+
+ if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
+ (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
+ return NULL;
+ }
+
+ errno = 0;
+
+ /* Connect (but non-blocking!) */
+ if (connect (sockfd, &addr->sa, sizeof (addr->sa)) < 0 &&
+ errno != EINPROGRESS) {
+ (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
+ return NULL;
+ }
+
+ /* Unref in soup_socket_new_cb if failure */
+ soup_address_ref (addr);
+
+ /* Connect succeeded, return immediately */
+ if (!errno) {
+ SoupSocket *s = g_new0 (SoupSocket, 1);
+ s->ref_count = 1;
+ s->sockfd = sockfd;
+ s->addr = addr;
+
+ (*func) (s, SOUP_SOCKET_NEW_STATUS_OK, data);
+ return NULL;
+ }
+
+ chan = g_io_channel_unix_new (sockfd);
+
+ /* Wait for the connection */
+ state = g_new0 (SoupSocketState, 1);
+ state->sockfd = sockfd;
+ state->addr = addr;
+ state->func = func;
+ state->data = data;
+ state->flags = flags;
+ state->connect_watch = g_io_add_watch (chan,
+ SOUP_ANY_IO_CONDITION,
+ soup_socket_new_cb,
+ state);
+
+ g_io_channel_unref (chan);
+
+ return state;
+}
+
+/**
+ * soup_socket_new_cancel:
+ * @id: ID of the connection.
+ *
+ * Cancel an asynchronous connection that was started with
+ * soup_socket_new().
+ **/
+void
+soup_socket_new_cancel (SoupSocketNewId id)
+{
+ SoupSocketState* state = (SoupSocketState*) id;
+
+ g_source_remove (state->connect_watch);
+ soup_address_unref (state->addr);
+ g_free (state);
+}
+
+/**
+ * soup_socket_server_accept:
+ * @socket: #SoupSocket to accept connections from.
+ *
+ * Accept a connection from the socket. The socket must have been
+ * created using soup_socket_server_new(). This function will
+ * block (use soup_socket_server_try_accept() if you don't
+ * want to block). If the socket's #GIOChannel is readable, it DOES
+ * NOT mean that this function will not block.
+ *
+ * Returns: a new #SoupSocket if there is another connect, or NULL if
+ * there's an error.
+ **/
+SoupSocket *
+soup_socket_server_accept (SoupSocket *socket)
+{
+ gint sockfd;
+ gint flags;
+ struct sockaddr sa;
+ socklen_t n;
+ fd_set fdset;
+ SoupSocket* s;
+
+ g_return_val_if_fail (socket != NULL, NULL);
+
+ try_again:
+ FD_ZERO (&fdset);
+ FD_SET (socket->sockfd, &fdset);
+
+ if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
+ if (errno == EINTR) goto try_again;
+ return NULL;
+ }
+
+ n = sizeof(s->addr->sa);
+
+ if ((sockfd = accept (socket->sockfd, &sa, &n)) == -1) {
+ if (errno == EWOULDBLOCK ||
+ errno == ECONNABORTED ||
+#ifdef EPROTO /* OpenBSD does not have EPROTO */
+ errno == EPROTO ||
+#endif
+ errno == EINTR)
+ goto try_again;
+
+ return NULL;
+ }
+
+ /* Get the flags (should all be 0?) */
+ flags = fcntl (sockfd, F_GETFL, 0);
+ if (flags == -1) return NULL;
+
+ /* Make the socket non-blocking */
+ 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 = g_new0 (SoupAddress, 1);
+ s->addr->ref_count = 1;
+ memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
+
+ return s;
+}
+
+/**
+ * soup_socket_server_try_accept:
+ * @socket: SoupSocket to accept connections from.
+ *
+ * Accept a connection from the socket without blocking. The socket
+ * must have been created using soup_socket_server_new(). This
+ * function is best used with the sockets #GIOChannel. If the
+ * channel is readable, then you PROBABLY have a connection. It is
+ * possible for the connection to close by the time you call this, so
+ * it may return NULL even if the channel was readable.
+ *
+ * Returns a new SoupSocket if there is another connect, or NULL
+ * otherwise.
+ **/
+SoupSocket *
+soup_socket_server_try_accept (SoupSocket *socket)
+{
+ gint sockfd;
+ gint flags;
+ struct sockaddr sa;
+ socklen_t n;
+ fd_set fdset;
+ SoupSocket* s;
+ struct timeval tv = {0, 0};
+
+ g_return_val_if_fail (socket != NULL, NULL);
+
+ try_again:
+ FD_ZERO (&fdset);
+ FD_SET (socket->sockfd, &fdset);
+
+ if (select (socket->sockfd + 1, &fdset, NULL, NULL, &tv) == -1) {
+ if (errno == EINTR) goto try_again;
+ return NULL;
+ }
+
+ n = sizeof(sa);
+
+ if ((sockfd = accept (socket->sockfd, &sa, &n)) == -1) {
+ /* If we get an error, return. We don't want to try again as we
+ do in soup_socket_server_accept() - it might cause a
+ block. */
+ return NULL;
+ }
+
+ /* Get the flags (should all be 0?) */
+ flags = fcntl (sockfd, F_GETFL, 0);
+ if (flags == -1) return NULL;
+
+ /* Make the socket non-blocking */
+ 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 = g_new0 (SoupAddress, 1);
+ s->addr->ref_count = 1;
+ memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
+
+ return s;
+}
diff --git a/libsoup/soup-socket.c b/libsoup/soup-socket.c
index 96addeea..32bd300c 100644
--- a/libsoup/soup-socket.c
+++ b/libsoup/soup-socket.c
@@ -15,163 +15,32 @@
#include <config.h>
#endif
-#include <errno.h>
#include <fcntl.h>
#include <glib.h>
-#include <signal.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <string.h>
-#include <sys/types.h>
-
-#ifdef HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
#include "soup-private.h"
#include "soup-socket.h"
-#ifndef SOUP_WIN32 /*********** Unix specific ***********/
-
-#include <netdb.h>
-#include <resolv.h>
-#include <unistd.h>
-#include <arpa/inet.h>
-#include <arpa/nameser.h>
-#include <net/if.h>
-#include <netinet/in.h>
-#include <sys/ioctl.h>
-#include <sys/ptrace.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <sys/utsname.h>
-#include <sys/wait.h>
-
-#ifdef HAVE_SYS_POLL_H
-#include <sys/poll.h>
-#endif
-
-#ifdef HAVE_SYS_SOCKIO_H
-#include <sys/sockio.h>
-#endif
-
-#ifndef socklen_t
-#define socklen_t size_t
-#endif
-
-#define SOUP_CLOSE_SOCKET(SOCKFD) close(SOCKFD)
-#define SOUP_SOCKET_IOCHANNEL_NEW(SOCKFD) g_io_channel_unix_new(SOCKFD)
-
-/*
- * Maintains a list of all currently valid SoupAddresses or active
- * SoupAddressState lookup requests.
- */
-static GHashTable *active_address_hash = NULL;
-
-#else /*********** Windows specific ***********/
-
-#include <windows.h>
-#include <winbase.h>
-#include <winuser.h>
-#include <io.h>
-
-#define socklen_t gint32
-
-#define SOUP_CLOSE_SOCKET(SOCKFD) closesocket(SOCKFD)
-#define SOUP_SOCKET_IOCHANNEL_NEW(SOCKFD) \
- g_io_channel_win32_new_stream_socket(SOCKFD)
-
-WNDCLASSEX soupWndClass;
-HWND soup_hWnd;
-guint soup_io_watch_ID;
-GIOChannel *soup_iochannel;
-
-GHashTable *soup_hash;
-HANDLE soup_Mutex;
-HANDLE soup_hostent_Mutex;
-
-#define IA_NEW_MSG 100 /* soup_address_new */
-#define GET_NAME_MSG 101 /* soup_address_get_name */
-
-/*
- * Windows does not have inet_aton, but it does have inet_addr.
- *
- * TODO: We should write a better inet_aton because inet_addr doesn't catch
- * 255.255.255.255 properly.
- */
-static int
-inet_aton(const char *cp, struct in_addr *inp)
-{
- inp->s_addr = inet_addr (cp);
- if (inp->s_addr == INADDR_NONE) return 0;
- return 1;
-}
-
-#endif /*********** End Windows specific ***********/
-
-#ifndef INET_ADDRSTRLEN
-#define INET_ADDRSTRLEN 16
-#define INET6_ADDRSTRLEN 46
-#endif
-
-#define SOUP_SOCKADDR_IN(s) (*((struct sockaddr_in*) &s))
-#define SOUP_ANY_IO_CONDITION (G_IO_IN | G_IO_OUT | G_IO_PRI | \
- G_IO_ERR | G_IO_HUP | G_IO_NVAL)
-
-typedef struct {
- SoupAddressNewFn func;
- gpointer data;
-} SoupAddressCbData;
-
-typedef struct {
- SoupAddress ia;
- SoupAddressNewFn func;
- gpointer data;
- GSList *cb_list; /* CONTAINS: SoupAddressCbData */
-#ifndef SOUP_WIN32
- pid_t pid;
- int fd;
- guint watch;
- guchar buffer [16];
- int len;
-#else
- int WSAhandle;
- char hostentBuffer [MAXGETHOSTSTRUCT];
- int errorcode;
-#endif
-} SoupAddressState;
-
-
-typedef struct {
- SoupAddress *ia;
- SoupAddressGetNameFn func;
- gpointer data;
-#ifndef SOUP_WIN32
- pid_t pid;
- int fd;
- guint watch;
- guchar buffer [256 + 1];
- int len;
-#else
- int WSAhandle;
- char hostentBuffer [MAXGETHOSTSTRUCT];
- int errorcode;
-#endif
-} SoupAddressReverseState;
-
-
-typedef struct {
- gint sockfd;
- SoupAddress *addr;
- SoupSocketNewFn func;
- gpointer data;
- gint flags;
- guint connect_watch;
#ifdef SOUP_WIN32
- gint errorcode;
+# define socklen_t gint32
+# define SOUP_CLOSE_SOCKET(fd) closesocket(fd)
+# define SOUP_SOCKET_IOCHANNEL_NEW(fd) g_io_channel_win32_new_stream_socket(fd)
+# ifndef INET_ADDRSTRLEN
+# define INET_ADDRSTRLEN 16
+# define INET6_ADDRSTRLEN 46
+# endif
+#else
+# include <unistd.h>
+# ifndef socklen_t
+# define socklen_t size_t
+# endif
+# define SOUP_CLOSE_SOCKET(fd) close(fd)
+# define SOUP_SOCKET_IOCHANNEL_NEW(fd) g_io_channel_unix_new(fd)
+ extern GHashTable *active_address_hash;
#endif
-} SoupSocketState;
+#define SOUP_SOCKADDR_IN(s) (*((struct sockaddr_in*) &s))
typedef struct {
SoupSocketConnectFn func;
@@ -181,847 +50,6 @@ typedef struct {
gpointer tcp_id;
} SoupSocketConnectState;
-
-/* Testing Defines */
-/* #undef HAVE_GETHOSTBYNAME_R_GLIBC */
-/* #define HAVE_GETHOSTBYNAME_R_GLIB_MUTEX */
-
-#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
-G_LOCK_DEFINE (gethostbyname);
-#endif
-
-/**
- * soup_gethostbyname:
- *
- * Thread safe gethostbyname. The only valid fields are sin_len,
- * sin_family, and sin_addr.
- */
-static gboolean
-soup_gethostbyname(const char* hostname,
- struct sockaddr_in* sa,
- gchar** nicename)
-{
- gboolean rv = FALSE;
-
-#ifdef HAVE_GETHOSTBYNAME_R_GLIBC
- {
- struct hostent result_buf, *result;
- size_t len;
- char* buf;
- int herr;
- int res;
-
- len = 1024;
- buf = g_new (gchar, len);
-
- while ((res = gethostbyname_r (hostname,
- &result_buf,
- buf,
- len,
- &result,
- &herr)) == ERANGE) {
- len *= 2;
- buf = g_renew (gchar, buf, len);
- }
-
- if (res || result == NULL || result->h_addr_list [0] == NULL)
- goto done;
-
- if (sa) {
- sa->sin_family = result->h_addrtype;
- memcpy (&sa->sin_addr,
- result->h_addr_list [0],
- result->h_length);
- }
-
- if (nicename && result->h_name)
- *nicename = g_strdup (result->h_name);
-
- rv = TRUE;
-
- done:
- g_free(buf);
- }
-#else
-#ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
- {
- struct hostent result;
- size_t len;
- char* buf;
- int herr;
- int res;
-
- len = 1024;
- buf = g_new (gchar, len);
-
- while ((res = gethostbyname_r (hostname,
- &result,
- buf,
- len,
- &herr)) == ERANGE) {
- len *= 2;
- buf = g_renew (gchar, buf, len);
- }
-
- if (res || hp == NULL || hp->h_addr_list [0] == NULL)
- goto done;
-
- if (sa) {
- sa->sin_family = result->h_addrtype;
- memcpy (&sa->sin_addr,
- result->h_addr_list [0],
- result->h_length);
- }
-
- if (nicename && result->h_name)
- *nicename = g_strdup (result->h_name);
-
- rv = TRUE;
-
- done:
- g_free(buf);
- }
-#else
-#ifdef HAVE_GETHOSTBYNAME_R_HPUX
- {
- struct hostent result;
- struct hostent_data buf;
- int res;
-
- res = gethostbyname_r (hostname, &result, &buf);
-
- if (res == 0) {
- if (sa) {
- sa->sin_family = result.h_addrtype;
- memcpy (&sa->sin_addr,
- result.h_addr_list [0],
- result.h_length);
- }
-
- if (nicename && result.h_name)
- *nicename = g_strdup(result.h_name);
-
- rv = TRUE;
- }
- }
-#else
-#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
- {
- struct hostent* he;
-
- G_LOCK (gethostbyname);
- he = gethostbyname (hostname);
- G_UNLOCK (gethostbyname);
-
- if (he != NULL && he->h_addr_list [0] != NULL) {
- if (sa) {
- sa->sin_family = he->h_addrtype;
- memcpy (&sa->sin_addr,
- he->h_addr_list [0],
- he->h_length);
- }
-
- if (nicename && he->h_name)
- *nicename = g_strdup (he->h_name);
-
- rv = TRUE;
- }
- }
-#else
-#ifdef SOUP_WIN32
- {
- struct hostent *result;
-
- WaitForSingleObject (soup_hostent_Mutex, INFINITE);
- result = gethostbyname (hostname);
-
- if (result != NULL) {
- if (sa) {
- sa->sin_family = result->h_addrtype;
- memcpy (&sa->sin_addr,
- result->h_addr_list [0],
- result->h_length);
- }
-
- if (nicename && result->h_name)
- *nicename = g_strdup(result->h_name);
-
- ReleaseMutex(soup_hostent_Mutex);
- rv = TRUE;
- }
- }
-#else
- {
- struct hostent* he;
-
- he = gethostbyname (hostname);
- if (he != NULL && he->h_addr_list [0] != NULL) {
- if (sa) {
- sa->sin_family = he->h_addrtype;
- memcpy (&sa->sin_addr,
- he->h_addr_list [0],
- he->h_length);
- }
-
- if (nicename && he->h_name)
- *nicename = g_strdup (he->h_name);
-
- rv = TRUE;
- }
- }
-#endif
-#endif
-#endif
-#endif
-#endif
-
- return rv;
-}
-
-/*
- 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 gchar *
-soup_gethostbyaddr (const char* addr, size_t length, int type)
-{
- gchar* rv = NULL;
-
-#ifdef HAVE_GETHOSTBYNAME_R_GLIBC
- {
- struct hostent result_buf, *result;
- size_t len;
- char* buf;
- int herr;
- int res;
-
- len = 1024;
- buf = g_new (gchar, len);
-
- while ((res = gethostbyaddr_r (addr,
- length,
- type,
- &result_buf,
- buf,
- len,
- &result,
- &herr)) == ERANGE) {
- len *= 2;
- buf = g_renew (gchar, buf, len);
- }
-
- if (res || result == NULL || result->h_name == NULL)
- goto done;
-
- rv = g_strdup(result->h_name);
-
- done:
- g_free(buf);
- }
-#else
-#ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
- {
- struct hostent result;
- size_t len;
- char* buf;
- int herr;
- int res;
-
- len = 1024;
- buf = g_new (gchar, len);
-
- while ((res = gethostbyaddr_r (addr,
- length,
- type,
- &result,
- buf,
- len,
- &herr)) == ERANGE) {
- len *= 2;
- buf = g_renew (gchar, buf, len);
- }
-
- if (res || hp == NULL || hp->h_name == NULL)
- goto done;
-
- rv = g_strdup(result->h_name);
-
- done:
- g_free(buf);
- }
-#else
-#ifdef HAVE_GETHOSTBYNAME_R_HPUX
- {
- struct hostent result;
- struct hostent_data buf;
- int res;
-
- res = gethostbyaddr_r (addr, length, type, &result, &buf);
-
- if (res == 0) rv = g_strdup (result.h_name);
- }
-#else
-#ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
- {
- struct hostent* he;
-
- G_LOCK (gethostbyname);
- he = gethostbyaddr (addr, length, type);
- G_UNLOCK (gethostbyname);
- if (he != NULL && he->h_name != NULL)
- rv = g_strdup (he->h_name);
- }
-#else
-#ifdef SOUP_WIN32
- {
- struct hostent* he;
-
- WaitForSingleObject (soup_hostent_Mutex, INFINITE);
- he = gethostbyaddr (addr, length, type);
- if (he != NULL && he->h_name != NULL)
- rv = g_strdup (he->h_name);
- ReleaseMutex (soup_hostent_Mutex);
- }
-#else
- {
- struct hostent* he;
-
- he = gethostbyaddr (addr, length, type);
- if (he != NULL && he->h_name != NULL)
- rv = g_strdup (he->h_name);
- }
-#endif
-#endif
-#endif
-#endif
-#endif
-
- return rv;
-}
-
-#ifndef SOUP_WIN32 /*********** Unix code ***********/
-
-static gboolean
-soup_address_new_cb (GIOChannel* iochannel,
- GIOCondition condition,
- gpointer data)
-{
- SoupAddressState* state = (SoupAddressState*) data;
- struct sockaddr_in* sa_in;
- GSList *cb_list, *iter;
- SoupAddressNewFn cb_func;
- gpointer cb_data;
-
- if (!(condition & G_IO_IN)) {
- int ret;
-
- g_source_remove (state->watch);
- close (state->fd);
- waitpid (state->pid, &ret, 0);
-
- if (WIFSIGNALED (ret) || WEXITSTATUS (ret) != 1) goto ERROR;
-
- /*
- * Exit status of one means we are inside a debugger.
- * Resolve the name synchronously.
- */
- sa_in = (struct sockaddr_in*) &state->ia.sa;
-
- if (!soup_gethostbyname (state->ia.name, sa_in, NULL))
- g_warning ("Problem resolving host name");
- } else {
- int rv;
- char* buf;
- int length;
-
- buf = &state->buffer [state->len];
- length = sizeof (state->buffer) - state->len;
-
- 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_in = (struct sockaddr_in*) &state->ia.sa;
- memcpy (&sa_in->sin_addr, &state->buffer [1], (state->len - 1));
-
- /* Cleanup state */
- g_source_remove (state->watch);
- close (state->fd);
- waitpid (state->pid, NULL, WNOHANG);
- }
-
- /* Get state data before realloc */
- cb_list = iter = state->cb_list;
- cb_func = state->func;
- cb_data = state->data;
-
- /* Invert resolved address reference count */
- state->ia.ref_count = ~state->ia.ref_count + 1;
-
- /*
- * Realloc state to size of SoupAddress, and reinsert to resolved
- * address table.
- */
- state = g_realloc (state, sizeof (SoupAddress));
- g_hash_table_insert (active_address_hash, state->ia.name, state);
-
- (*cb_func) (&state->ia, SOUP_ADDRESS_STATUS_OK, cb_data);
-
- while (iter) {
- SoupAddressCbData *cb = iter->data;
-
- (*cb->func) (&state->ia, SOUP_ADDRESS_STATUS_OK, cb->data);
-
- g_free (cb);
- iter = iter->next;
- }
-
- g_slist_free (cb_list);
-
- return FALSE;
-
- ERROR:
- /* Remove the watch now in case we don't return immediately */
- g_source_remove (state->watch);
-
- (*state->func) (NULL, SOUP_ADDRESS_STATUS_ERROR, state->data);
-
- for (cb_list = state->cb_list; cb_list; cb_list = cb_list->next) {
- SoupAddressCbData *cb_data = cb_list->data;
- (*cb_data->func) (NULL,
- SOUP_ADDRESS_STATUS_ERROR,
- cb_data->data);
- }
-
- /* Force cancel */
- state->ia.ref_count = -1;
- soup_address_new_cancel (state);
-
- 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.
- * @port: port number (0 if the port doesn't matter)
- * @func: Callback function.
- * @data: User data passed when callback function is called.
- *
- * Create a SoupAddress from a name and port 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.
- *
- * The Unix version 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, we recommend calling
- * g_main_iteration(FALSE) between calls. This will help prevent an
- * explosion of processes.
- *
- * If you need a more robust library for Unix, look at <ulink
- * url="http://www.gnu.org/software/adns/adns.html">GNU ADNS</ulink>.
- * GNU ADNS is under the GNU GPL.
- *
- * The Windows version should work fine. Windows has an asynchronous
- * DNS lookup function.
- *
- * Returns: ID of the lookup which can be used with
- * soup_address_new_cancel() to cancel it; NULL on immediate
- * success or failure.
- **/
-SoupAddressNewId
-soup_address_new (const gchar* name,
- const gint port,
- SoupAddressNewFn func,
- gpointer data)
-{
- pid_t pid = -1;
- int pipes [2];
- struct in_addr inaddr;
- struct sockaddr_in sa;
- struct sockaddr_in* sa_in;
- SoupAddress* ia;
- SoupAddressState* state;
- GIOChannel *chan;
-
- 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 */
- if (inet_aton (name, &inaddr) != 0) {
- ia = g_new0 (SoupAddress, 1);
- ia->ref_count = 1;
-
- sa_in = (struct sockaddr_in*) &ia->sa;
- sa_in->sin_family = AF_INET;
- sa_in->sin_port = g_htons(port);
- memcpy (&sa_in->sin_addr,
- (char*) &inaddr,
- sizeof(struct in_addr));
-
- (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
- return NULL;
- }
-
- if (!active_address_hash)
- active_address_hash = g_hash_table_new (soup_str_case_hash,
- soup_str_case_equal);
- else {
- ia = g_hash_table_lookup (active_address_hash, name);
-
- if (ia && ia->ref_count > 0) {
- /*
- * Existing valid request, use it.
- */
- if (soup_address_get_port (ia) == port) {
- soup_address_ref (ia);
- } else {
- /*
- * We can reuse the address, but we have to
- * change port
- */
- SoupAddress *new_ia = soup_address_copy (ia);
- soup_address_set_port (new_ia, port);
- ia = new_ia;
- }
-
- (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
- return NULL;
- } else if (ia && soup_address_get_port (ia) == port) {
- /*
- * Lookup currently in progress.
- * Add func to list of callbacks in state.
- * Note that if it's not the same port, we have to do
- * the lookup again, since there's no way to communicate
- * the port change.
- */
- SoupAddressCbData *cb_data;
-
- cb_data = g_new0 (SoupAddressCbData, 1);
- cb_data->func = func;
- cb_data->data = data;
-
- state = (SoupAddressState *) ia;
- state->cb_list = g_slist_prepend (state->cb_list,
- cb_data);
-
- state->ia.ref_count--;
-
- return state;
- }
- }
-
- /* Check to see if we are doing synchronous DNS lookups */
- if (getenv ("SOUP_SYNC_DNS")) {
- if (!soup_gethostbyname (name, &sa, NULL)) {
- g_warning ("Problem resolving host name");
- (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
- return NULL;
- }
-
- sa_in = (struct sockaddr_in*) &sa;
- sa_in->sin_family = AF_INET;
- sa_in->sin_port = g_htons (port);
-
- ia = g_new0(SoupAddress, 1);
- ia->name = g_strdup (name);
- ia->ref_count = 1;
- ia->sa = *((struct sockaddr *) &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 PTRACE_ATTACH
- signal (SIGCHLD, SIG_IGN);
-
- if (ptrace (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.
- */
- waitpid (getppid (), NULL, 0);
-
- if (ptrace (PTRACE_DETACH, getppid (), NULL, NULL) == -1)
- g_warning ("ptrace: Detach failed: %s",
- strerror(errno));
-
- kill (getppid(), SIGCONT);
-#endif
-
- /*
- * Try to get the host by name (ie, DNS)
- */
- if (soup_gethostbyname (name, &sa, NULL)) {
- guchar size = 4; /* FIX for IPv6 */
-
- if ((write (pipes [1], &size, sizeof(guchar)) == -1) ||
- (write (pipes [1], &sa.sin_addr, size) == -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 (SoupAddressState, 1);
- state->ia.name = g_strdup (name);
- state->ia.ref_count = -1;
- state->func = func;
- state->data = data;
- state->pid = pid;
- state->fd = pipes [0];
-
- sa_in = (struct sockaddr_in*) &state->ia.sa;
- sa_in->sin_family = AF_INET;
- sa_in->sin_port = g_htons (port);
-
- g_hash_table_insert (active_address_hash,
- state->ia.name,
- state);
-
- chan = g_io_channel_unix_new (pipes [0]);
-
- /* Set up an watch to read from the pipe */
- 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 state;
- }
-}
-
-/**
- * soup_address_new_cancel:
- * @id: ID of the lookup
- *
- * Cancel an asynchronous SoupAddress creation that was started with
- * soup_address_new().
- */
-void
-soup_address_new_cancel (SoupAddressNewId id)
-{
- SoupAddressState* state = (SoupAddressState*) id;
- GSList *cb_list;
-
- g_return_if_fail (state != NULL);
-
- state->ia.ref_count++;
-
- if (state->ia.ref_count == 0) {
- g_hash_table_remove (active_address_hash, state->ia.name);
- g_free (state->ia.name);
-
- for (cb_list = state->cb_list; cb_list; cb_list = cb_list->next)
- g_free (cb_list->data);
- g_slist_free (state->cb_list);
-
- g_source_remove (state->watch);
-
- close (state->fd);
- kill (state->pid, SIGKILL);
- waitpid (state->pid, NULL, 0);
-
- g_free (state);
- }
-}
-
-#else /*********** Windows code ***********/
-
-static gboolean
-soup_address_new_cb (GIOChannel* iochannel,
- GIOCondition condition,
- gpointer data)
-{
- SoupAddressState* state = (SoupAddressState*) data;
- struct hostent *result;
- struct sockaddr_in *sa_in;
-
- if (state->errorcode) {
- (*state->func) (&state->ia,
- SOUP_ADDRESS_STATUS_ERROR,
- state->data);
- g_free (state);
- return FALSE;
- }
-
- result = (struct hostent*) state->hostentBuffer;
-
- sa_in = (struct sockaddr_in*) &state->ia.sa;
- memcpy (&sa_in->sin_addr, result->h_addr_list [0], result->h_length);
-
- state->ia.name = g_strdup (result->h_name);
-
- state = g_realloc (state, sizeof (SoupAddress));
-
- (*state->func) (&state->ia, SOUP_ADDRESS_STATUS_OK, state->data);
- g_free (state);
-
- return FALSE;
-}
-
-SoupAddressNewId
-soup_address_new (const gchar* name,
- const gint port,
- SoupAddressNewFn func,
- gpointer data)
-{
- struct in_addr inaddr;
- struct sockaddr_in* sa_in;
- SoupAddressState* state;
-
- 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.s_addr = inet_addr(name);
- if (inaddr.s_addr != INADDR_NONE) {
- SoupAddress* ia = NULL;
- struct sockaddr_in* sa_in;
-
- ia = g_new0(SoupAddress, 1);
- ia->ref_count = 1;
-
- sa_in = (struct sockaddr_in*) &ia->sa;
- sa_in->sin_family = AF_INET;
- sa_in->sin_port = g_htons (port);
- memcpy (&sa_in->sin_addr,
- (char*) &inaddr,
- sizeof (struct in_addr));
-
- (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
- return NULL;
- }
-
- /* Create a structure for the call back */
- state = g_new0 (SoupAddressState, 1);
- state->ia.name = g_strdup (name);
- state->ia.ref_count = 1;
- state->func = func;
- state->data = data;
-
- sa_in = (struct sockaddr_in*) &state->ia.sa;
- sa_in->sin_family = AF_INET;
- sa_in->sin_port = g_htons (port);
-
- state->WSAhandle = (int)
- WSAAsyncGetHostByName (soup_hWnd,
- IA_NEW_MSG,
- name,
- state->hostentBuffer,
- sizeof (state->hostentBuffer));
-
- if (!state->WSAhandle) {
- g_free (state);
- (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
- return NULL;
- }
-
- /*get a lock and insert the state into the hash */
- WaitForSingleObject (soup_Mutex, INFINITE);
- g_hash_table_insert (soup_hash,
- (gpointer) state->WSAhandle,
- (gpointer) state);
- ReleaseMutex (soup_Mutex);
-
- return state;
-}
-
-void
-soup_address_new_cancel (SoupAddressNewId id)
-{
- SoupAddressState* state = (SoupAddressState*) id;
-
- g_return_if_fail(state != NULL);
-
- WSACancelAsyncRequest ((HANDLE)state->WSAhandle);
-
- /*get a lock and remove the hash entry */
- WaitForSingleObject (soup_Mutex, INFINITE);
- g_hash_table_remove (soup_hash, (gpointer) state->WSAhandle);
- ReleaseMutex (soup_Mutex);
- g_free (state);
-}
-
-#endif /*********** End Windows code ***********/
-
static void
soup_address_new_sync_cb (SoupAddress *addr,
SoupAddressStatus status,
@@ -1060,7 +88,6 @@ soup_address_ref (SoupAddress* ia)
++ia->ref_count;
}
-
/**
* soup_address_unref
* @ia: SoupAddress to unreference
@@ -1107,345 +134,6 @@ soup_address_copy (SoupAddress* ia)
return new_ia;
}
-#ifndef SOUP_WIN32 /*********** Unix code ***********/
-
-static gboolean
-soup_address_get_name_cb (GIOChannel* iochannel,
- GIOCondition condition,
- gpointer data)
-{
- SoupAddressReverseState* state;
- gchar* name = NULL;
-
- state = (SoupAddressReverseState*) 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 */
- name = g_new (gchar, state->buffer [0] + 1);
- strncpy (name, &state->buffer [1], state->buffer [0]);
- name [state->buffer [0]] = '\0';
-
- state->ia->name = name;
-
- /* 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,
- name,
- state->data);
-
- close (state->fd);
- waitpid (state->pid, NULL, 0);
- g_free (state);
- return FALSE;
- }
- }
-
- /* 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_ERROR,
- NULL,
- state->data);
- soup_address_get_name_cancel (state);
- return FALSE;
-}
-
-/**
- * soup_address_get_name:
- * @ia: 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.
- *
- * The Unix version forks and does the reverse lookup. This has
- * problems. See the notes for soup_address_new(). The
- * Windows version should work fine.
- *
- * Returns: ID of the lookup which can be used with
- * soup_addressr_get_name_cancel() to cancel it; NULL on
- * immediate success or failure.
- **/
-SoupAddressGetNameId
-soup_address_get_name (SoupAddress* ia,
- SoupAddressGetNameFn func,
- gpointer data)
-{
- SoupAddressReverseState* state;
- gchar* name;
- guchar len;
- pid_t pid = -1;
- int pipes [2];
-
- g_return_val_if_fail (ia != NULL, NULL);
- g_return_val_if_fail (func != NULL, NULL);
-
- if (ia->name) {
- (func) (ia, SOUP_ADDRESS_STATUS_OK, ia->name, data);
- return NULL;
- }
-
- /* 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;
- }
-
- 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 (
- (char*) &((struct sockaddr_in*)&ia->sa)->sin_addr,
- sizeof (struct in_addr),
- AF_INET);
-
- if (name) {
- guint 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);
- } else {
- /* defined in netinet/in.h */
- gchar buffer [INET_ADDRSTRLEN];
- guchar* p;
- p = (guchar*) &(SOUP_SOCKADDR_IN (ia->sa).sin_addr);
-
- g_snprintf(buffer,
- sizeof (buffer),
- "%d.%d.%d.%d",
- p [0],
- p [1],
- p [2],
- p [3]);
- len = strlen (buffer);
-
- if ((write (pipes [1], &len, sizeof(len)) == -1) ||
- (write (pipes [1], buffer, len) == -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]);
-
- 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;
- }
-}
-
-/**
- * soup_address_get_name_cancel:
- * @id: ID of the lookup
- *
- * Cancel an asynchronous nice name lookup that was started with
- * soup_address_get_name().
- */
-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);
-
- close (state->fd);
- kill (state->pid, SIGKILL);
- waitpid (state->pid, NULL, 0);
-
- g_free(state);
-}
-
-#else /*********** Windows code ***********/
-
-static gboolean
-soup_address_get_name_cb (GIOChannel* iochannel,
- GIOCondition condition,
- gpointer data)
-{
- SoupAddressReverseState* state;
- gchar* name;
- struct hostent* result;
- state = (SoupAddressReverseState*) data;
-
- result = (struct hostent*) state->hostentBuffer;
-
- if (state->errorcode) {
- (*state->func) (state->ia,
- SOUP_ADDRESS_STATUS_ERROR,
- NULL,
- state->data);
- return FALSE;
- }
-
- state->ia->name = g_strdup (result->h_name);
- name = NULL;
- name = g_strdup (state->ia->name);
-
- (*state->func) (state->ia,
- SOUP_ADDRESS_STATUS_OK,
- name,
- state->data);
-
- g_free(state);
- return FALSE;
-}
-
-SoupAddressGetNameId
-soup_address_get_name (SoupAddress* ia,
- SoupAddressGetNameFn func,
- gpointer data)
-{
- SoupAddressReverseState* state;
- struct sockaddr_in* sa_in;
-
- g_return_val_if_fail(ia != NULL, NULL);
- g_return_val_if_fail(func != NULL, NULL);
-
- /* If we already know the name, just copy that */
- if (ia->name != NULL) {
- (func) (ia,
- SOUP_ADDRESS_STATUS_OK,
- g_strdup (ia->name),
- data);
- }
-
- /* Create a structure for the call back */
- state = g_new0 (SoupAddressReverseState, 1);
- state->ia = ia;
- state->func = func;
- state->data = data;
-
- sa_in = (struct sockaddr_in*) &ia->sa;
-
- state->WSAhandle = (int)
- WSAAsyncGetHostByAddr (soup_hWnd, GET_NAME_MSG,
- (const char*) &sa_in->sin_addr,
- (int) (sizeof (&sa_in->sin_addr)),
- (int) &sa_in->sin_family,
- state->hostentBuffer,
- sizeof (state->hostentBuffer));
-
- if (!state->WSAhandle) {
- g_free (state);
- (func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
- return NULL;
- }
-
- /*get a lock and insert the state into the hash */
- WaitForSingleObject (soup_Mutex, INFINITE);
- g_hash_table_insert (soup_hash,
- (gpointer) state->WSAhandle,
- (gpointer) state);
- ReleaseMutex (soup_Mutex);
-
- return state;
-}
-
-void
-soup_address_get_name_cancel (SoupAddressGetNameId id)
-{
- SoupAddressReverseState* state;
- state = (SoupAddressReverseState*) id;
-
- g_return_if_fail(state != NULL);
-
- soup_address_unref (state->ia);
- WSACancelAsyncRequest ((HANDLE) state->WSAhandle);
-
- /*get a lock and remove the hash entry */
- WaitForSingleObject (soup_Mutex, INFINITE);
- g_hash_table_remove (soup_hash, (gpointer) state->WSAhandle);
- ReleaseMutex (soup_Mutex);
-
- g_free (state);
-}
-
-#endif /*********** End Windows code ***********/
-
static void
soup_address_get_name_sync_cb (SoupAddress *addr,
SoupAddressStatus status,
@@ -1462,9 +150,7 @@ soup_address_get_name_sync (SoupAddress *addr)
const char *ret = (const char *) 0xdeadbeef;
soup_address_get_name (addr,
-
soup_address_get_name_sync_cb,
-
(gpointer) &ret);
while (1) {
@@ -1606,49 +292,6 @@ soup_address_noport_equal (const gpointer p1, const gpointer p2)
SOUP_SOCKADDR_IN(ia2->sa).sin_addr.s_addr);
}
-#ifndef SOUP_WIN32 /*********** Unix code ***********/
-
-/**
- * soup_address_gethostname:
- *
- * Get the primary host's name.
- *
- * Returns: the name of the host; NULL if there was an error. The
- * caller is responsible for deleting the returned string.
- **/
-gchar*
-soup_address_gethostname (void)
-{
- gchar* name = NULL;
- struct utsname myname;
-
- if (uname (&myname) < 0) return NULL;
-
- if (!soup_gethostbyname (myname.nodename, NULL, &name)) return NULL;
-
- return name;
-}
-
-#else /*********** Windows code ***********/
-
-gchar*
-soup_address_gethostname (void)
-{
- gchar* name = NULL;
- int error = 0;
-
- name = g_new0 (char, 256);
- error = gethostname (name, 256);
- if (error) {
- g_free(name);
- return NULL;
- }
-
- return name;
-}
-
-#endif /*********** End Windows code ***********/
-
/**
* soup_address_gethostaddr:
*
@@ -1666,7 +309,7 @@ soup_address_gethostaddr (void)
name = soup_address_gethostname ();
- if (name && soup_gethostbyname(name, &sa, NULL)) {
+ if (name && soup_gethostbyname (name, &sa, NULL)) {
ia = g_new0 (SoupAddress, 1);
ia->name = g_strdup (name);
ia->ref_count = 1;
@@ -1818,261 +461,6 @@ soup_socket_connect_sync (const gchar *name,
return ret;
}
-
-#ifndef SOUP_WIN32 /*********** Unix code ***********/
-
-static gboolean
-soup_socket_new_cb (GIOChannel* iochannel,
- GIOCondition condition,
- gpointer data)
-{
- SoupSocketState* state = (SoupSocketState*) data;
- SoupSocket* s;
- gint error = 0;
- gint len = sizeof (gint);
-
- /* Remove the watch now in case we don't return immediately */
- g_source_remove (state->connect_watch);
-
- if (condition & ~(G_IO_IN | G_IO_OUT)) goto ERROR;
-
- errno = 0;
- if (getsockopt (state->sockfd,
- SOL_SOCKET,
- SO_ERROR,
- &error,
- &len) != 0) goto ERROR;
-
- if (error) goto ERROR;
-
- 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;
-
- (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
-
- g_free (state);
-
- return FALSE;
-
- ERROR:
- soup_address_unref (state->addr);
- (*state->func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, state->data);
- g_free (state);
-
- return FALSE;
-}
-
-/**
- * soup_socket_new:
- * @addr: Address to connect to.
- * @func: Callback function.
- * @data: User data passed when callback function is called.
- *
- * Connect to a specifed address asynchronously. When the connection
- * is complete or there is an error, it will call the callback. It
- * may call the callback before the function returns. It will call
- * the callback if there is a failure.
- *
- * Returns: ID of the connection which can be used with
- * soup_socket_connect_cancel() to cancel it; NULL on
- * failure.
- **/
-SoupSocketNewId
-soup_socket_new (SoupAddress *addr,
- SoupSocketNewFn func,
- gpointer data)
-{
- gint sockfd;
- gint flags;
- SoupSocketState* state;
- GIOChannel *chan;
-
- g_return_val_if_fail(addr != NULL, NULL);
- g_return_val_if_fail(func != NULL, NULL);
-
- /* Create socket */
- sockfd = socket (AF_INET, SOCK_STREAM, 0);
- if (sockfd < 0) {
- (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
- return NULL;
- }
-
- /* Get the flags (should all be 0?) */
- flags = fcntl (sockfd, F_GETFL, 0);
- if (flags == -1) {
- (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
- return NULL;
- }
-
- if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
- (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
- return NULL;
- }
-
- errno = 0;
-
- /* Connect (but non-blocking!) */
- if (connect (sockfd, &addr->sa, sizeof (addr->sa)) < 0 &&
- errno != EINPROGRESS) {
- (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
- return NULL;
- }
-
- /* Unref in soup_socket_new_cb if failure */
- soup_address_ref (addr);
-
- /* Connect succeeded, return immediately */
- if (!errno) {
- SoupSocket *s = g_new0 (SoupSocket, 1);
- s->ref_count = 1;
- s->sockfd = sockfd;
- s->addr = addr;
-
- (*func) (s, SOUP_SOCKET_NEW_STATUS_OK, data);
- return NULL;
- }
-
- chan = SOUP_SOCKET_IOCHANNEL_NEW (sockfd);
-
- /* Wait for the connection */
- state = g_new0 (SoupSocketState, 1);
- state->sockfd = sockfd;
- state->addr = addr;
- state->func = func;
- state->data = data;
- state->flags = flags;
- state->connect_watch = g_io_add_watch (chan,
- SOUP_ANY_IO_CONDITION,
- soup_socket_new_cb,
- state);
-
- g_io_channel_unref (chan);
-
- return state;
-}
-
-#else /*********** Windows code ***********/
-
-static gboolean
-soup_socket_new_cb (GIOChannel* iochannel,
- GIOCondition condition,
- gpointer data)
-{
- SoupSocketState* state = (SoupSocketState*) data;
- SoupSocket *s;
-
- /* Remove the watch now in case we don't return immediately */
- g_source_remove (state->connect_watch);
-
- if (condition & ~(G_IO_IN | G_IO_OUT)) goto _ERROR;
-
- s = g_new0 (SoupSocket, 1);
- s->ref_count = 1;
- s->sockfd = state->sockfd;
- s->addr = state->addr;
-
- (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
- g_free (state);
- return FALSE;
-
- _ERROR:
- soup_address_unref (state->addr);
- (*state->func) ((SoupSocket *) NULL,
- SOUP_SOCKET_NEW_STATUS_ERROR,
- state->data);
- g_free (state);
-
- return FALSE;
-}
-
-SoupSocketNewId
-soup_socket_new (SoupAddress *addr,
- SoupSocketNewFn func,
- gpointer data)
-{
- gint sockfd;
- gint status;
- SoupSocketState* state = (SoupSocketState*) data;
- u_long arg = 1;
- GIOChannel *chan;
-
- g_return_val_if_fail (addr != NULL, NULL);
- g_return_val_if_fail (func != NULL, NULL);
-
- /* Create socket */
- sockfd = socket (AF_INET, SOCK_STREAM, 0);
- if (sockfd == INVALID_SOCKET) {
- (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
- return NULL;
- }
-
- /* Set non-blocking mode */
- ioctlsocket(sockfd, FIONBIO, &arg);
-
- status = connect (sockfd, &addr->sa, sizeof(addr->sa));
- /* Returning an error is ok, unless.. */
- if (status == SOCKET_ERROR) {
- status = WSAGetLastError();
- if (status != WSAEWOULDBLOCK) {
- (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
- return NULL;
- }
- }
-
- soup_address_ref (addr);
-
- if (status != SOCKET_ERROR) {
- SoupSocket *s = g_new0 (SoupSocket, 1);
- s->ref_count = 1;
- s->sockfd = sockfd;
- s->addr = addr;
-
- (*func) (s, SOUP_SOCKET_NEW_STATUS_OK, data);
- return NULL;
- }
-
- chan = SOUP_SOCKET_IOCHANNEL_NEW (sockfd),
-
- /* Wait for the connection */
- state = g_new0 (SoupSocketState, 1);
- state->addr = addr;
- state->func = func;
- state->data = data;
- state->sockfd = sockfd;
- state->connect_watch = g_io_add_watch (chan,
- SOUP_ANY_IO_CONDITION,
- soup_socket_new_cb,
- state);
-
- g_io_channel_unref (chan);
-
- return state;
-}
-
-#endif /*********** End Windows code ***********/
-
-/**
- * soup_socket_new_cancel:
- * @id: ID of the connection.
- *
- * Cancel an asynchronous connection that was started with
- * soup_socket_new().
- **/
-void
-soup_socket_new_cancel (SoupSocketNewId id)
-{
- SoupSocketState* state = (SoupSocketState*) id;
-
- g_source_remove (state->connect_watch);
- soup_address_unref (state->addr);
- g_free (state);
-}
-
static void
soup_socket_new_sync_cb (SoupSocket* socket,
SoupSocketNewStatus status,
@@ -2127,9 +515,7 @@ soup_socket_unref (SoupSocket* s)
if (s->ref_count == 0) {
SOUP_CLOSE_SOCKET (s->sockfd);
-
if (s->addr) soup_address_unref (s->addr);
-
if (s->iochannel) g_io_channel_unref (s->iochannel);
g_free(s);
@@ -2290,408 +676,3 @@ soup_socket_server_new (const gint port)
g_free (s);
return NULL;
}
-
-#ifndef SOUP_WIN32 /*********** Unix code ***********/
-
-/**
- * soup_socket_server_accept:
- * @socket: #SoupSocket to accept connections from.
- *
- * Accept a connection from the socket. The socket must have been
- * created using soup_socket_server_new(). This function will
- * block (use soup_socket_server_try_accept() if you don't
- * want to block). If the socket's #GIOChannel is readable, it DOES
- * NOT mean that this function will not block.
- *
- * Returns: a new #SoupSocket if there is another connect, or NULL if
- * there's an error.
- **/
-SoupSocket *
-soup_socket_server_accept (SoupSocket *socket)
-{
- gint sockfd;
- gint flags;
- struct sockaddr sa;
- socklen_t n;
- fd_set fdset;
- SoupSocket* s;
-
- g_return_val_if_fail (socket != NULL, NULL);
-
- try_again:
- FD_ZERO (&fdset);
- FD_SET (socket->sockfd, &fdset);
-
- if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
- if (errno == EINTR) goto try_again;
- return NULL;
- }
-
- n = sizeof(s->addr->sa);
-
- if ((sockfd = accept (socket->sockfd, &sa, &n)) == -1) {
- if (errno == EWOULDBLOCK ||
- errno == ECONNABORTED ||
-#ifdef EPROTO /* OpenBSD does not have EPROTO */
- errno == EPROTO ||
-#endif
- errno == EINTR)
- goto try_again;
-
- return NULL;
- }
-
- /* Get the flags (should all be 0?) */
- flags = fcntl (sockfd, F_GETFL, 0);
- if (flags == -1) return NULL;
-
- /* Make the socket non-blocking */
- 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 = g_new0 (SoupAddress, 1);
- s->addr->ref_count = 1;
- memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
-
- return s;
-}
-
-/**
- * soup_socket_server_try_accept:
- * @socket: SoupSocket to accept connections from.
- *
- * Accept a connection from the socket without blocking. The socket
- * must have been created using soup_socket_server_new(). This
- * function is best used with the sockets #GIOChannel. If the
- * channel is readable, then you PROBABLY have a connection. It is
- * possible for the connection to close by the time you call this, so
- * it may return NULL even if the channel was readable.
- *
- * Returns a new SoupSocket if there is another connect, or NULL
- * otherwise.
- **/
-SoupSocket *
-soup_socket_server_try_accept (SoupSocket *socket)
-{
- gint sockfd;
- gint flags;
- struct sockaddr sa;
- socklen_t n;
- fd_set fdset;
- SoupSocket* s;
- struct timeval tv = {0, 0};
-
- g_return_val_if_fail (socket != NULL, NULL);
-
- try_again:
- FD_ZERO (&fdset);
- FD_SET (socket->sockfd, &fdset);
-
- if (select (socket->sockfd + 1, &fdset, NULL, NULL, &tv) == -1) {
- if (errno == EINTR) goto try_again;
- return NULL;
- }
-
- n = sizeof(sa);
-
- if ((sockfd = accept (socket->sockfd, &sa, &n)) == -1) {
- /* If we get an error, return. We don't want to try again as we
- do in soup_socket_server_accept() - it might cause a
- block. */
- return NULL;
- }
-
- /* Get the flags (should all be 0?) */
- flags = fcntl (sockfd, F_GETFL, 0);
- if (flags == -1) return NULL;
-
- /* Make the socket non-blocking */
- 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 = g_new0 (SoupAddress, 1);
- s->addr->ref_count = 1;
- memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
-
- return s;
-}
-
-#else /*********** Windows code ***********/
-
-SoupSocket *
-soup_socket_server_accept (SoupSocket *socket)
-{
- gint sockfd;
- struct sockaddr sa;
- gint n;
- fd_set fdset;
- SoupSocket* s;
- u_long arg;
-
- g_return_val_if_fail (socket != NULL, NULL);
-
- FD_ZERO (&fdset);
- FD_SET ((unsigned)socket->sockfd, &fdset);
-
- if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
- return NULL;
- }
-
- /* make sure the socket is in blocking mode */
-
- arg = 0;
- if (ioctlsocket (socket->sockfd, FIONBIO, &arg))
- return NULL;
-
- sockfd = accept (socket->sockfd, &sa, NULL);
- /* if it fails, looping isn't going to help */
-
- if (sockfd == INVALID_SOCKET) {
- return NULL;
- }
-
- s = g_new0 (SoupSocket, 1);
- s->ref_count = 1;
- s->sockfd = sockfd;
-
- s->addr = g_new0 (SoupAddress, 1);
- s->addr->ref_count = 1;
- memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
-
- return s;
-}
-
-SoupSocket *
-soup_socket_server_try_accept (SoupSocket *socket)
-{
- gint sockfd;
- struct sockaddr sa;
-
- fd_set fdset;
- SoupSocket* s;
- u_long arg;
-
- g_return_val_if_fail (socket != NULL, NULL);
- FD_ZERO (&fdset);
- FD_SET ((unsigned)socket->sockfd, &fdset);
-
- if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
- return NULL;
- }
- /* make sure the socket is in non-blocking mode */
-
- arg = 1;
- if (ioctlsocket (socket->sockfd, FIONBIO, &arg))
- return NULL;
-
- sockfd = accept (socket->sockfd, &sa, NULL);
- /* if it fails, looping isn't going to help */
-
- if (sockfd == INVALID_SOCKET) {
- return NULL;
- }
-
- s = g_new0 (SoupSocket, 1);
- s->ref_count = 1;
- s->sockfd = sockfd;
-
- s->addr = g_new0 (SoupAddress, 1);
- s->addr->ref_count = 1;
- memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
-
- return s;
-}
-#endif /*********** End Windows code ***********/
-
-#ifdef SOUP_WIN32 /*********** Windows code ***********/
-int
-soup_MainCallBack (GIOChannel *iochannel,
- GIOCondition condition,
- void *nodata)
-{
- MSG msg;
-
- gpointer data;
- SoupAddressState *IAstate;
- SoupAddressReverseState *IARstate;
-
- /*Take the msg off the message queue */
- PeekMessage (&msg, soup_hWnd, 0, 0, PM_REMOVE);
-
- switch (msg.message) {
- case IA_NEW_MSG:
- WaitForSingleObject (soup_Mutex, INFINITE);
- data = g_hash_table_lookup (soup_hash, (gpointer) msg.wParam);
- g_hash_table_remove (soup_hash, (gpointer) msg.wParam);
- ReleaseMutex (soup_Mutex);
-
- IAstate = (SoupAddressState*) data;
- /* NULL if OK */
- IAstate->errorcode = WSAGETASYNCERROR(msg.lParam);
-
- /* Now call the callback function */
- soup_address_new_cb (NULL, G_IO_IN, (gpointer) IAstate);
-
- break;
- case GET_NAME_MSG:
- WaitForSingleObject (soup_Mutex, INFINITE);
- data = g_hash_table_lookup (soup_hash, (gpointer) msg.wParam);
- g_hash_table_remove (soup_hash, (gpointer) msg.wParam);
- ReleaseMutex (soup_Mutex);
-
- IARstate = (SoupAddressReverseState*) data;
- /* NULL if OK */
- IARstate->errorcode = WSAGETASYNCERROR(msg.lParam);
-
- /* Now call the callback function */
- soup_address_get_name_cb (NULL,
- G_IO_IN,
- (gpointer) IARstate);
- break;
- }
-
- return 1;
-}
-
-LRESULT CALLBACK
-SoupWndProc (HWND hwnd, /* handle to window */
- UINT uMsg, /* message identifier */
- WPARAM wParam, /* first message parameter */
- LPARAM lParam) /* second message parameter */
-{
- switch (uMsg) {
- case WM_CREATE: /* Initialize the window. */
- return 0;
- case WM_PAINT: /* Paint the window's client area. */
- return 0;
- case WM_SIZE: /* Set the size and position of the window. */
- return 0;
- case WM_DESTROY: /* Clean up window-specific data objects. */
- return 0;
-
- default:
- return DefWindowProc (hwnd, uMsg, wParam, lParam);
- }
-}
-
-BOOL WINAPI
-DllMain (HINSTANCE hinstDLL, /* handle to DLL module */
- DWORD fdwReason, /* reason for calling functionm */
- LPVOID lpvReserved /* reserved */)
-{
- WORD wVersionRequested;
- WSADATA wsaData;
- int err;
-
- switch(fdwReason) {
- case DLL_PROCESS_ATTACH:
- /* The DLL is being mapped into process's address space */
- /* Do any required initialization on a per application basis,
- return FALSE if failed */
- wVersionRequested = MAKEWORD (2, 0);
-
- err = WSAStartup (wVersionRequested, &wsaData);
- if (err != 0) {
- /* Tell the user that we could not find a usable
- WinSock DLL. */
- return FALSE;
- }
-
- /* Confirm that the WinSock DLL supports 2.0.*/
- /* Note that if the DLL supports versions greater */
- /* than 2.0 in addition to 2.0, it will still return */
- /* 2.0 in wVersion since that is the version we */
- /* requested. */
-
- if (LOBYTE(wsaData.wVersion) != 2 ||
- HIBYTE(wsaData.wVersion) != 0) {
- /* Tell the user that we could not find a usable */
- /* WinSock DLL. */
- WSACleanup ();
- return FALSE;
- }
-
- /* The WinSock DLL is acceptable. Proceed. */
-
- /* Setup and register a windows class that we use for out
- GIOchannel */
- soupWndClass.cbSize = sizeof (WNDCLASSEX);
- soupWndClass.style = CS_SAVEBITS;
- soupWndClass.lpfnWndProc = (WNDPROC) SoupWndProc;
- soupWndClass.cbClsExtra = 0;
- soupWndClass.cbWndExtra = 0;
- soupWndClass.hInstance = hinstDLL;
- soupWndClass.hIcon = NULL;
- soupWndClass.hCursor = NULL;
- soupWndClass.hbrBackground = NULL;
- soupWndClass.lpszMenuName = NULL;
- soupWndClass.lpszClassName = "Soup";
- soupWndClass.hIconSm = NULL;
-
- if (!RegisterClassEx (&soupWndClass)) return FALSE;
-
- soup_hWnd = CreateWindowEx (0,
- "Soup",
- "none",
- WS_OVERLAPPEDWINDOW,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- CW_USEDEFAULT,
- (HWND) NULL,
- (HMENU) NULL,
- hinstDLL,
- (LPVOID) NULL);
-
- if (!soup_hWnd) return FALSE;
-
- soup_iochannel =
- g_io_channel_win32_new_messages (
- (unsigned int) soup_hWnd);
-
- /* Add a watch */
- soup_io_watch_ID =
- g_io_add_watch (soup_iochannel,
- G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
- soup_MainCallBack,
- NULL);
-
- soup_hash = g_hash_table_new (NULL, NULL);
-
- soup_Mutex = CreateMutex (NULL, FALSE, "soup_Mutex");
- if (soup_Mutex == NULL) return FALSE;
-
- soup_hostent_Mutex = CreateMutex (NULL,
- FALSE,
- "soup_hostent_Mutex");
- if (soup_hostent_Mutex == NULL) return FALSE;
-
- break;
- case DLL_THREAD_ATTACH:
- break;
- case DLL_THREAD_DETACH:
- break;
- case DLL_PROCESS_DETACH:
- /* The DLL unmapped from process's address space. Do necessary
- cleanup */
- g_source_remove (soup_io_watch_ID);
- g_free (soup_iochannel);
- DestroyWindow (soup_hWnd);
-
- WSACleanup ();
-
- break;
- }
-
- return TRUE;
-}
-
-#endif /*********** End Windows code ***********/
diff --git a/libsoup/soup-socket.h b/libsoup/soup-socket.h
index c1a6e5e3..9b242ff2 100644
--- a/libsoup/soup-socket.h
+++ b/libsoup/soup-socket.h
@@ -15,6 +15,15 @@
#define SOUP_SOCKET_H 1
#include <glib.h>
+#include <sys/socket.h>
+
+gboolean soup_gethostbyname (const gchar *hostname,
+ struct sockaddr_in *sa,
+ gchar **nicename);
+
+gchar *soup_gethostbyaddr (const gchar *addr,
+ size_t length,
+ int type);
typedef struct _SoupAddress SoupAddress;