Remove Glib workarounds for Windows socket io.
[platform/upstream/libsoup.git] / libsoup / soup-socket.c
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3  * soup-socket.c: Asyncronous Callback-based SOAP Request Queue.
4  *
5  * Authors:
6  *      David Helder  (dhelder@umich.edu)
7  *      Alex Graveley (alex@helixcode.com)
8  *
9  * Original code compliments of David Helder's GNET Networking Library.
10  *
11  * Copyright (C) 2000, Helix Code, Inc.
12  */
13
14 #ifdef HAVE_CONFIG_H
15 #include <config.h>
16 #endif
17
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <glib.h>
21 #include <signal.h>
22 #include <stdio.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <sys/types.h>
26
27 #ifdef HAVE_SYS_PARAM_H
28 #include <sys/param.h>
29 #endif
30
31 #include "soup-private.h"
32 #include "soup-socket.h"
33
34 #ifndef SOUP_WIN32  /*********** Unix specific ***********/
35
36 #include <netdb.h>
37 #include <resolv.h>
38 #include <unistd.h>
39 #include <arpa/inet.h>
40 #include <arpa/nameser.h>
41 #include <net/if.h>
42 #include <netinet/in.h>
43 #include <sys/ioctl.h>
44 #include <sys/ptrace.h>
45 #include <sys/socket.h>
46 #include <sys/time.h>
47 #include <sys/utsname.h>
48 #include <sys/wait.h>
49
50 #ifdef HAVE_SYS_POLL_H
51 #include <sys/poll.h>
52 #endif
53
54 #ifdef HAVE_SYS_SOCKIO_H
55 #include <sys/sockio.h>
56 #endif
57
58 #ifndef socklen_t
59 #define socklen_t size_t
60 #endif
61
62 #define SOUP_CLOSE_SOCKET(SOCKFD) close(SOCKFD)
63 #define SOUP_SOCKET_IOCHANNEL_NEW(SOCKFD) g_io_channel_unix_new(SOCKFD)
64
65 /*
66  * Maintains a list of all currently valid SoupAddresses or active
67  * SoupAddressState lookup requests.
68  */
69 static GHashTable *active_address_hash = NULL;
70
71 #else   /*********** Windows specific ***********/
72
73 #include <windows.h>
74 #include <winbase.h>
75 #include <winuser.h>
76 #include <io.h>
77
78 #define socklen_t gint32
79
80 #define SOUP_CLOSE_SOCKET(SOCKFD) closesocket(SOCKFD)
81 #define SOUP_SOCKET_IOCHANNEL_NEW(SOCKFD) \
82         g_io_channel_win32_new_stream_socket(SOCKFD)
83
84 WNDCLASSEX soupWndClass;
85 HWND  soup_hWnd;
86 guint soup_io_watch_ID;
87 GIOChannel *soup_iochannel;
88
89 GHashTable *soup_hash;
90 HANDLE soup_Mutex;
91 HANDLE soup_hostent_Mutex;
92
93 #define IA_NEW_MSG 100          /* soup_address_new */
94 #define GET_NAME_MSG 101        /* soup_address_get_name */
95
96 /* 
97  * Windows does not have inet_aton, but it does have inet_addr.
98  *
99  * TODO: We should write a better inet_aton because inet_addr doesn't catch
100  * 255.255.255.255 properly.
101  */
102 static int
103 inet_aton(const char *cp, struct in_addr *inp)
104 {
105         inp->s_addr = inet_addr (cp);
106         if (inp->s_addr == INADDR_NONE) return 0;
107         return 1;
108 }
109
110 #endif  /*********** End Windows specific ***********/
111
112 #ifndef INET_ADDRSTRLEN
113 #define INET_ADDRSTRLEN 16
114 #define INET6_ADDRSTRLEN 46
115 #endif
116
117 #define SOUP_SOCKADDR_IN(s) (*((struct sockaddr_in*) &s))
118 #define SOUP_ANY_IO_CONDITION  (G_IO_IN | G_IO_OUT | G_IO_PRI | \
119                                 G_IO_ERR | G_IO_HUP | G_IO_NVAL)
120
121 typedef struct {
122         SoupAddressNewFn  func;
123         gpointer          data;
124 } SoupAddressCbData;
125
126 typedef struct {
127         SoupAddress       ia;
128         SoupAddressNewFn  func;
129         gpointer          data;
130         GSList           *cb_list;    /* CONTAINS: SoupAddressCbData */
131 #ifndef SOUP_WIN32
132         pid_t             pid;
133         int               fd;
134         guint             watch;
135         guchar            buffer [16];
136         int               len;
137 #else
138         int               WSAhandle;
139         char              hostentBuffer [MAXGETHOSTSTRUCT];
140         int               errorcode;
141 #endif
142 } SoupAddressState;
143
144
145 typedef struct {
146         SoupAddress          *ia;
147         SoupAddressGetNameFn  func;
148         gpointer              data;
149 #ifndef SOUP_WIN32
150         pid_t                 pid;
151         int                   fd;
152         guint                 watch;
153         guchar                buffer [256 + 1];
154         int                   len;
155 #else
156         int                   WSAhandle;
157         char                  hostentBuffer [MAXGETHOSTSTRUCT];
158         int                   errorcode;
159 #endif
160 } SoupAddressReverseState;
161
162
163 typedef struct {
164         gint             sockfd;
165         SoupAddress     *addr;
166         SoupSocketNewFn  func;
167         gpointer         data;
168         gint             flags;
169         guint            connect_watch;
170 #ifdef SOUP_WIN32
171         gint             errorcode;
172 #endif
173 } SoupSocketState;
174
175
176 typedef struct {
177         SoupSocketConnectFn  func;
178         gpointer             data;
179
180         gpointer             inetaddr_id;
181         gpointer             tcp_id;
182 } SoupSocketConnectState;
183
184
185 /* Testing Defines */
186 /*  #undef   HAVE_GETHOSTBYNAME_R_GLIBC */
187 /*  #define  HAVE_GETHOSTBYNAME_R_GLIB_MUTEX */
188
189 #ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
190 G_LOCK_DEFINE (gethostbyname);
191 #endif
192
193 /**
194  * soup_gethostbyname:
195  *
196  * Thread safe gethostbyname.  The only valid fields are sin_len,
197  * sin_family, and sin_addr.
198  */
199 static gboolean
200 soup_gethostbyname(const char*         hostname,
201                    struct sockaddr_in* sa,
202                    gchar**             nicename)
203 {
204         gboolean rv = FALSE;
205
206 #ifdef HAVE_GETHOSTBYNAME_R_GLIBC
207         {
208                 struct hostent result_buf, *result;
209                 size_t len;
210                 char* buf;
211                 int herr;
212                 int res;
213
214                 len = 1024;
215                 buf = g_new (gchar, len);
216
217                 while ((res = gethostbyname_r (hostname,
218                                                &result_buf,
219                                                buf,
220                                                len,
221                                                &result,
222                                                &herr)) == ERANGE) {
223                         len *= 2;
224                         buf = g_renew (gchar, buf, len);
225                 }
226
227                 if (res || result == NULL || result->h_addr_list [0] == NULL)
228                         goto done;
229
230                 if (sa) {
231                         sa->sin_family = result->h_addrtype;
232                         memcpy (&sa->sin_addr,
233                                 result->h_addr_list [0],
234                                 result->h_length);
235                 }
236
237                 if (nicename && result->h_name)
238                         *nicename = g_strdup (result->h_name);
239
240                 rv = TRUE;
241
242         done:
243                 g_free(buf);
244         }
245 #else
246 #ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
247         {
248                 struct hostent result;
249                 size_t len;
250                 char* buf;
251                 int herr;
252                 int res;
253
254                 len = 1024;
255                 buf = g_new (gchar, len);
256
257                 while ((res = gethostbyname_r (hostname,
258                                                &result,
259                                                buf,
260                                                len,
261                                                &herr)) == ERANGE) {
262                         len *= 2;
263                         buf = g_renew (gchar, buf, len);
264                 }
265
266                 if (res || hp == NULL || hp->h_addr_list [0] == NULL)
267                         goto done;
268
269                 if (sa) {
270                         sa->sin_family = result->h_addrtype;
271                         memcpy (&sa->sin_addr,
272                                 result->h_addr_list [0],
273                                 result->h_length);
274                 }
275
276                 if (nicename && result->h_name)
277                         *nicename = g_strdup (result->h_name);
278
279                 rv = TRUE;
280
281         done:
282                 g_free(buf);
283         }
284 #else
285 #ifdef HAVE_GETHOSTBYNAME_R_HPUX
286         {
287                 struct hostent result;
288                 struct hostent_data buf;
289                 int res;
290
291                 res = gethostbyname_r (hostname, &result, &buf);
292
293                 if (res == 0) {
294                         if (sa) {
295                                 sa->sin_family = result.h_addrtype;
296                                 memcpy (&sa->sin_addr,
297                                         result.h_addr_list [0],
298                                         result.h_length);
299                         }
300
301                         if (nicename && result.h_name)
302                                 *nicename = g_strdup(result.h_name);
303
304                         rv = TRUE;
305                 }
306         }
307 #else
308 #ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
309         {
310                 struct hostent* he;
311
312                 G_LOCK (gethostbyname);
313                 he = gethostbyname (hostname);
314                 G_UNLOCK (gethostbyname);
315
316                 if (he != NULL && he->h_addr_list [0] != NULL) {
317                         if (sa) {
318                                 sa->sin_family = he->h_addrtype;
319                                 memcpy (&sa->sin_addr,
320                                         he->h_addr_list [0],
321                                         he->h_length);
322                         }
323
324                         if (nicename && he->h_name)
325                                 *nicename = g_strdup (he->h_name);
326
327                         rv = TRUE;
328                 }
329         }
330 #else
331 #ifdef SOUP_WIN32
332         {
333                 struct hostent *result;
334
335                 WaitForSingleObject (soup_hostent_Mutex, INFINITE);
336                 result = gethostbyname (hostname);
337
338                 if (result != NULL) {
339                         if (sa) {
340                                 sa->sin_family = result->h_addrtype;
341                                 memcpy (&sa->sin_addr,
342                                         result->h_addr_list [0],
343                                         result->h_length);
344                         }
345
346                         if (nicename && result->h_name)
347                                 *nicename = g_strdup(result->h_name);
348
349                         ReleaseMutex(soup_hostent_Mutex);
350                         rv = TRUE;
351                 }
352         }
353 #else
354         {
355                 struct hostent* he;
356
357                 he = gethostbyname (hostname);
358                 if (he != NULL && he->h_addr_list [0] != NULL) {
359                         if (sa) {
360                                 sa->sin_family = he->h_addrtype;
361                                 memcpy (&sa->sin_addr,
362                                         he->h_addr_list [0],
363                                         he->h_length);
364                         }
365
366                         if (nicename && he->h_name)
367                                 *nicename = g_strdup (he->h_name);
368
369                         rv = TRUE;
370                 }
371         }
372 #endif
373 #endif
374 #endif
375 #endif
376 #endif
377
378         return rv;
379 }
380
381 /*
382    Thread safe gethostbyaddr (we assume that gethostbyaddr_r follows
383    the same pattern as gethostbyname_r, so we don't have special
384    checks for it in configure.in.
385
386    Returns the hostname, NULL if there was an error.
387 */
388
389 static gchar *
390 soup_gethostbyaddr (const char* addr, size_t length, int type)
391 {
392         gchar* rv = NULL;
393
394 #ifdef HAVE_GETHOSTBYNAME_R_GLIBC
395         {
396                 struct hostent result_buf, *result;
397                 size_t len;
398                 char* buf;
399                 int herr;
400                 int res;
401
402                 len = 1024;
403                 buf = g_new (gchar, len);
404
405                 while ((res = gethostbyaddr_r (addr,
406                                                length,
407                                                type,
408                                                &result_buf,
409                                                buf,
410                                                len,
411                                                &result,
412                                                &herr)) == ERANGE) {
413                         len *= 2;
414                         buf = g_renew (gchar, buf, len);
415                 }
416
417                 if (res || result == NULL || result->h_name == NULL)
418                         goto done;
419
420                 rv = g_strdup(result->h_name);
421
422         done:
423                 g_free(buf);
424         }
425 #else
426 #ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
427         {
428                 struct hostent result;
429                 size_t len;
430                 char* buf;
431                 int herr;
432                 int res;
433
434                 len = 1024;
435                 buf = g_new (gchar, len);
436
437                 while ((res = gethostbyaddr_r (addr,
438                                                length,
439                                                type,
440                                                &result,
441                                                buf,
442                                                len,
443                                                &herr)) == ERANGE) {
444                         len *= 2;
445                         buf = g_renew (gchar, buf, len);
446                 }
447
448                 if (res || hp == NULL || hp->h_name == NULL)
449                         goto done;
450
451                 rv = g_strdup(result->h_name);
452
453         done:
454                 g_free(buf);
455         }
456 #else
457 #ifdef HAVE_GETHOSTBYNAME_R_HPUX
458         {
459                 struct hostent result;
460                 struct hostent_data buf;
461                 int res;
462
463                 res = gethostbyaddr_r (addr, length, type, &result, &buf);
464
465                 if (res == 0) rv = g_strdup (result.h_name);
466         }
467 #else
468 #ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
469         {
470                 struct hostent* he;
471
472                 G_LOCK (gethostbyname);
473                 he = gethostbyaddr (addr, length, type);
474                 G_UNLOCK (gethostbyname);
475                 if (he != NULL && he->h_name != NULL)
476                         rv = g_strdup (he->h_name);
477         }
478 #else
479 #ifdef SOUP_WIN32
480         {
481                 struct hostent* he;
482
483                 WaitForSingleObject (soup_hostent_Mutex, INFINITE);
484                 he = gethostbyaddr (addr, length, type);
485                 if (he != NULL && he->h_name != NULL)
486                         rv = g_strdup (he->h_name);
487                 ReleaseMutex (soup_hostent_Mutex);
488         }
489 #else
490         {
491                 struct hostent* he;
492
493                 he = gethostbyaddr (addr, length, type);
494                 if (he != NULL && he->h_name != NULL)
495                         rv = g_strdup (he->h_name);
496         }
497 #endif
498 #endif
499 #endif
500 #endif
501 #endif
502
503         return rv;
504 }
505
506 #ifndef SOUP_WIN32  /*********** Unix code ***********/
507
508 static gboolean
509 soup_address_new_cb (GIOChannel* iochannel,
510                      GIOCondition condition,
511                      gpointer data)
512 {
513         SoupAddressState* state = (SoupAddressState*) data;
514         struct sockaddr_in* sa_in;
515         GSList *cb_list, *iter;
516         SoupAddressNewFn cb_func;
517         gpointer cb_data;       
518
519         if (!(condition & G_IO_IN)) {
520                 int ret;
521
522                 g_source_remove (state->watch);
523                 close (state->fd);
524                 waitpid (state->pid, &ret, 0);
525
526                 if (WIFSIGNALED (ret) || WEXITSTATUS (ret) != 1) goto ERROR;
527
528                 /* 
529                  * Exit status of one means we are inside a debugger.
530                  * Resolve the name synchronously.
531                  */
532                 sa_in = (struct sockaddr_in*) &state->ia.sa;
533
534                 if (!soup_gethostbyname (state->ia.name, sa_in, NULL))
535                         g_warning ("Problem resolving host name");
536         } else {
537                 int rv;
538                 char* buf;
539                 int length;
540
541                 buf = &state->buffer [state->len];
542                 length = sizeof (state->buffer) - state->len;
543
544                 rv = read (state->fd, buf, length);
545                 if (rv < 0) goto ERROR;
546
547                 state->len += rv;
548
549                 /* Return true if there's more to read */
550                 if ((state->len - 1) != state->buffer [0]) return TRUE;
551
552                 if (state->len < 2) goto ERROR;
553
554                 /* Success. Copy resolved address. */
555                 sa_in = (struct sockaddr_in*) &state->ia.sa;
556                 memcpy (&sa_in->sin_addr, &state->buffer [1], (state->len - 1));
557
558                 /* Cleanup state */
559                 g_source_remove (state->watch);
560                 close (state->fd);
561                 waitpid (state->pid, NULL, WNOHANG);
562         }
563
564         /* Get state data before realloc */
565         cb_list = iter = state->cb_list;
566         cb_func = state->func;
567         cb_data = state->data;
568
569         /* Invert resolved address reference count */
570         state->ia.ref_count = ~state->ia.ref_count + 1;
571
572         /* 
573          * Realloc state to size of SoupAddress, and reinsert to resolved
574          * address table. 
575          */
576         state = g_realloc (state, sizeof (SoupAddress));
577         g_hash_table_insert (active_address_hash, state->ia.name, state);
578
579         (*cb_func) (&state->ia, SOUP_ADDRESS_STATUS_OK, cb_data);
580
581         while (iter) {
582                 SoupAddressCbData *cb = iter->data;
583
584                 (*cb->func) (&state->ia, SOUP_ADDRESS_STATUS_OK, cb->data);
585
586                 g_free (cb);
587                 iter = iter->next;
588         }
589
590         g_slist_free (cb_list);
591
592         return FALSE;
593
594  ERROR:
595         /* Remove the watch now in case we don't return immediately */
596         g_source_remove (state->watch);
597
598         (*state->func) (NULL, SOUP_ADDRESS_STATUS_ERROR, state->data);
599
600         for (cb_list = state->cb_list; cb_list; cb_list = cb_list->next) {
601                 SoupAddressCbData *cb_data = cb_list->data;
602                 (*cb_data->func) (NULL,
603                                   SOUP_ADDRESS_STATUS_ERROR,
604                                   cb_data->data);
605         }
606
607         /* Force cancel */
608         state->ia.ref_count = -1;
609         soup_address_new_cancel (state);
610
611         return FALSE;
612 }
613
614 /**
615  * soup_address_new:
616  * @name: a nice name (eg, mofo.eecs.umich.edu) or a dotted decimal name
617  *   (eg, 141.213.8.59).  You can delete the after the function is called.
618  * @port: port number (0 if the port doesn't matter)
619  * @func: Callback function.
620  * @data: User data passed when callback function is called.
621  *
622  * Create a SoupAddress from a name and port asynchronously.  Once the
623  * structure is created, it will call the callback.  It may call the
624  * callback before the function returns.  It will call the callback
625  * if there is a failure.
626  *
627  * The Unix version forks and does the lookup, which can cause some
628  * problems.  In general, this will work ok for most programs most of
629  * the time.  It will be slow or even fail when using operating
630  * systems that copy the entire process when forking.
631  *
632  * If you need to lookup a lot of addresses, we recommend calling
633  * g_main_iteration(FALSE) between calls.  This will help prevent an
634  * explosion of processes.
635  *
636  * If you need a more robust library for Unix, look at <ulink
637  * url="http://www.gnu.org/software/adns/adns.html">GNU ADNS</ulink>.
638  * GNU ADNS is under the GNU GPL.
639  *
640  * The Windows version should work fine.  Windows has an asynchronous
641  * DNS lookup function.
642  *
643  * Returns: ID of the lookup which can be used with
644  * soup_address_new_cancel() to cancel it; NULL on immediate
645  * success or failure.
646  **/
647 SoupAddressNewId
648 soup_address_new (const gchar* name,
649                   const gint port,
650                   SoupAddressNewFn func,
651                   gpointer data)
652 {
653         pid_t pid = -1;
654         int pipes [2];
655         struct in_addr inaddr;
656         struct sockaddr_in sa;
657         struct sockaddr_in* sa_in;
658         SoupAddress* ia;
659         SoupAddressState* state;
660         GIOChannel *chan;
661
662         g_return_val_if_fail (name != NULL, NULL);
663         g_return_val_if_fail (func != NULL, NULL);
664
665         /* Try to read the name as if were dotted decimal */
666         if (inet_aton (name, &inaddr) != 0) {
667                 ia = g_new0 (SoupAddress, 1);
668                 ia->ref_count = 1;
669
670                 sa_in = (struct sockaddr_in*) &ia->sa;
671                 sa_in->sin_family = AF_INET;
672                 sa_in->sin_port = g_htons(port);
673                 memcpy (&sa_in->sin_addr,
674                         (char*) &inaddr,
675                         sizeof(struct in_addr));
676
677                 (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
678                 return NULL;
679         }
680
681         if (!active_address_hash)
682                 active_address_hash = g_hash_table_new (soup_str_case_hash,
683                                                         soup_str_case_equal);
684         else {
685                 ia = g_hash_table_lookup (active_address_hash, name);
686
687                 if (ia && ia->ref_count > 0) {
688                         /*
689                          * Existing valid request, use it.
690                          */
691                         if (soup_address_get_port (ia) == port) {
692                                 soup_address_ref (ia);
693                         } else {
694                                 /* 
695                                  * We can reuse the address, but we have to
696                                  * change port 
697                                  */
698                                 SoupAddress *new_ia = soup_address_copy (ia);
699                                 soup_address_set_port (new_ia, port);
700                                 ia = new_ia;
701                         }
702
703                         (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
704                         return NULL;
705                 } else if (ia && soup_address_get_port (ia) == port) {
706                         /*
707                          * Lookup currently in progress.
708                          * Add func to list of callbacks in state.
709                          * Note that if it's not the same port, we have to do
710                          * the lookup again, since there's no way to communicate
711                          * the port change.
712                          */
713                         SoupAddressCbData *cb_data;
714
715                         cb_data = g_new0 (SoupAddressCbData, 1);
716                         cb_data->func = func;
717                         cb_data->data = data;
718
719                         state = (SoupAddressState *) ia;
720                         state->cb_list = g_slist_prepend (state->cb_list,
721                                                           cb_data);
722
723                         state->ia.ref_count--;
724
725                         return state;
726                 }
727         }
728
729         /* Check to see if we are doing synchronous DNS lookups */
730         if (getenv ("SOUP_SYNC_DNS")) {
731                 if (!soup_gethostbyname (name, &sa, NULL)) {
732                         g_warning ("Problem resolving host name");
733                         (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
734                         return NULL;
735                 }
736
737                 sa_in = (struct sockaddr_in*) &sa;
738                 sa_in->sin_family = AF_INET;
739                 sa_in->sin_port = g_htons (port);
740
741                 ia = g_new0(SoupAddress, 1);
742                 ia->name = g_strdup (name);
743                 ia->ref_count = 1;
744                 ia->sa = *((struct sockaddr *) &sa);
745
746                 (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
747
748                 return NULL;
749         }
750
751         /* That didn't work - we need to fork */
752
753         /* Open a pipe */
754         if (pipe (pipes) == -1) {
755                 (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
756                 return NULL;
757         }
758
759  FORK_AGAIN:
760         errno = 0;
761         pid = fork ();
762
763         switch (pid) {
764         case -1:
765                 if (errno == EAGAIN) {
766                         /* Yield the processor */
767                         sleep(0);
768                         goto FORK_AGAIN;
769                 }
770
771                 /* Else there was a goofy error */
772                 g_warning ("Fork error: %s (%d)\n",
773                            g_strerror (errno),
774                            errno);
775                 close (pipes [0]);
776                 close (pipes [1]);
777
778                 (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
779
780                 return NULL;
781         case 0:
782                 close (pipes [0]);
783
784 #ifdef PTRACE_ATTACH
785                 signal (SIGCHLD, SIG_IGN);
786
787                 if (ptrace (PTRACE_ATTACH, getppid (), NULL, NULL) == -1) {
788                         /* 
789                          * Attach failed; it's probably already being
790                          * debugged. 
791                          */
792                         if (errno != EPERM)
793                                 g_warning ("ptrace: Unexpected error: %s",
794                                            strerror(errno));
795
796                         _exit (1);
797                 }
798                 
799                 /* 
800                  * Wait for the SIGSTOP from PTRACE_ATTACH to arrive at the
801                  * parent.  
802                  */
803                 waitpid (getppid (), NULL, 0);
804
805                 if (ptrace (PTRACE_DETACH, getppid (), NULL, NULL) == -1)
806                         g_warning ("ptrace: Detach failed: %s", 
807                                    strerror(errno));
808
809                 kill (getppid(), SIGCONT);
810 #endif
811
812                 /* 
813                  * Try to get the host by name (ie, DNS) 
814                  */
815                 if (soup_gethostbyname (name, &sa, NULL)) {
816                         guchar size = 4;        /* FIX for IPv6 */
817
818                         if ((write (pipes [1], &size, sizeof(guchar)) == -1) ||
819                             (write (pipes [1], &sa.sin_addr, size) == -1))
820                                 g_warning ("Problem writing to pipe\n");
821                 } else {
822                         /* Write a zero */
823                         guchar zero = 0;
824
825                         if (write (pipes [1], &zero, sizeof(zero)) == -1)
826                                 g_warning ("Problem writing to pipe\n");
827                 }
828
829                 /* Close the socket */
830                 close (pipes [1]);
831
832                 /* Exit (we don't want atexit called, so do _exit instead) */
833                 _exit (EXIT_SUCCESS);
834         default:
835                 close (pipes [1]);
836                 
837                 /* Create a structure for the call back */
838                 state = g_new0 (SoupAddressState, 1);
839                 state->ia.name = g_strdup (name);
840                 state->ia.ref_count = -1;
841                 state->func = func;
842                 state->data = data;
843                 state->pid = pid;
844                 state->fd = pipes [0];
845
846                 sa_in = (struct sockaddr_in*) &state->ia.sa;
847                 sa_in->sin_family = AF_INET;
848                 sa_in->sin_port = g_htons (port);
849
850                 g_hash_table_insert (active_address_hash,
851                                      state->ia.name,
852                                      state);
853
854                 chan = g_io_channel_unix_new (pipes [0]);
855
856                 /* Set up an watch to read from the pipe */
857                 state->watch =
858                         g_io_add_watch(
859                                 chan,
860                                 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
861                                 soup_address_new_cb,
862                                 state);
863
864                 g_io_channel_unref (chan);
865
866                 return state;
867         }
868 }
869
870 /**
871  * soup_address_new_cancel:
872  * @id: ID of the lookup
873  *
874  * Cancel an asynchronous SoupAddress creation that was started with
875  * soup_address_new().
876  */
877 void
878 soup_address_new_cancel (SoupAddressNewId id)
879 {
880         SoupAddressState* state = (SoupAddressState*) id;
881         GSList *cb_list;
882
883         g_return_if_fail (state != NULL);
884
885         state->ia.ref_count++;
886
887         if (state->ia.ref_count == 0) {
888                 g_hash_table_remove (active_address_hash, state->ia.name);
889                 g_free (state->ia.name);
890
891                 for (cb_list = state->cb_list; cb_list; cb_list = cb_list->next)
892                         g_free (cb_list->data);
893                 g_slist_free (state->cb_list);
894
895                 g_source_remove (state->watch);
896
897                 close (state->fd);
898                 kill (state->pid, SIGKILL);
899                 waitpid (state->pid, NULL, 0);
900
901                 g_free (state);
902         }
903 }
904
905 #else   /*********** Windows code ***********/
906
907 static gboolean
908 soup_address_new_cb (GIOChannel* iochannel,
909                      GIOCondition condition,
910                      gpointer data)
911 {
912         SoupAddressState* state = (SoupAddressState*) data;
913         struct hostent *result;
914         struct sockaddr_in *sa_in;
915
916         if (state->errorcode) {
917                 (*state->func) (&state->ia,
918                                 SOUP_ADDRESS_STATUS_ERROR,
919                                 state->data);
920                 g_free (state);
921                 return FALSE;
922         }
923
924         result = (struct hostent*) state->hostentBuffer;
925
926         sa_in = (struct sockaddr_in*) &state->ia.sa;
927         memcpy (&sa_in->sin_addr, result->h_addr_list [0], result->h_length);
928
929         state->ia.name = g_strdup (result->h_name);
930
931         state = g_realloc (state, sizeof (SoupAddress));
932
933         (*state->func) (&state->ia, SOUP_ADDRESS_STATUS_OK, state->data);
934         g_free (state);
935
936         return FALSE;
937 }
938
939 SoupAddressNewId
940 soup_address_new (const gchar* name,
941                   const gint port,
942                   SoupAddressNewFn func,
943                   gpointer data)
944 {
945         struct in_addr inaddr;
946         struct sockaddr_in* sa_in;
947         SoupAddressState* state;
948
949         g_return_val_if_fail(name != NULL, NULL);
950         g_return_val_if_fail(func != NULL, NULL);
951
952         /* Try to read the name as if were dotted decimal */
953
954         inaddr.s_addr = inet_addr(name);
955         if (inaddr.s_addr != INADDR_NONE) {
956                 SoupAddress* ia = NULL;
957                 struct sockaddr_in* sa_in;
958
959                 ia = g_new0(SoupAddress, 1);
960                 ia->ref_count = 1;
961
962                 sa_in = (struct sockaddr_in*) &ia->sa;
963                 sa_in->sin_family = AF_INET;
964                 sa_in->sin_port = g_htons (port);
965                 memcpy (&sa_in->sin_addr,
966                         (char*) &inaddr,
967                         sizeof (struct in_addr));
968
969                 (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
970                 return NULL;
971         }
972
973         /* Create a structure for the call back */
974         state = g_new0 (SoupAddressState, 1);
975         state->ia.name = g_strdup (name);
976         state->ia.ref_count = 1;
977         state->func = func;
978         state->data = data;
979
980         sa_in = (struct sockaddr_in*) &state->ia.sa;
981         sa_in->sin_family = AF_INET;
982         sa_in->sin_port = g_htons (port);
983
984         state->WSAhandle = (int)
985                 WSAAsyncGetHostByName (soup_hWnd,
986                                        IA_NEW_MSG,
987                                        name,
988                                        state->hostentBuffer,
989                                        sizeof (state->hostentBuffer));
990
991         if (!state->WSAhandle) {
992                 g_free (state);
993                 (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
994                 return NULL;
995         }
996
997         /*get a lock and insert the state into the hash */
998         WaitForSingleObject (soup_Mutex, INFINITE);
999         g_hash_table_insert (soup_hash,
1000                              (gpointer) state->WSAhandle,
1001                              (gpointer) state);
1002         ReleaseMutex (soup_Mutex);
1003
1004         return state;
1005 }
1006
1007 void
1008 soup_address_new_cancel (SoupAddressNewId id)
1009 {
1010         SoupAddressState* state = (SoupAddressState*) id;
1011
1012         g_return_if_fail(state != NULL);
1013
1014         WSACancelAsyncRequest ((HANDLE)state->WSAhandle);
1015
1016         /*get a lock and remove the hash entry */
1017         WaitForSingleObject (soup_Mutex, INFINITE);
1018         g_hash_table_remove (soup_hash, (gpointer) state->WSAhandle);
1019         ReleaseMutex (soup_Mutex);
1020         g_free (state);
1021 }
1022
1023 #endif          /*********** End Windows code ***********/
1024
1025 static void
1026 soup_address_new_sync_cb (SoupAddress *addr,
1027                           SoupAddressStatus  status,
1028                           gpointer           user_data)
1029 {
1030         SoupAddress **ret = user_data;
1031         *ret = addr;
1032 }
1033
1034 SoupAddress *
1035 soup_address_new_sync (const gchar *name, const gint port)
1036 {
1037         SoupAddress *ret = (SoupAddress *) 0xdeadbeef;
1038
1039         soup_address_new (name, port, soup_address_new_sync_cb, &ret);
1040
1041         while (1) {
1042                 g_main_iteration (TRUE);
1043                 if (ret != (SoupAddress *) 0xdeadbeef) return ret;
1044         }
1045
1046         return ret;
1047 }
1048
1049 /**
1050  * soup_address_ref
1051  * @ia: SoupAddress to reference
1052  *
1053  * Increment the reference counter of the SoupAddress.
1054  **/
1055 void
1056 soup_address_ref (SoupAddress* ia)
1057 {
1058         g_return_if_fail (ia != NULL);
1059
1060         ++ia->ref_count;
1061 }
1062
1063
1064 /**
1065  * soup_address_unref
1066  * @ia: SoupAddress to unreference
1067  *
1068  * Remove a reference from the SoupAddress.  When reference count
1069  * reaches 0, the address is deleted.
1070  **/
1071 void
1072 soup_address_unref (SoupAddress* ia)
1073 {
1074         g_return_if_fail (ia != NULL);
1075
1076         --ia->ref_count;
1077
1078         if (ia->ref_count == 0) {
1079                 if (ia->name != NULL) {
1080 #ifndef SOUP_WIN32
1081                         g_hash_table_remove (active_address_hash, ia->name);
1082 #endif
1083                         g_free (ia->name);
1084                 }
1085                 g_free (ia);
1086         }
1087 }
1088
1089 /**
1090  * soup_address_copy
1091  * @ia: SoupAddress to copy
1092  *
1093  * Creates a copy of the given SoupAddress
1094  **/
1095 SoupAddress *
1096 soup_address_copy (SoupAddress* ia)
1097 {
1098         SoupAddress* new_ia;
1099         g_return_val_if_fail (ia != NULL, NULL);
1100
1101         new_ia = g_new0(SoupAddress, 1);
1102         new_ia->ref_count = 1;
1103
1104         new_ia->name = g_strdup (ia->name);
1105         memcpy (&new_ia->sa, &ia->sa, sizeof(struct sockaddr));
1106
1107         return new_ia;
1108 }
1109
1110 #ifndef SOUP_WIN32  /*********** Unix code ***********/
1111
1112 static gboolean
1113 soup_address_get_name_cb (GIOChannel* iochannel,
1114                           GIOCondition condition,
1115                           gpointer data)
1116 {
1117         SoupAddressReverseState* state;
1118         gchar* name = NULL;
1119
1120         state = (SoupAddressReverseState*) data;
1121
1122         g_return_val_if_fail (state != NULL, FALSE);
1123
1124         /* Read from the pipe */
1125         if (condition & G_IO_IN) {
1126                 int rv;
1127                 char* buf;
1128                 int length;
1129
1130                 buf = &state->buffer [state->len];
1131                 length = sizeof(state->buffer) - state->len;
1132
1133                 if ((rv = read (state->fd, buf, length)) >= 0) {
1134                         state->len += rv;
1135
1136                         /* Return true if there's more to read */
1137                         if ((state->len - 1) != state->buffer [0])
1138                                 return TRUE;
1139
1140                         /* Copy the name */
1141                         name = g_new (gchar, state->buffer [0] + 1);
1142                         strncpy (name, &state->buffer [1], state->buffer [0]);
1143                         name [state->buffer [0]] = '\0';
1144
1145                         state->ia->name = name;
1146
1147                         /* Remove the watch now in case we don't return
1148                            immediately */
1149                         g_source_remove (state->watch);
1150
1151                         /* Call back */
1152                         (*state->func) (state->ia,
1153                                         SOUP_ADDRESS_STATUS_OK,
1154                                         name,
1155                                         state->data);
1156
1157                         close (state->fd);
1158                         waitpid (state->pid, NULL, 0);
1159                         g_free (state);
1160                         return FALSE;
1161                 }
1162         }
1163
1164         /* Remove the watch now in case we don't return immediately */
1165         g_source_remove (state->watch);
1166
1167         /* Call back */
1168         (*state->func) (state->ia,
1169                         SOUP_ADDRESS_STATUS_ERROR,
1170                         NULL,
1171                         state->data);
1172         soup_address_get_name_cancel (state);
1173         return FALSE;
1174 }
1175
1176 /**
1177  * soup_address_get_name:
1178  * @ia: Address to get the name of.
1179  * @func: Callback function.
1180  * @data: User data passed when callback function is called.
1181  *
1182  * Get the nice name of the address (eg, "mofo.eecs.umich.edu").
1183  * This function will use the callback once it knows the nice name.
1184  * It may even call the callback before it returns.  The callback
1185  * will be called if there is an error.
1186  *
1187  * The Unix version forks and does the reverse lookup.  This has
1188  * problems.  See the notes for soup_address_new().  The
1189  * Windows version should work fine.
1190  *
1191  * Returns: ID of the lookup which can be used with
1192  * soup_addressr_get_name_cancel() to cancel it; NULL on
1193  * immediate success or failure.
1194  **/
1195 SoupAddressGetNameId
1196 soup_address_get_name (SoupAddress*         ia,
1197                        SoupAddressGetNameFn func,
1198                        gpointer             data)
1199 {
1200         SoupAddressReverseState* state;
1201         gchar* name;
1202         guchar len;
1203         pid_t pid = -1;
1204         int pipes [2];
1205
1206         g_return_val_if_fail (ia != NULL, NULL);
1207         g_return_val_if_fail (func != NULL, NULL);
1208
1209         if (ia->name) {
1210                 (func) (ia, SOUP_ADDRESS_STATUS_OK, ia->name, data);
1211                 return NULL;
1212         }
1213
1214         /* Open a pipe */
1215         if (pipe (pipes) != 0) {
1216                 (func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
1217                 return NULL;
1218         }
1219
1220  FORK_AGAIN:
1221         errno = 0;
1222         pid = fork ();
1223
1224         switch (pid) {
1225         case -1:
1226                 if (errno == EAGAIN) {
1227                         /* Yield the processor */
1228                         sleep(0);
1229                         goto FORK_AGAIN;
1230                 }
1231
1232                 close(pipes[0]);
1233                 close(pipes[1]);
1234
1235                 /* Else there was a goofy error */
1236                 g_warning ("Fork error: %s (%d)\n",
1237                            g_strerror(errno),
1238                            errno);
1239
1240                 (*func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
1241
1242                 return NULL;
1243         case 0:
1244                 close(pipes[0]);
1245
1246                 /* Write the name to the pipe.  If we didn't get a name,
1247                    we just write the canonical name. */
1248                 name = soup_gethostbyaddr (
1249                             (char*) &((struct sockaddr_in*)&ia->sa)->sin_addr,
1250                             sizeof (struct in_addr),
1251                             AF_INET);
1252
1253                 if (name) {
1254                         guint lenint = strlen(name);
1255
1256                         if (lenint > 255) {
1257                                 g_warning ("Truncating domain name: %s\n",
1258                                            name);
1259                                 name [256] = '\0';
1260                                 lenint = 255;
1261                         }
1262
1263                         len = lenint;
1264
1265                         if ((write (pipes [1], &len, sizeof(len)) == -1) ||
1266                             (write (pipes [1], name, len) == -1) )
1267                                 g_warning ("Problem writing to pipe\n");
1268
1269                         g_free(name);
1270                 } else {
1271                         /* defined in netinet/in.h */
1272                         gchar buffer [INET_ADDRSTRLEN];
1273                         guchar* p;
1274                         p = (guchar*) &(SOUP_SOCKADDR_IN (ia->sa).sin_addr);
1275
1276                         g_snprintf(buffer,
1277                                    sizeof (buffer),
1278                                    "%d.%d.%d.%d",
1279                                    p [0],
1280                                    p [1],
1281                                    p [2],
1282                                    p [3]);
1283                         len = strlen (buffer);
1284
1285                         if ((write (pipes [1], &len, sizeof(len)) == -1) ||
1286                             (write (pipes [1], buffer, len) == -1))
1287                                 g_warning ("Problem writing to pipe\n");
1288                 }
1289
1290                 /* Close the socket */
1291                 close(pipes [1]);
1292
1293                 /* Exit (we don't want atexit called, so do _exit instead) */
1294                 _exit(EXIT_SUCCESS);
1295         default:
1296                 close(pipes[1]);
1297
1298                 soup_address_ref (ia);
1299
1300                 state = g_new0 (SoupAddressReverseState, 1);
1301                 state->ia = ia;
1302                 state->func = func;
1303                 state->data = data;
1304                 state->pid = pid;
1305                 state->fd = pipes [0];
1306
1307                 /* Add a watch */
1308                 state->watch =
1309                         g_io_add_watch(g_io_channel_unix_new (pipes [0]),
1310                                        G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
1311                                        soup_address_get_name_cb,
1312                                        state);
1313                 return state;
1314         }
1315 }
1316
1317 /**
1318  * soup_address_get_name_cancel:
1319  * @id: ID of the lookup
1320  *
1321  * Cancel an asynchronous nice name lookup that was started with
1322  * soup_address_get_name().
1323  */
1324 void
1325 soup_address_get_name_cancel (SoupAddressGetNameId id)
1326 {
1327         SoupAddressReverseState* state;
1328         state = (SoupAddressReverseState*) id;
1329
1330         g_return_if_fail(state != NULL);
1331
1332         soup_address_unref (state->ia);
1333         g_source_remove (state->watch);
1334
1335         close (state->fd);
1336         kill (state->pid, SIGKILL);
1337         waitpid (state->pid, NULL, 0);
1338
1339         g_free(state);
1340 }
1341
1342 #else   /*********** Windows code ***********/
1343
1344 static gboolean
1345 soup_address_get_name_cb (GIOChannel* iochannel,
1346                           GIOCondition condition,
1347                           gpointer data)
1348 {
1349         SoupAddressReverseState* state;
1350         gchar* name;
1351         struct hostent* result;
1352         state = (SoupAddressReverseState*) data;
1353
1354         result = (struct hostent*) state->hostentBuffer;
1355
1356         if (state->errorcode) {
1357                 (*state->func) (state->ia,
1358                                 SOUP_ADDRESS_STATUS_ERROR,
1359                                 NULL,
1360                                 state->data);
1361                 return FALSE;
1362         }
1363
1364         state->ia->name = g_strdup (result->h_name);
1365         name = NULL;
1366         name = g_strdup (state->ia->name);
1367
1368         (*state->func) (state->ia,
1369                         SOUP_ADDRESS_STATUS_OK,
1370                         name,
1371                         state->data);
1372
1373         g_free(state);
1374         return FALSE;
1375 }
1376
1377 SoupAddressGetNameId
1378 soup_address_get_name (SoupAddress* ia,
1379                        SoupAddressGetNameFn func,
1380                        gpointer data)
1381 {
1382         SoupAddressReverseState* state;
1383         struct sockaddr_in* sa_in;
1384
1385         g_return_val_if_fail(ia != NULL, NULL);
1386         g_return_val_if_fail(func != NULL, NULL);
1387
1388         /* If we already know the name, just copy that */
1389         if (ia->name != NULL) {
1390                 (func) (ia,
1391                         SOUP_ADDRESS_STATUS_OK,
1392                         g_strdup (ia->name),
1393                         data);
1394         }
1395
1396         /* Create a structure for the call back */
1397         state = g_new0 (SoupAddressReverseState, 1);
1398         state->ia = ia;
1399         state->func = func;
1400         state->data = data;
1401
1402         sa_in = (struct sockaddr_in*) &ia->sa;
1403
1404         state->WSAhandle = (int)
1405                 WSAAsyncGetHostByAddr (soup_hWnd, GET_NAME_MSG,
1406                                        (const char*) &sa_in->sin_addr,
1407                                        (int) (sizeof (&sa_in->sin_addr)),
1408                                        (int) &sa_in->sin_family,
1409                                        state->hostentBuffer,
1410                                        sizeof (state->hostentBuffer));
1411
1412         if (!state->WSAhandle) {
1413                 g_free (state);
1414                 (func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
1415                 return NULL;
1416         }
1417
1418         /*get a lock and insert the state into the hash */
1419         WaitForSingleObject (soup_Mutex, INFINITE);
1420         g_hash_table_insert (soup_hash,
1421                              (gpointer) state->WSAhandle,
1422                              (gpointer) state);
1423         ReleaseMutex (soup_Mutex);
1424
1425         return state;
1426 }
1427
1428 void
1429 soup_address_get_name_cancel (SoupAddressGetNameId id)
1430 {
1431         SoupAddressReverseState* state;
1432         state = (SoupAddressReverseState*) id;
1433
1434         g_return_if_fail(state != NULL);
1435
1436         soup_address_unref (state->ia);
1437         WSACancelAsyncRequest ((HANDLE) state->WSAhandle);
1438
1439         /*get a lock and remove the hash entry */
1440         WaitForSingleObject (soup_Mutex, INFINITE);
1441         g_hash_table_remove (soup_hash, (gpointer) state->WSAhandle);
1442         ReleaseMutex (soup_Mutex);
1443
1444         g_free (state);
1445 }
1446
1447 #endif          /*********** End Windows code ***********/
1448
1449 static void
1450 soup_address_get_name_sync_cb (SoupAddress       *addr,
1451                                SoupAddressStatus  status,
1452                                const char        *name,
1453                                gpointer           user_data)
1454 {
1455         const char **ret = user_data;
1456         *ret = name;
1457 }
1458
1459 const gchar *
1460 soup_address_get_name_sync (SoupAddress *addr)
1461 {
1462         const char *ret = (const char *) 0xdeadbeef;
1463
1464         soup_address_get_name (addr, 
1465
1466                                soup_address_get_name_sync_cb, 
1467
1468                                (gpointer) &ret);
1469
1470         while (1) {
1471                 g_main_iteration (TRUE);
1472                 if (ret != (const char *) 0xdeadbeef) return ret;
1473         }
1474
1475         return ret;
1476 }
1477
1478 /**
1479  * soup_address_get_canonical_name:
1480  * @ia: Address to get the canonical name of.
1481  *
1482  * Get the "canonical" name of an address (eg, for IP4 the dotted
1483  * decimal name 141.213.8.59).
1484  *
1485  * Returns: NULL if there was an error.  The caller is responsible
1486  * for deleting the returned string.
1487  **/
1488 gchar*
1489 soup_address_get_canonical_name (SoupAddress* ia)
1490 {
1491         gchar buffer [INET_ADDRSTRLEN]; /* defined in netinet/in.h */
1492         guchar* p = (guchar*) &(SOUP_SOCKADDR_IN(ia->sa).sin_addr);
1493
1494         g_return_val_if_fail (ia != NULL, NULL);
1495
1496         g_snprintf(buffer,
1497                    sizeof (buffer),
1498                    "%d.%d.%d.%d",
1499                    p [0],
1500                    p [1],
1501                    p [2],
1502                    p [3]);
1503
1504         return g_strdup (buffer);
1505 }
1506
1507 /**
1508  * soup_address_get_port:
1509  * @ia: Address to get the port number of.
1510  *
1511  * Get the port number.
1512  * Returns: the port number.
1513  */
1514 gint
1515 soup_address_get_port (const SoupAddress* ia)
1516 {
1517         g_return_val_if_fail(ia != NULL, -1);
1518
1519         return (gint) g_ntohs (((struct sockaddr_in*) &ia->sa)->sin_port);
1520 }
1521
1522 /**
1523  * soup_address_set_port:
1524  * @ia: Address to set the port number of.
1525  * @port: New port number
1526  *
1527  * Set the port number.
1528  **/
1529 void
1530 soup_address_set_port (const SoupAddress* ia, guint port)
1531 {
1532         g_return_if_fail (ia != NULL);
1533
1534         ((struct sockaddr_in*) &ia->sa)->sin_port = g_htons (port);
1535 }
1536
1537 /**
1538  * soup_address_hash:
1539  * @p: Pointer to an #SoupAddress.
1540  *
1541  * Hash the address.  This is useful for glib containers.
1542  *
1543  * Returns: hash value.
1544  **/
1545 guint
1546 soup_address_hash (const gpointer p)
1547 {
1548         const SoupAddress* ia;
1549         guint32 port;
1550         guint32 addr;
1551
1552         g_assert(p != NULL);
1553
1554         ia = (const SoupAddress*) p;
1555         /* We do pay attention to network byte order just in case the hash
1556            result is saved or sent to a different host.  */
1557         port = (guint32) g_ntohs (((struct sockaddr_in*) &ia->sa)->sin_port);
1558         addr = g_ntohl (((struct sockaddr_in*) &ia->sa)->sin_addr.s_addr);
1559
1560         return (port ^ addr);
1561 }
1562
1563 /**
1564  * soup_address_equal:
1565  * @p1: Pointer to first #SoupAddress.
1566  * @p2: Pointer to second #SoupAddress.
1567  *
1568  * Compare two #SoupAddress's.
1569  *
1570  * Returns: 1 if they are the same; 0 otherwise.
1571  **/
1572 gint
1573 soup_address_equal (const gpointer p1, const gpointer p2)
1574 {
1575         const SoupAddress* ia1 = (const SoupAddress*) p1;
1576         const SoupAddress* ia2 = (const SoupAddress*) p2;
1577
1578         g_assert(p1 != NULL && p2 != NULL);
1579
1580         /* Note network byte order doesn't matter */
1581         return ((SOUP_SOCKADDR_IN(ia1->sa).sin_addr.s_addr ==
1582                  SOUP_SOCKADDR_IN(ia2->sa).sin_addr.s_addr) &&
1583                 (SOUP_SOCKADDR_IN(ia1->sa).sin_port ==
1584                  SOUP_SOCKADDR_IN(ia2->sa).sin_port));
1585 }
1586
1587 /**
1588  * soup_address_noport_equal:
1589  * @p1: Pointer to first SoupAddress.
1590  * @p2: Pointer to second SoupAddress.
1591  *
1592  * Compare two #SoupAddress's, but does not compare the port numbers.
1593  *
1594  * Returns: 1 if they are the same; 0 otherwise.
1595  **/
1596 gint
1597 soup_address_noport_equal (const gpointer p1, const gpointer p2)
1598 {
1599         const SoupAddress* ia1 = (const SoupAddress*) p1;
1600         const SoupAddress* ia2 = (const SoupAddress*) p2;
1601
1602         g_assert (p1 != NULL && p2 != NULL);
1603
1604         /* Note network byte order doesn't matter */
1605         return (SOUP_SOCKADDR_IN(ia1->sa).sin_addr.s_addr ==
1606                 SOUP_SOCKADDR_IN(ia2->sa).sin_addr.s_addr);
1607 }
1608
1609 #ifndef SOUP_WIN32  /*********** Unix code ***********/
1610
1611 /**
1612  * soup_address_gethostname:
1613  *
1614  * Get the primary host's name.
1615  *
1616  * Returns: the name of the host; NULL if there was an error.  The
1617  * caller is responsible for deleting the returned string.
1618  **/
1619 gchar*
1620 soup_address_gethostname (void)
1621 {
1622         gchar* name = NULL;
1623         struct utsname myname;
1624
1625         if (uname (&myname) < 0) return NULL;
1626
1627         if (!soup_gethostbyname (myname.nodename, NULL, &name)) return NULL;
1628
1629         return name;
1630 }
1631
1632 #else   /*********** Windows code ***********/
1633
1634 gchar*
1635 soup_address_gethostname (void)
1636 {
1637         gchar* name = NULL;
1638         int error = 0;
1639
1640         name = g_new0 (char, 256);
1641         error = gethostname (name, 256);
1642         if (error) {
1643                 g_free(name);
1644                 return NULL;
1645         }
1646
1647         return name;
1648 }
1649
1650 #endif          /*********** End Windows code ***********/
1651
1652 /**
1653  * soup_address_gethostaddr:
1654  *
1655  * Get the primary host's #SoupAddress.
1656  *
1657  * Returns: the #SoupAddress of the host; NULL if there was an error.
1658  * The caller is responsible for deleting the returned #SoupAddress.
1659  **/
1660 SoupAddress *
1661 soup_address_gethostaddr (void)
1662 {
1663         gchar* name;
1664         struct sockaddr_in* sa_in, sa;
1665         SoupAddress* ia = NULL;
1666
1667         name = soup_address_gethostname ();
1668
1669         if (name && soup_gethostbyname(name, &sa, NULL)) {
1670                 ia = g_new0 (SoupAddress, 1);
1671                 ia->name = g_strdup (name);
1672                 ia->ref_count = 1;
1673
1674                 sa_in = (struct sockaddr_in*) &ia->sa;
1675                 sa_in->sin_family = AF_INET;
1676                 sa_in->sin_port = 0;
1677                 memcpy (&sa_in->sin_addr, &sa.sin_addr, 4);
1678         }
1679
1680         return ia;
1681 }
1682
1683
1684 static void
1685 soup_socket_connect_tcp_cb (SoupSocket* socket,
1686                             SoupSocketConnectStatus status,
1687                             gpointer data)
1688 {
1689         SoupSocketConnectState* state = (SoupSocketConnectState*) data;
1690
1691         if (status == SOUP_SOCKET_NEW_STATUS_OK)
1692                 (*state->func) (socket,
1693                                 SOUP_SOCKET_CONNECT_ERROR_NONE,
1694                                 state->data);
1695         else
1696                 (*state->func) (NULL,
1697                                 SOUP_SOCKET_CONNECT_ERROR_NETWORK,
1698                                 state->data);
1699
1700         g_free(state);
1701 }
1702
1703 static void
1704 soup_socket_connect_inetaddr_cb (SoupAddress* inetaddr,
1705                                  SoupAddressStatus status,
1706                                  gpointer data)
1707 {
1708         SoupSocketConnectState* state = (SoupSocketConnectState*) data;
1709
1710         if (status == SOUP_ADDRESS_STATUS_OK) {
1711                 state->inetaddr_id = NULL;
1712                 state->tcp_id = soup_socket_new (inetaddr,
1713                                                  soup_socket_connect_tcp_cb,
1714                                                  state);
1715                 soup_address_unref (inetaddr);
1716         } else {
1717                 (*state->func) (NULL,
1718                                 SOUP_SOCKET_CONNECT_ERROR_ADDR_RESOLVE,
1719                                 state->data);
1720                 g_free(state);
1721         }
1722 }
1723
1724 /**
1725  * soup_socket_connect:
1726  * @hostname: Name of host to connect to
1727  * @port: Port to connect to
1728  * @func: Callback function
1729  * @data: User data passed when callback function is called.
1730  *
1731  * A quick and easy non-blocking #SoupSocket constructor.  This
1732  * connects to the specified address and port and then calls the
1733  * callback with the data.  Use this function when you're a client
1734  * connecting to a server and you don't want to block or mess with
1735  * #SoupAddress's.  It may call the callback before the function
1736  * returns.  It will call the callback if there is a failure.
1737  *
1738  * Returns: ID of the connection which can be used with
1739  * soup_socket_connect_cancel() to cancel it; NULL on
1740  * failure.
1741  **/
1742 SoupSocketConnectId
1743 soup_socket_connect (const gchar*        hostname,
1744                      const gint          port,
1745                      SoupSocketConnectFn func,
1746                      gpointer            data)
1747 {
1748         SoupSocketConnectState* state;
1749         gpointer id;
1750
1751         g_return_val_if_fail (hostname != NULL, NULL);
1752         g_return_val_if_fail (func != NULL, NULL);
1753
1754         state = g_new0 (SoupSocketConnectState, 1);
1755         state->func = func;
1756         state->data = data;
1757
1758         id = soup_address_new (hostname,
1759                                port,
1760                                soup_socket_connect_inetaddr_cb,
1761                                state);
1762
1763         /* Note that soup_address_new can fail immediately and call
1764            our callback which will delete the state.  The users callback
1765            would be called in the process. */
1766
1767         if (id == NULL) return NULL;
1768
1769         state->inetaddr_id = id;
1770
1771         return state;
1772 }
1773
1774 /**
1775  * soup_socket_connect_cancel:
1776  * @id: Id of the connection.
1777  *
1778  * Cancel an asynchronous connection that was started with
1779  * soup_socket_connect().
1780  */
1781 void
1782 soup_socket_connect_cancel (SoupSocketConnectId id)
1783 {
1784         SoupSocketConnectState* state = (SoupSocketConnectState*) id;
1785
1786         g_return_if_fail (state != NULL);
1787
1788         if (state->inetaddr_id)
1789                 soup_address_new_cancel (state->inetaddr_id);
1790         else if (state->tcp_id)
1791                 soup_socket_new_cancel (state->tcp_id);
1792
1793         g_free (state);
1794 }
1795
1796 static void
1797 soup_socket_connect_sync_cb (SoupSocket              *socket,
1798                              SoupSocketConnectStatus  status,
1799                              gpointer                 data)
1800 {
1801         SoupSocket **ret = data;
1802         *ret = socket;
1803 }
1804
1805 SoupSocket *
1806 soup_socket_connect_sync (const gchar *name,
1807                           const gint   port)
1808 {
1809         SoupSocket *ret = (SoupSocket *) 0xdeadbeef;
1810
1811         soup_socket_connect (name, port, soup_socket_connect_sync_cb, &ret);
1812
1813         while (1) {
1814                 g_main_iteration (TRUE);
1815                 if (ret != (SoupSocket *) 0xdeadbeef) return ret;
1816         }
1817
1818         return ret;
1819 }
1820
1821
1822 #ifndef SOUP_WIN32  /*********** Unix code ***********/
1823
1824 static gboolean
1825 soup_socket_new_cb (GIOChannel* iochannel,
1826                     GIOCondition condition,
1827                     gpointer data)
1828 {
1829         SoupSocketState* state = (SoupSocketState*) data;
1830         SoupSocket* s;
1831         gint error = 0;
1832         gint len = sizeof (gint);
1833
1834         /* Remove the watch now in case we don't return immediately */
1835         g_source_remove (state->connect_watch);
1836
1837         if (condition & ~(G_IO_IN | G_IO_OUT)) goto ERROR;
1838
1839         errno = 0;
1840         if (getsockopt (state->sockfd,
1841                         SOL_SOCKET,
1842                         SO_ERROR,
1843                         &error,
1844                         &len) != 0) goto ERROR;
1845
1846         if (error) goto ERROR;
1847
1848         if (fcntl (state->sockfd, F_SETFL, state->flags) != 0)
1849                 goto ERROR;
1850
1851         s = g_new0 (SoupSocket, 1);
1852         s->ref_count = 1;
1853         s->sockfd = state->sockfd;
1854         s->addr = state->addr;
1855
1856         (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
1857
1858         g_free (state);
1859
1860         return FALSE;
1861
1862  ERROR:
1863         soup_address_unref (state->addr);
1864         (*state->func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, state->data);
1865         g_free (state);
1866
1867         return FALSE;
1868 }
1869
1870 /**
1871  * soup_socket_new:
1872  * @addr: Address to connect to.
1873  * @func: Callback function.
1874  * @data: User data passed when callback function is called.
1875  *
1876  * Connect to a specifed address asynchronously.  When the connection
1877  * is complete or there is an error, it will call the callback.  It
1878  * may call the callback before the function returns.  It will call
1879  * the callback if there is a failure.
1880  *
1881  * Returns: ID of the connection which can be used with
1882  * soup_socket_connect_cancel() to cancel it; NULL on
1883  * failure.
1884  **/
1885 SoupSocketNewId
1886 soup_socket_new (SoupAddress      *addr,
1887                  SoupSocketNewFn   func,
1888                  gpointer          data)
1889 {
1890         gint sockfd;
1891         gint flags;
1892         SoupSocketState* state;
1893         GIOChannel *chan;
1894
1895         g_return_val_if_fail(addr != NULL, NULL);
1896         g_return_val_if_fail(func != NULL, NULL);
1897
1898         /* Create socket */
1899         sockfd = socket (AF_INET, SOCK_STREAM, 0);
1900         if (sockfd < 0) {
1901                 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
1902                 return NULL;
1903         }
1904
1905         /* Get the flags (should all be 0?) */
1906         flags = fcntl (sockfd, F_GETFL, 0);
1907         if (flags == -1) {
1908                 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
1909                 return NULL;
1910         }
1911
1912         if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
1913                 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
1914                 return NULL;
1915         }
1916
1917         errno = 0;
1918
1919         /* Connect (but non-blocking!) */
1920         if (connect (sockfd, &addr->sa, sizeof (addr->sa)) < 0 &&
1921             errno != EINPROGRESS) {
1922                 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
1923                 return NULL;
1924         }
1925
1926         /* Unref in soup_socket_new_cb if failure */
1927         soup_address_ref (addr);
1928
1929         /* Connect succeeded, return immediately */
1930         if (!errno) {
1931                 SoupSocket *s = g_new0 (SoupSocket, 1);
1932                 s->ref_count = 1;
1933                 s->sockfd = sockfd;
1934                 s->addr = addr;
1935
1936                 (*func) (s, SOUP_SOCKET_NEW_STATUS_OK, data);
1937                 return NULL;
1938         }
1939
1940         chan = SOUP_SOCKET_IOCHANNEL_NEW (sockfd);
1941
1942         /* Wait for the connection */
1943         state = g_new0 (SoupSocketState, 1);
1944         state->sockfd = sockfd;
1945         state->addr = addr;
1946         state->func = func;
1947         state->data = data;
1948         state->flags = flags;
1949         state->connect_watch = g_io_add_watch (chan,
1950                                                SOUP_ANY_IO_CONDITION,
1951                                                soup_socket_new_cb,
1952                                                state);
1953
1954         g_io_channel_unref (chan);
1955
1956         return state;
1957 }
1958
1959 #else   /*********** Windows code ***********/
1960
1961 static gboolean
1962 soup_socket_new_cb (GIOChannel* iochannel,
1963                     GIOCondition condition,
1964                     gpointer data)
1965 {
1966         SoupSocketState* state = (SoupSocketState*) data;
1967         SoupSocket *s;
1968 \r
1969         /* Remove the watch now in case we don't return immediately */\r
1970         g_source_remove (state->connect_watch);\r
1971 \r
1972         if (condition & ~(G_IO_IN | G_IO_OUT)) goto _ERROR;\r
1973
1974         s = g_new0 (SoupSocket, 1);
1975         s->ref_count = 1;
1976         s->sockfd = state->sockfd;
1977         s->addr = state->addr;
1978
1979         (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
1980         g_free (state);
1981         return FALSE;\r
1982 \r
1983  _ERROR:\r
1984         soup_address_unref (state->addr);\r
1985         (*state->func) ((SoupSocket *) NULL,\r
1986                         SOUP_SOCKET_NEW_STATUS_ERROR,\r
1987                         state->data);\r
1988         g_free (state);\r
1989 \r
1990         return FALSE;
1991 }
1992
1993 SoupSocketNewId
1994 soup_socket_new (SoupAddress     *addr,
1995                  SoupSocketNewFn  func,
1996                  gpointer         data)
1997 {
1998         gint sockfd;
1999         gint status;
2000         SoupSocketState* state = (SoupSocketState*) data;\r
2001         u_long arg = 1;\r
2002         GIOChannel *chan;
2003
2004         g_return_val_if_fail (addr != NULL, NULL);
2005         g_return_val_if_fail (func != NULL, NULL);
2006
2007         /* Create socket */
2008         sockfd = socket (AF_INET, SOCK_STREAM, 0);
2009         if (sockfd == INVALID_SOCKET) {
2010                 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
2011                 return NULL;
2012         }
2013 \r
2014         /* Set non-blocking mode */
2015         ioctlsocket(sockfd, FIONBIO, &arg);\r
2016
2017         status = connect (sockfd, &addr->sa, sizeof(addr->sa));
2018         /* Returning an error is ok, unless.. */
2019         if (status == SOCKET_ERROR) {
2020                 status = WSAGetLastError();
2021                 if (status != WSAEWOULDBLOCK) {
2022                         (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
2023                         return NULL;
2024                 }
2025         }
2026
2027         soup_address_ref (addr);
2028
2029         if (status != SOCKET_ERROR) {
2030                 SoupSocket *s = g_new0 (SoupSocket, 1);
2031                 s->ref_count = 1;
2032                 s->sockfd = sockfd;
2033                 s->addr = addr;
2034
2035                 (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
2036                 return NULL;
2037         }
2038 \r
2039         chan = SOUP_SOCKET_IOCHANNEL_NEW (sockfd),\r
2040
2041         /* Wait for the connection */
2042         state = g_new0 (SoupSocketState, 1);
2043         state->addr = addr;
2044         state->func = func;
2045         state->data = data;
2046         state->sockfd = sockfd;\r
2047         state->connect_watch = g_io_add_watch (chan,\r
2048                                                SOUP_ANY_IO_CONDITION,\r
2049                                                soup_socket_new_cb, \r
2050                                                state);\r
2051 \r
2052         g_io_channel_unref (chan);\r
2053
2054         return state;
2055 }
2056
2057 #endif          /*********** End Windows code ***********/\r
2058 \r
2059 /**\r
2060  * soup_socket_new_cancel:\r
2061  * @id: ID of the connection.\r
2062  *\r
2063  * Cancel an asynchronous connection that was started with\r
2064  * soup_socket_new().\r
2065  **/\r
2066 void\r
2067 soup_socket_new_cancel (SoupSocketNewId id)\r
2068 {\r
2069         SoupSocketState* state = (SoupSocketState*) id;\r
2070 \r
2071         g_source_remove (state->connect_watch);\r
2072         soup_address_unref (state->addr);\r
2073         g_free (state);\r
2074 }\r
2075
2076 static void
2077 soup_socket_new_sync_cb (SoupSocket*         socket,
2078                          SoupSocketNewStatus status,
2079                          gpointer            data)
2080 {
2081         SoupSocket **ret = data;
2082         *ret = socket;
2083 }
2084
2085 SoupSocket *
2086 soup_socket_new_sync (SoupAddress *addr)
2087 {
2088         SoupSocket *ret = (SoupSocket *) 0xdeadbeef;
2089
2090         soup_socket_new (addr, soup_socket_new_sync_cb, &ret);
2091
2092         while (1) {
2093                 g_main_iteration (TRUE);
2094                 if (ret != (SoupSocket *) 0xdeadbeef) return ret;
2095         }
2096
2097         return ret;
2098 }
2099
2100 /**
2101  * soup_socket_ref
2102  * @s: SoupSocket to reference
2103  *
2104  * Increment the reference counter of the SoupSocket.
2105  **/
2106 void
2107 soup_socket_ref (SoupSocket* s)
2108 {
2109         g_return_if_fail (s != NULL);
2110
2111         ++s->ref_count;
2112 }
2113
2114 /**
2115  * soup_socket_unref
2116  * @s: #SoupSocket to unreference
2117  *
2118  * Remove a reference from the #SoupSocket.  When reference count
2119  * reaches 0, the socket is deleted.
2120  **/
2121 void
2122 soup_socket_unref (SoupSocket* s)
2123 {
2124         g_return_if_fail(s != NULL);
2125
2126         --s->ref_count;
2127
2128         if (s->ref_count == 0) {
2129                 SOUP_CLOSE_SOCKET (s->sockfd);
2130
2131                 if (s->addr) soup_address_unref (s->addr);
2132
2133                 if (s->iochannel) g_io_channel_unref (s->iochannel);
2134
2135                 g_free(s);
2136         }
2137 }
2138
2139 /**
2140  * soup_socket_get_iochannel:
2141  * @socket: SoupSocket to get GIOChannel from.
2142  *
2143  * Get the #GIOChannel for the #SoupSocket.
2144  *
2145  * For a client socket, the #GIOChannel represents the data stream.
2146  * Use it like you would any other #GIOChannel.
2147  *
2148  * For a server socket however, the #GIOChannel represents incoming
2149  * connections.  If you can read from it, there's a connection
2150  * waiting.
2151  *
2152  * There is one channel for every socket.  This function refs the
2153  * channel before returning it.  You should unref the channel when
2154  * you are done with it.  However, you should not close the channel -
2155  * this is done when you delete the socket.
2156  *
2157  * Returns: A #GIOChannel; NULL on failure.
2158  *
2159  **/
2160 GIOChannel*
2161 soup_socket_get_iochannel (SoupSocket* socket)
2162 {
2163         g_return_val_if_fail (socket != NULL, NULL);
2164
2165         if (socket->iochannel == NULL)
2166                 socket->iochannel = SOUP_SOCKET_IOCHANNEL_NEW (socket->sockfd);
2167
2168         g_io_channel_ref (socket->iochannel);
2169
2170         return socket->iochannel;
2171 }
2172
2173 /**
2174  * soup_socket_get_address:
2175  * @socket: #SoupSocket to get address of.
2176  *
2177  * Get the address of the socket.  If the socket is client socket,
2178  * the address is the address of the remote host it is connected to.
2179  * If the socket is a server socket, the address is the address of
2180  * the local host.  (Though you should use
2181  * soup_address_gethostaddr() to get the #SoupAddress of the local
2182  * host.)
2183  *
2184  * Returns: #SoupAddress of socket; NULL on failure.
2185  **/
2186 SoupAddress *
2187 soup_socket_get_address (const SoupSocket* socket)
2188 {
2189         g_return_val_if_fail (socket != NULL, NULL);
2190         g_return_val_if_fail (socket->addr != NULL, NULL);
2191
2192         soup_address_ref (socket->addr);
2193
2194         return socket->addr;
2195 }
2196
2197 /**
2198  * soup_socket_get_port:
2199  * @socket: SoupSocket to get the port number of.
2200  *
2201  * Get the port number the socket is bound to.
2202  *
2203  * Returns: Port number of the socket.
2204  **/
2205 gint
2206 soup_socket_get_port(const SoupSocket* socket)
2207 {
2208         g_return_val_if_fail (socket != NULL, 0);
2209
2210         return g_ntohs (SOUP_SOCKADDR_IN (socket->addr->sa).sin_port);
2211 }
2212
2213 /**
2214  * soup_socket_server_new:
2215  * @port: Port number for the socket (SOUP_SERVER_ANY_PORT if you don't care).
2216  *
2217  * Create and open a new #SoupSocket with the specified port number.
2218  * Use this sort of socket when your are a server and you know what
2219  * the port number should be (or pass 0 if you don't care what the
2220  * port is).
2221  *
2222  * Returns: a new #SoupSocket, or NULL if there was a failure.
2223  **/
2224 SoupSocket *
2225 soup_socket_server_new (const gint port)
2226 {
2227         SoupSocket* s;
2228         struct sockaddr_in* sa_in;
2229         socklen_t socklen;
2230
2231         /* Create socket */
2232         s = g_new0 (SoupSocket, 1);
2233         s->ref_count = 1;
2234
2235         if ((s->sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
2236                 g_free (s);
2237                 return NULL;
2238         }
2239
2240         s->addr = g_new0 (SoupAddress, 1);
2241         s->addr->ref_count = 1;
2242
2243         /* Set up address and port for connection */
2244         sa_in = (struct sockaddr_in*) &s->addr->sa;
2245         sa_in->sin_family = AF_INET;
2246         sa_in->sin_addr.s_addr = g_htonl (INADDR_ANY);
2247         sa_in->sin_port = g_htons (port);
2248
2249         /* The socket is set to non-blocking mode later in the Windows
2250            version.*/
2251 #ifndef SOUP_WIN32
2252         {
2253                 const int on = 1;
2254                 gint flags;
2255
2256                 /* Set REUSEADDR so we can reuse the port */
2257                 if (setsockopt (s->sockfd,
2258                                 SOL_SOCKET,
2259                                 SO_REUSEADDR,
2260                                 &on,
2261                                 sizeof (on)) != 0)
2262                         g_warning("Can't set reuse on tcp socket\n");
2263
2264                 /* Get the flags (should all be 0?) */
2265                 flags = fcntl (s->sockfd, F_GETFL, 0);
2266                 if (flags == -1) goto SETUP_ERROR;
2267
2268                 /* Make the socket non-blocking */
2269                 if (fcntl (s->sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
2270                         goto SETUP_ERROR;
2271         }
2272 #endif
2273
2274         /* Bind */
2275         if (bind (s->sockfd, &s->addr->sa, sizeof (s->addr->sa)) != 0)
2276                 goto SETUP_ERROR;
2277
2278         /* Get the socket name - don't care if it fails */
2279         socklen = sizeof (s->addr->sa);
2280         getsockname (s->sockfd, &s->addr->sa, &socklen);
2281
2282         /* Listen */
2283         if (listen (s->sockfd, 10) != 0) goto SETUP_ERROR;
2284
2285         return s;
2286
2287  SETUP_ERROR:
2288         close (s->sockfd);
2289         g_free (s->addr);
2290         g_free (s);
2291         return NULL;
2292 }
2293
2294 #ifndef SOUP_WIN32  /*********** Unix code ***********/
2295
2296 /**
2297  * soup_socket_server_accept:
2298  * @socket: #SoupSocket to accept connections from.
2299  *
2300  * Accept a connection from the socket.  The socket must have been
2301  * created using soup_socket_server_new().  This function will
2302  * block (use soup_socket_server_try_accept() if you don't
2303  * want to block).  If the socket's #GIOChannel is readable, it DOES
2304  * NOT mean that this function will not block.
2305  *
2306  * Returns: a new #SoupSocket if there is another connect, or NULL if
2307  * there's an error.
2308  **/
2309 SoupSocket *
2310 soup_socket_server_accept (SoupSocket *socket)
2311 {
2312         gint sockfd;
2313         gint flags;
2314         struct sockaddr sa;
2315         socklen_t n;
2316         fd_set fdset;
2317         SoupSocket* s;
2318
2319         g_return_val_if_fail (socket != NULL, NULL);
2320
2321  try_again:
2322         FD_ZERO (&fdset);
2323         FD_SET (socket->sockfd, &fdset);
2324
2325         if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
2326                 if (errno == EINTR) goto try_again;
2327                 return NULL;
2328         }
2329
2330         n = sizeof(s->addr->sa);
2331
2332         if ((sockfd = accept (socket->sockfd, &sa, &n)) == -1) {
2333                 if (errno == EWOULDBLOCK ||
2334                     errno == ECONNABORTED ||
2335 #ifdef EPROTO           /* OpenBSD does not have EPROTO */
2336                     errno == EPROTO ||
2337 #endif
2338                     errno == EINTR)
2339                         goto try_again;
2340
2341                 return NULL;
2342         }
2343
2344         /* Get the flags (should all be 0?) */
2345         flags = fcntl (sockfd, F_GETFL, 0);
2346         if (flags == -1) return NULL;
2347
2348         /* Make the socket non-blocking */
2349         if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
2350                 return NULL;
2351
2352         s = g_new0 (SoupSocket, 1);
2353         s->ref_count = 1;
2354         s->sockfd = sockfd;
2355
2356         s->addr = g_new0 (SoupAddress, 1);
2357         s->addr->ref_count = 1;
2358         memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
2359
2360         return s;
2361 }
2362
2363 /**
2364  * soup_socket_server_try_accept:
2365  * @socket: SoupSocket to accept connections from.
2366  *
2367  * Accept a connection from the socket without blocking.  The socket
2368  * must have been created using soup_socket_server_new().  This
2369  * function is best used with the sockets #GIOChannel.  If the
2370  * channel is readable, then you PROBABLY have a connection.  It is
2371  * possible for the connection to close by the time you call this, so
2372  * it may return NULL even if the channel was readable.
2373  *
2374  * Returns a new SoupSocket if there is another connect, or NULL
2375  * otherwise.
2376  **/
2377 SoupSocket *
2378 soup_socket_server_try_accept (SoupSocket *socket)
2379 {
2380         gint sockfd;
2381         gint flags;
2382         struct sockaddr sa;
2383         socklen_t n;
2384         fd_set fdset;
2385         SoupSocket* s;
2386         struct timeval tv = {0, 0};
2387
2388         g_return_val_if_fail (socket != NULL, NULL);
2389
2390  try_again:
2391         FD_ZERO (&fdset);
2392         FD_SET (socket->sockfd, &fdset);
2393
2394         if (select (socket->sockfd + 1, &fdset, NULL, NULL, &tv) == -1) {
2395                 if (errno == EINTR) goto try_again;
2396                 return NULL;
2397         }
2398
2399         n = sizeof(sa);
2400
2401         if ((sockfd = accept (socket->sockfd, &sa, &n)) == -1) {
2402                 /* If we get an error, return.  We don't want to try again as we
2403                    do in soup_socket_server_accept() - it might cause a
2404                    block. */
2405                 return NULL;
2406         }
2407
2408         /* Get the flags (should all be 0?) */
2409         flags = fcntl (sockfd, F_GETFL, 0);
2410         if (flags == -1) return NULL;
2411
2412         /* Make the socket non-blocking */
2413         if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
2414                 return NULL;
2415
2416         s = g_new0 (SoupSocket, 1);
2417         s->ref_count = 1;
2418         s->sockfd = sockfd;
2419
2420         s->addr = g_new0 (SoupAddress, 1);
2421         s->addr->ref_count = 1;
2422         memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
2423
2424         return s;
2425 }
2426
2427 #else   /*********** Windows code ***********/
2428
2429 SoupSocket *
2430 soup_socket_server_accept (SoupSocket *socket)
2431 {
2432         gint sockfd;
2433         struct sockaddr sa;
2434         gint n;
2435         fd_set fdset;
2436         SoupSocket* s;
2437         u_long arg;
2438
2439         g_return_val_if_fail (socket != NULL, NULL);
2440
2441         FD_ZERO (&fdset);
2442         FD_SET ((unsigned)socket->sockfd, &fdset);
2443
2444         if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
2445                 return NULL;
2446         }
2447
2448         /* make sure the socket is in blocking mode */
2449
2450         arg = 0;
2451         if (ioctlsocket (socket->sockfd, FIONBIO, &arg))
2452                 return NULL;
2453
2454         sockfd = accept (socket->sockfd, &sa, NULL);
2455         /* if it fails, looping isn't going to help */
2456
2457         if (sockfd == INVALID_SOCKET) {
2458                 return NULL;
2459         }
2460
2461         s = g_new0 (SoupSocket, 1);
2462         s->ref_count = 1;
2463         s->sockfd = sockfd;
2464
2465         s->addr = g_new0 (SoupAddress, 1);
2466         s->addr->ref_count = 1;
2467         memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
2468
2469         return s;
2470 }
2471
2472 SoupSocket *
2473 soup_socket_server_try_accept (SoupSocket *socket)
2474 {
2475         gint sockfd;
2476         struct sockaddr sa;
2477
2478         fd_set fdset;
2479         SoupSocket* s;
2480         u_long arg;
2481
2482         g_return_val_if_fail (socket != NULL, NULL);
2483         FD_ZERO (&fdset);
2484         FD_SET ((unsigned)socket->sockfd, &fdset);
2485
2486         if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
2487                 return NULL;
2488         }
2489         /* make sure the socket is in non-blocking mode */
2490
2491         arg = 1;
2492         if (ioctlsocket (socket->sockfd, FIONBIO, &arg))
2493                 return NULL;
2494
2495         sockfd = accept (socket->sockfd, &sa, NULL);
2496         /* if it fails, looping isn't going to help */
2497
2498         if (sockfd == INVALID_SOCKET) {
2499                 return NULL;
2500         }
2501
2502         s = g_new0 (SoupSocket, 1);
2503         s->ref_count = 1;
2504         s->sockfd = sockfd;
2505
2506         s->addr = g_new0 (SoupAddress, 1);
2507         s->addr->ref_count = 1;
2508         memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
2509
2510         return s;
2511 }
2512 #endif          /*********** End Windows code ***********/
2513
2514 #ifdef SOUP_WIN32  /*********** Windows code ***********/
2515 int
2516 soup_MainCallBack (GIOChannel   *iochannel,
2517                    GIOCondition  condition,
2518                    void         *nodata)
2519 {
2520         MSG msg;
2521
2522         gpointer data;
2523         SoupAddressState *IAstate;
2524         SoupAddressReverseState *IARstate;
2525
2526         /*Take the msg off the message queue */
2527         PeekMessage (&msg, soup_hWnd, 0, 0, PM_REMOVE);
2528
2529         switch (msg.message) {
2530         case IA_NEW_MSG:
2531                 WaitForSingleObject (soup_Mutex, INFINITE);
2532                 data = g_hash_table_lookup (soup_hash, (gpointer) msg.wParam);
2533                 g_hash_table_remove (soup_hash, (gpointer) msg.wParam);
2534                 ReleaseMutex (soup_Mutex);
2535
2536                 IAstate = (SoupAddressState*) data;
2537                 /* NULL if OK */
2538                 IAstate->errorcode = WSAGETASYNCERROR(msg.lParam);
2539
2540                 /* Now call the callback function */
2541                 soup_address_new_cb (NULL, G_IO_IN, (gpointer) IAstate);
2542
2543                 break;
2544         case GET_NAME_MSG:
2545                 WaitForSingleObject (soup_Mutex, INFINITE);
2546                 data = g_hash_table_lookup (soup_hash, (gpointer) msg.wParam);
2547                 g_hash_table_remove (soup_hash, (gpointer) msg.wParam);
2548                 ReleaseMutex (soup_Mutex);
2549
2550                 IARstate = (SoupAddressReverseState*) data;
2551                 /* NULL if OK */
2552                 IARstate->errorcode = WSAGETASYNCERROR(msg.lParam);
2553
2554                 /* Now call the callback function */
2555                 soup_address_get_name_cb (NULL,
2556                                           G_IO_IN,
2557                                           (gpointer) IARstate);
2558                 break;\r
2559         }
2560
2561         return 1;
2562 }
2563
2564 LRESULT CALLBACK
2565 SoupWndProc (HWND hwnd,        /* handle to window */
2566              UINT uMsg,        /* message identifier */
2567              WPARAM wParam,    /* first message parameter */
2568              LPARAM lParam)    /* second message parameter */
2569 {
2570         switch (uMsg) {
2571         case WM_CREATE:  /* Initialize the window. */
2572                 return 0;
2573         case WM_PAINT:   /* Paint the window's client area. */
2574                 return 0;
2575         case WM_SIZE:    /* Set the size and position of the window. */
2576                 return 0;
2577         case WM_DESTROY: /* Clean up window-specific data objects. */
2578                 return 0;
2579
2580         default:
2581                 return DefWindowProc (hwnd, uMsg, wParam, lParam);
2582         }
2583 }
2584
2585 BOOL WINAPI
2586 DllMain (HINSTANCE hinstDLL,  /* handle to DLL module */
2587          DWORD fdwReason,     /* reason for calling functionm */
2588          LPVOID lpvReserved   /* reserved */)
2589 {
2590         WORD wVersionRequested;
2591         WSADATA wsaData;
2592         int err;
2593
2594         switch(fdwReason) {
2595         case DLL_PROCESS_ATTACH:
2596                 /* The DLL is being mapped into process's address space */
2597                 /* Do any required initialization on a per application basis,
2598                    return FALSE if failed */
2599                 wVersionRequested = MAKEWORD (2, 0);
2600
2601                 err = WSAStartup (wVersionRequested, &wsaData);
2602                 if (err != 0) {
2603                         /* Tell the user that we could not find a usable
2604                            WinSock DLL.  */
2605                         return FALSE;
2606                 }
2607
2608                 /* Confirm that the WinSock DLL supports 2.0.*/
2609                 /* Note that if the DLL supports versions greater    */
2610                 /* than 2.0 in addition to 2.0, it will still return */
2611                 /* 2.0 in wVersion since that is the version we      */
2612                 /* requested.                                        */
2613
2614                 if (LOBYTE(wsaData.wVersion) != 2 ||
2615                     HIBYTE(wsaData.wVersion) != 0) {
2616                         /* Tell the user that we could not find a usable */
2617                         /* WinSock DLL.                                  */
2618                         WSACleanup ();
2619                         return FALSE;
2620                 }
2621
2622                 /* The WinSock DLL is acceptable. Proceed. */
2623
2624                 /* Setup and register a windows class that we use for out
2625                    GIOchannel */
2626                 soupWndClass.cbSize = sizeof (WNDCLASSEX);
2627                 soupWndClass.style = CS_SAVEBITS;
2628                 soupWndClass.lpfnWndProc = (WNDPROC) SoupWndProc;
2629                 soupWndClass.cbClsExtra = 0;
2630                 soupWndClass.cbWndExtra = 0;
2631                 soupWndClass.hInstance = hinstDLL;
2632                 soupWndClass.hIcon = NULL;
2633                 soupWndClass.hCursor = NULL;
2634                 soupWndClass.hbrBackground = NULL;
2635                 soupWndClass.lpszMenuName = NULL;
2636                 soupWndClass.lpszClassName = "Soup";
2637                 soupWndClass.hIconSm = NULL;
2638
2639                 if (!RegisterClassEx (&soupWndClass)) return FALSE;
2640
2641                 soup_hWnd  = CreateWindowEx (0,
2642                                              "Soup",
2643                                              "none",
2644                                              WS_OVERLAPPEDWINDOW,
2645                                              CW_USEDEFAULT,
2646                                              CW_USEDEFAULT,
2647                                              CW_USEDEFAULT,
2648                                              CW_USEDEFAULT,
2649                                              (HWND) NULL,
2650                                              (HMENU) NULL,
2651                                              hinstDLL,
2652                                              (LPVOID) NULL);
2653
2654                 if (!soup_hWnd) return FALSE;
2655
2656                 soup_iochannel =
2657                         g_io_channel_win32_new_messages (
2658                                 (unsigned int) soup_hWnd);
2659
2660                 /* Add a watch */
2661                 soup_io_watch_ID =
2662                         g_io_add_watch (soup_iochannel,
2663                                         G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
2664                                         soup_MainCallBack,
2665                                         NULL);
2666
2667                 soup_hash = g_hash_table_new (NULL, NULL);
2668
2669                 soup_Mutex = CreateMutex (NULL, FALSE, "soup_Mutex");
2670                 if (soup_Mutex == NULL) return FALSE;
2671
2672                 soup_hostent_Mutex = CreateMutex (NULL,
2673                                                   FALSE,
2674                                                   "soup_hostent_Mutex");
2675                 if (soup_hostent_Mutex == NULL) return FALSE;
2676
2677                 break;
2678         case DLL_THREAD_ATTACH:
2679                 break;
2680         case DLL_THREAD_DETACH:
2681                 break;
2682         case DLL_PROCESS_DETACH:
2683                 /* The DLL unmapped from process's address space. Do necessary
2684                    cleanup */
2685                 g_source_remove (soup_io_watch_ID);
2686                 g_free (soup_iochannel);
2687                 DestroyWindow (soup_hWnd);
2688
2689                 WSACleanup ();
2690
2691                 break;
2692         }
2693
2694         return TRUE;
2695 }
2696
2697 #endif          /*********** End Windows code ***********/