1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
3 * soup-socket.c: Asyncronous Callback-based SOAP Request Queue.
6 * David Helder (dhelder@umich.edu)
7 * Alex Graveley (alex@helixcode.com)
9 * Original code compliments of David Helder's GNET Networking Library.
11 * Copyright (C) 2000, Helix Code, Inc.
25 #include <sys/types.h>
27 #ifdef HAVE_SYS_PARAM_H
28 #include <sys/param.h>
31 #include "soup-private.h"
32 #include "soup-socket.h"
34 #ifndef SOUP_WIN32 /*********** Unix specific ***********/
39 #include <arpa/inet.h>
40 #include <arpa/nameser.h>
42 #include <netinet/in.h>
43 #include <sys/ioctl.h>
44 #include <sys/ptrace.h>
45 #include <sys/socket.h>
47 #include <sys/utsname.h>
50 #ifdef HAVE_SYS_POLL_H
54 #ifdef HAVE_SYS_SOCKIO_H
55 #include <sys/sockio.h>
59 #define socklen_t size_t
62 #define SOUP_CLOSE_SOCKET(SOCKFD) close(SOCKFD)
63 #define SOUP_SOCKET_IOCHANNEL_NEW(SOCKFD) g_io_channel_unix_new(SOCKFD)
66 * Maintains a list of all currently valid SoupAddresses or active
67 * SoupAddressState lookup requests.
69 static GHashTable *active_address_hash = NULL;
71 #else /*********** Windows specific ***********/
78 #define socklen_t gint32
80 #define SOUP_CLOSE_SOCKET(SOCKFD) closesocket(SOCKFD)
81 #define SOUP_SOCKET_IOCHANNEL_NEW(SOCKFD) \
82 g_io_channel_win32_new_stream_socket(SOCKFD)
84 WNDCLASSEX soupWndClass;
86 guint soup_io_watch_ID;
87 GIOChannel *soup_iochannel;
89 GHashTable *soup_hash;
91 HANDLE soup_hostent_Mutex;
93 #define IA_NEW_MSG 100 /* soup_address_new */
94 #define GET_NAME_MSG 101 /* soup_address_get_name */
97 * Windows does not have inet_aton, but it does have inet_addr.
99 * TODO: We should write a better inet_aton because inet_addr doesn't catch
100 * 255.255.255.255 properly.
103 inet_aton(const char *cp, struct in_addr *inp)
105 inp->s_addr = inet_addr (cp);
106 if (inp->s_addr == INADDR_NONE) return 0;
110 #endif /*********** End Windows specific ***********/
112 #ifndef INET_ADDRSTRLEN
113 #define INET_ADDRSTRLEN 16
114 #define INET6_ADDRSTRLEN 46
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)
122 SoupAddressNewFn func;
128 SoupAddressNewFn func;
130 GSList *cb_list; /* CONTAINS: SoupAddressCbData */
139 char hostentBuffer [MAXGETHOSTSTRUCT];
147 SoupAddressGetNameFn func;
153 guchar buffer [256 + 1];
157 char hostentBuffer [MAXGETHOSTSTRUCT];
160 } SoupAddressReverseState;
166 SoupSocketNewFn func;
177 SoupSocketConnectFn func;
180 gpointer inetaddr_id;
182 } SoupSocketConnectState;
185 /* Testing Defines */
186 /* #undef HAVE_GETHOSTBYNAME_R_GLIBC */
187 /* #define HAVE_GETHOSTBYNAME_R_GLIB_MUTEX */
189 #ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
190 G_LOCK_DEFINE (gethostbyname);
194 * soup_gethostbyname:
196 * Thread safe gethostbyname. The only valid fields are sin_len,
197 * sin_family, and sin_addr.
200 soup_gethostbyname(const char* hostname,
201 struct sockaddr_in* sa,
206 #ifdef HAVE_GETHOSTBYNAME_R_GLIBC
208 struct hostent result_buf, *result;
215 buf = g_new (gchar, len);
217 while ((res = gethostbyname_r (hostname,
224 buf = g_renew (gchar, buf, len);
227 if (res || result == NULL || result->h_addr_list [0] == NULL)
231 sa->sin_family = result->h_addrtype;
232 memcpy (&sa->sin_addr,
233 result->h_addr_list [0],
237 if (nicename && result->h_name)
238 *nicename = g_strdup (result->h_name);
246 #ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
248 struct hostent result;
255 buf = g_new (gchar, len);
257 while ((res = gethostbyname_r (hostname,
263 buf = g_renew (gchar, buf, len);
266 if (res || hp == NULL || hp->h_addr_list [0] == NULL)
270 sa->sin_family = result->h_addrtype;
271 memcpy (&sa->sin_addr,
272 result->h_addr_list [0],
276 if (nicename && result->h_name)
277 *nicename = g_strdup (result->h_name);
285 #ifdef HAVE_GETHOSTBYNAME_R_HPUX
287 struct hostent result;
288 struct hostent_data buf;
291 res = gethostbyname_r (hostname, &result, &buf);
295 sa->sin_family = result.h_addrtype;
296 memcpy (&sa->sin_addr,
297 result.h_addr_list [0],
301 if (nicename && result.h_name)
302 *nicename = g_strdup(result.h_name);
308 #ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
312 G_LOCK (gethostbyname);
313 he = gethostbyname (hostname);
314 G_UNLOCK (gethostbyname);
316 if (he != NULL && he->h_addr_list [0] != NULL) {
318 sa->sin_family = he->h_addrtype;
319 memcpy (&sa->sin_addr,
324 if (nicename && he->h_name)
325 *nicename = g_strdup (he->h_name);
333 struct hostent *result;
335 WaitForSingleObject (soup_hostent_Mutex, INFINITE);
336 result = gethostbyname (hostname);
338 if (result != NULL) {
340 sa->sin_family = result->h_addrtype;
341 memcpy (&sa->sin_addr,
342 result->h_addr_list [0],
346 if (nicename && result->h_name)
347 *nicename = g_strdup(result->h_name);
349 ReleaseMutex(soup_hostent_Mutex);
357 he = gethostbyname (hostname);
358 if (he != NULL && he->h_addr_list [0] != NULL) {
360 sa->sin_family = he->h_addrtype;
361 memcpy (&sa->sin_addr,
366 if (nicename && he->h_name)
367 *nicename = g_strdup (he->h_name);
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.
386 Returns the hostname, NULL if there was an error.
390 soup_gethostbyaddr (const char* addr, size_t length, int type)
394 #ifdef HAVE_GETHOSTBYNAME_R_GLIBC
396 struct hostent result_buf, *result;
403 buf = g_new (gchar, len);
405 while ((res = gethostbyaddr_r (addr,
414 buf = g_renew (gchar, buf, len);
417 if (res || result == NULL || result->h_name == NULL)
420 rv = g_strdup(result->h_name);
426 #ifdef HAVE_GET_HOSTBYNAME_R_SOLARIS
428 struct hostent result;
435 buf = g_new (gchar, len);
437 while ((res = gethostbyaddr_r (addr,
445 buf = g_renew (gchar, buf, len);
448 if (res || hp == NULL || hp->h_name == NULL)
451 rv = g_strdup(result->h_name);
457 #ifdef HAVE_GETHOSTBYNAME_R_HPUX
459 struct hostent result;
460 struct hostent_data buf;
463 res = gethostbyaddr_r (addr, length, type, &result, &buf);
465 if (res == 0) rv = g_strdup (result.h_name);
468 #ifdef HAVE_GETHOSTBYNAME_R_GLIB_MUTEX
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);
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);
493 he = gethostbyaddr (addr, length, type);
494 if (he != NULL && he->h_name != NULL)
495 rv = g_strdup (he->h_name);
506 #ifndef SOUP_WIN32 /*********** Unix code ***********/
509 soup_address_new_cb (GIOChannel* iochannel,
510 GIOCondition condition,
513 SoupAddressState* state = (SoupAddressState*) data;
514 struct sockaddr_in* sa_in;
515 GSList *cb_list, *iter;
516 SoupAddressNewFn cb_func;
519 if (!(condition & G_IO_IN)) {
522 g_source_remove (state->watch);
524 waitpid (state->pid, &ret, 0);
526 if (WIFSIGNALED (ret) || WEXITSTATUS (ret) != 1) goto ERROR;
529 * Exit status of one means we are inside a debugger.
530 * Resolve the name synchronously.
532 sa_in = (struct sockaddr_in*) &state->ia.sa;
534 if (!soup_gethostbyname (state->ia.name, sa_in, NULL))
535 g_warning ("Problem resolving host name");
541 buf = &state->buffer [state->len];
542 length = sizeof (state->buffer) - state->len;
544 rv = read (state->fd, buf, length);
545 if (rv < 0) goto ERROR;
549 /* Return true if there's more to read */
550 if ((state->len - 1) != state->buffer [0]) return TRUE;
552 if (state->len < 2) goto ERROR;
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));
559 g_source_remove (state->watch);
561 waitpid (state->pid, NULL, WNOHANG);
564 /* Get state data before realloc */
565 cb_list = iter = state->cb_list;
566 cb_func = state->func;
567 cb_data = state->data;
569 /* Invert resolved address reference count */
570 state->ia.ref_count = ~state->ia.ref_count + 1;
573 * Realloc state to size of SoupAddress, and reinsert to resolved
576 state = g_realloc (state, sizeof (SoupAddress));
577 g_hash_table_insert (active_address_hash, state->ia.name, state);
579 (*cb_func) (&state->ia, SOUP_ADDRESS_STATUS_OK, cb_data);
582 SoupAddressCbData *cb = iter->data;
584 (*cb->func) (&state->ia, SOUP_ADDRESS_STATUS_OK, cb->data);
590 g_slist_free (cb_list);
595 /* Remove the watch now in case we don't return immediately */
596 g_source_remove (state->watch);
598 (*state->func) (NULL, SOUP_ADDRESS_STATUS_ERROR, state->data);
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,
608 state->ia.ref_count = -1;
609 soup_address_new_cancel (state);
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.
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.
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.
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.
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.
640 * The Windows version should work fine. Windows has an asynchronous
641 * DNS lookup function.
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.
648 soup_address_new (const gchar* name,
650 SoupAddressNewFn func,
655 struct in_addr inaddr;
656 struct sockaddr_in sa;
657 struct sockaddr_in* sa_in;
659 SoupAddressState* state;
662 g_return_val_if_fail (name != NULL, NULL);
663 g_return_val_if_fail (func != NULL, NULL);
665 /* Try to read the name as if were dotted decimal */
666 if (inet_aton (name, &inaddr) != 0) {
667 ia = g_new0 (SoupAddress, 1);
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,
675 sizeof(struct in_addr));
677 (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
681 if (!active_address_hash)
682 active_address_hash = g_hash_table_new (soup_str_case_hash,
683 soup_str_case_equal);
685 ia = g_hash_table_lookup (active_address_hash, name);
687 if (ia && ia->ref_count > 0) {
689 * Existing valid request, use it.
691 if (soup_address_get_port (ia) == port) {
692 soup_address_ref (ia);
695 * We can reuse the address, but we have to
698 SoupAddress *new_ia = soup_address_copy (ia);
699 soup_address_set_port (new_ia, port);
703 (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
705 } else if (ia && soup_address_get_port (ia) == port) {
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
713 SoupAddressCbData *cb_data;
715 cb_data = g_new0 (SoupAddressCbData, 1);
716 cb_data->func = func;
717 cb_data->data = data;
719 state = (SoupAddressState *) ia;
720 state->cb_list = g_slist_prepend (state->cb_list,
723 state->ia.ref_count--;
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);
737 sa_in = (struct sockaddr_in*) &sa;
738 sa_in->sin_family = AF_INET;
739 sa_in->sin_port = g_htons (port);
741 ia = g_new0(SoupAddress, 1);
742 ia->name = g_strdup (name);
744 ia->sa = *((struct sockaddr *) &sa);
746 (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
751 /* That didn't work - we need to fork */
754 if (pipe (pipes) == -1) {
755 (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
765 if (errno == EAGAIN) {
766 /* Yield the processor */
771 /* Else there was a goofy error */
772 g_warning ("Fork error: %s (%d)\n",
778 (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
785 signal (SIGCHLD, SIG_IGN);
787 if (ptrace (PTRACE_ATTACH, getppid (), NULL, NULL) == -1) {
789 * Attach failed; it's probably already being
793 g_warning ("ptrace: Unexpected error: %s",
800 * Wait for the SIGSTOP from PTRACE_ATTACH to arrive at the
803 waitpid (getppid (), NULL, 0);
805 if (ptrace (PTRACE_DETACH, getppid (), NULL, NULL) == -1)
806 g_warning ("ptrace: Detach failed: %s",
809 kill (getppid(), SIGCONT);
813 * Try to get the host by name (ie, DNS)
815 if (soup_gethostbyname (name, &sa, NULL)) {
816 guchar size = 4; /* FIX for IPv6 */
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");
825 if (write (pipes [1], &zero, sizeof(zero)) == -1)
826 g_warning ("Problem writing to pipe\n");
829 /* Close the socket */
832 /* Exit (we don't want atexit called, so do _exit instead) */
833 _exit (EXIT_SUCCESS);
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;
844 state->fd = pipes [0];
846 sa_in = (struct sockaddr_in*) &state->ia.sa;
847 sa_in->sin_family = AF_INET;
848 sa_in->sin_port = g_htons (port);
850 g_hash_table_insert (active_address_hash,
854 chan = g_io_channel_unix_new (pipes [0]);
856 /* Set up an watch to read from the pipe */
860 G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
864 g_io_channel_unref (chan);
871 * soup_address_new_cancel:
872 * @id: ID of the lookup
874 * Cancel an asynchronous SoupAddress creation that was started with
875 * soup_address_new().
878 soup_address_new_cancel (SoupAddressNewId id)
880 SoupAddressState* state = (SoupAddressState*) id;
883 g_return_if_fail (state != NULL);
885 state->ia.ref_count++;
887 if (state->ia.ref_count == 0) {
888 g_hash_table_remove (active_address_hash, state->ia.name);
889 g_free (state->ia.name);
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);
895 g_source_remove (state->watch);
898 kill (state->pid, SIGKILL);
899 waitpid (state->pid, NULL, 0);
905 #else /*********** Windows code ***********/
908 soup_address_new_cb (GIOChannel* iochannel,
909 GIOCondition condition,
912 SoupAddressState* state = (SoupAddressState*) data;
913 struct hostent *result;
914 struct sockaddr_in *sa_in;
916 if (state->errorcode) {
917 (*state->func) (&state->ia,
918 SOUP_ADDRESS_STATUS_ERROR,
924 result = (struct hostent*) state->hostentBuffer;
926 sa_in = (struct sockaddr_in*) &state->ia.sa;
927 memcpy (&sa_in->sin_addr, result->h_addr_list [0], result->h_length);
929 state->ia.name = g_strdup (result->h_name);
931 state = g_realloc (state, sizeof (SoupAddress));
933 (*state->func) (&state->ia, SOUP_ADDRESS_STATUS_OK, state->data);
940 soup_address_new (const gchar* name,
942 SoupAddressNewFn func,
945 struct in_addr inaddr;
946 struct sockaddr_in* sa_in;
947 SoupAddressState* state;
949 g_return_val_if_fail(name != NULL, NULL);
950 g_return_val_if_fail(func != NULL, NULL);
952 /* Try to read the name as if were dotted decimal */
954 inaddr.s_addr = inet_addr(name);
955 if (inaddr.s_addr != INADDR_NONE) {
956 SoupAddress* ia = NULL;
957 struct sockaddr_in* sa_in;
959 ia = g_new0(SoupAddress, 1);
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,
967 sizeof (struct in_addr));
969 (*func) (ia, SOUP_ADDRESS_STATUS_OK, data);
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;
980 sa_in = (struct sockaddr_in*) &state->ia.sa;
981 sa_in->sin_family = AF_INET;
982 sa_in->sin_port = g_htons (port);
984 state->WSAhandle = (int)
985 WSAAsyncGetHostByName (soup_hWnd,
988 state->hostentBuffer,
989 sizeof (state->hostentBuffer));
991 if (!state->WSAhandle) {
993 (*func) (NULL, SOUP_ADDRESS_STATUS_ERROR, data);
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,
1002 ReleaseMutex (soup_Mutex);
1008 soup_address_new_cancel (SoupAddressNewId id)
1010 SoupAddressState* state = (SoupAddressState*) id;
1012 g_return_if_fail(state != NULL);
1014 WSACancelAsyncRequest ((HANDLE)state->WSAhandle);
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);
1023 #endif /*********** End Windows code ***********/
1026 soup_address_new_sync_cb (SoupAddress *addr,
1027 SoupAddressStatus status,
1030 SoupAddress **ret = user_data;
1035 soup_address_new_sync (const gchar *name, const gint port)
1037 SoupAddress *ret = (SoupAddress *) 0xdeadbeef;
1039 soup_address_new (name, port, soup_address_new_sync_cb, &ret);
1042 g_main_iteration (TRUE);
1043 if (ret != (SoupAddress *) 0xdeadbeef) return ret;
1051 * @ia: SoupAddress to reference
1053 * Increment the reference counter of the SoupAddress.
1056 soup_address_ref (SoupAddress* ia)
1058 g_return_if_fail (ia != NULL);
1065 * soup_address_unref
1066 * @ia: SoupAddress to unreference
1068 * Remove a reference from the SoupAddress. When reference count
1069 * reaches 0, the address is deleted.
1072 soup_address_unref (SoupAddress* ia)
1074 g_return_if_fail (ia != NULL);
1078 if (ia->ref_count == 0) {
1079 if (ia->name != NULL) {
1081 g_hash_table_remove (active_address_hash, ia->name);
1091 * @ia: SoupAddress to copy
1093 * Creates a copy of the given SoupAddress
1096 soup_address_copy (SoupAddress* ia)
1098 SoupAddress* new_ia;
1099 g_return_val_if_fail (ia != NULL, NULL);
1101 new_ia = g_new0(SoupAddress, 1);
1102 new_ia->ref_count = 1;
1104 new_ia->name = g_strdup (ia->name);
1105 memcpy (&new_ia->sa, &ia->sa, sizeof(struct sockaddr));
1110 #ifndef SOUP_WIN32 /*********** Unix code ***********/
1113 soup_address_get_name_cb (GIOChannel* iochannel,
1114 GIOCondition condition,
1117 SoupAddressReverseState* state;
1120 state = (SoupAddressReverseState*) data;
1122 g_return_val_if_fail (state != NULL, FALSE);
1124 /* Read from the pipe */
1125 if (condition & G_IO_IN) {
1130 buf = &state->buffer [state->len];
1131 length = sizeof(state->buffer) - state->len;
1133 if ((rv = read (state->fd, buf, length)) >= 0) {
1136 /* Return true if there's more to read */
1137 if ((state->len - 1) != state->buffer [0])
1141 name = g_new (gchar, state->buffer [0] + 1);
1142 strncpy (name, &state->buffer [1], state->buffer [0]);
1143 name [state->buffer [0]] = '\0';
1145 state->ia->name = name;
1147 /* Remove the watch now in case we don't return
1149 g_source_remove (state->watch);
1152 (*state->func) (state->ia,
1153 SOUP_ADDRESS_STATUS_OK,
1158 waitpid (state->pid, NULL, 0);
1164 /* Remove the watch now in case we don't return immediately */
1165 g_source_remove (state->watch);
1168 (*state->func) (state->ia,
1169 SOUP_ADDRESS_STATUS_ERROR,
1172 soup_address_get_name_cancel (state);
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.
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.
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.
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.
1195 SoupAddressGetNameId
1196 soup_address_get_name (SoupAddress* ia,
1197 SoupAddressGetNameFn func,
1200 SoupAddressReverseState* state;
1206 g_return_val_if_fail (ia != NULL, NULL);
1207 g_return_val_if_fail (func != NULL, NULL);
1210 (func) (ia, SOUP_ADDRESS_STATUS_OK, ia->name, data);
1215 if (pipe (pipes) != 0) {
1216 (func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
1226 if (errno == EAGAIN) {
1227 /* Yield the processor */
1235 /* Else there was a goofy error */
1236 g_warning ("Fork error: %s (%d)\n",
1240 (*func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
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),
1254 guint lenint = strlen(name);
1257 g_warning ("Truncating domain name: %s\n",
1265 if ((write (pipes [1], &len, sizeof(len)) == -1) ||
1266 (write (pipes [1], name, len) == -1) )
1267 g_warning ("Problem writing to pipe\n");
1271 /* defined in netinet/in.h */
1272 gchar buffer [INET_ADDRSTRLEN];
1274 p = (guchar*) &(SOUP_SOCKADDR_IN (ia->sa).sin_addr);
1283 len = strlen (buffer);
1285 if ((write (pipes [1], &len, sizeof(len)) == -1) ||
1286 (write (pipes [1], buffer, len) == -1))
1287 g_warning ("Problem writing to pipe\n");
1290 /* Close the socket */
1293 /* Exit (we don't want atexit called, so do _exit instead) */
1294 _exit(EXIT_SUCCESS);
1298 soup_address_ref (ia);
1300 state = g_new0 (SoupAddressReverseState, 1);
1305 state->fd = pipes [0];
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,
1318 * soup_address_get_name_cancel:
1319 * @id: ID of the lookup
1321 * Cancel an asynchronous nice name lookup that was started with
1322 * soup_address_get_name().
1325 soup_address_get_name_cancel (SoupAddressGetNameId id)
1327 SoupAddressReverseState* state;
1328 state = (SoupAddressReverseState*) id;
1330 g_return_if_fail(state != NULL);
1332 soup_address_unref (state->ia);
1333 g_source_remove (state->watch);
1336 kill (state->pid, SIGKILL);
1337 waitpid (state->pid, NULL, 0);
1342 #else /*********** Windows code ***********/
1345 soup_address_get_name_cb (GIOChannel* iochannel,
1346 GIOCondition condition,
1349 SoupAddressReverseState* state;
1351 struct hostent* result;
1352 state = (SoupAddressReverseState*) data;
1354 result = (struct hostent*) state->hostentBuffer;
1356 if (state->errorcode) {
1357 (*state->func) (state->ia,
1358 SOUP_ADDRESS_STATUS_ERROR,
1364 state->ia->name = g_strdup (result->h_name);
1366 name = g_strdup (state->ia->name);
1368 (*state->func) (state->ia,
1369 SOUP_ADDRESS_STATUS_OK,
1377 SoupAddressGetNameId
1378 soup_address_get_name (SoupAddress* ia,
1379 SoupAddressGetNameFn func,
1382 SoupAddressReverseState* state;
1383 struct sockaddr_in* sa_in;
1385 g_return_val_if_fail(ia != NULL, NULL);
1386 g_return_val_if_fail(func != NULL, NULL);
1388 /* If we already know the name, just copy that */
1389 if (ia->name != NULL) {
1391 SOUP_ADDRESS_STATUS_OK,
1392 g_strdup (ia->name),
1396 /* Create a structure for the call back */
1397 state = g_new0 (SoupAddressReverseState, 1);
1402 sa_in = (struct sockaddr_in*) &ia->sa;
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));
1412 if (!state->WSAhandle) {
1414 (func) (ia, SOUP_ADDRESS_STATUS_ERROR, NULL, data);
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,
1423 ReleaseMutex (soup_Mutex);
1429 soup_address_get_name_cancel (SoupAddressGetNameId id)
1431 SoupAddressReverseState* state;
1432 state = (SoupAddressReverseState*) id;
1434 g_return_if_fail(state != NULL);
1436 soup_address_unref (state->ia);
1437 WSACancelAsyncRequest ((HANDLE) state->WSAhandle);
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);
1447 #endif /*********** End Windows code ***********/
1450 soup_address_get_name_sync_cb (SoupAddress *addr,
1451 SoupAddressStatus status,
1455 const char **ret = user_data;
1460 soup_address_get_name_sync (SoupAddress *addr)
1462 const char *ret = (const char *) 0xdeadbeef;
1464 soup_address_get_name (addr,
1466 soup_address_get_name_sync_cb,
1471 g_main_iteration (TRUE);
1472 if (ret != (const char *) 0xdeadbeef) return ret;
1479 * soup_address_get_canonical_name:
1480 * @ia: Address to get the canonical name of.
1482 * Get the "canonical" name of an address (eg, for IP4 the dotted
1483 * decimal name 141.213.8.59).
1485 * Returns: NULL if there was an error. The caller is responsible
1486 * for deleting the returned string.
1489 soup_address_get_canonical_name (SoupAddress* ia)
1491 gchar buffer [INET_ADDRSTRLEN]; /* defined in netinet/in.h */
1492 guchar* p = (guchar*) &(SOUP_SOCKADDR_IN(ia->sa).sin_addr);
1494 g_return_val_if_fail (ia != NULL, NULL);
1504 return g_strdup (buffer);
1508 * soup_address_get_port:
1509 * @ia: Address to get the port number of.
1511 * Get the port number.
1512 * Returns: the port number.
1515 soup_address_get_port (const SoupAddress* ia)
1517 g_return_val_if_fail(ia != NULL, -1);
1519 return (gint) g_ntohs (((struct sockaddr_in*) &ia->sa)->sin_port);
1523 * soup_address_set_port:
1524 * @ia: Address to set the port number of.
1525 * @port: New port number
1527 * Set the port number.
1530 soup_address_set_port (const SoupAddress* ia, guint port)
1532 g_return_if_fail (ia != NULL);
1534 ((struct sockaddr_in*) &ia->sa)->sin_port = g_htons (port);
1538 * soup_address_hash:
1539 * @p: Pointer to an #SoupAddress.
1541 * Hash the address. This is useful for glib containers.
1543 * Returns: hash value.
1546 soup_address_hash (const gpointer p)
1548 const SoupAddress* ia;
1552 g_assert(p != NULL);
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);
1560 return (port ^ addr);
1564 * soup_address_equal:
1565 * @p1: Pointer to first #SoupAddress.
1566 * @p2: Pointer to second #SoupAddress.
1568 * Compare two #SoupAddress's.
1570 * Returns: 1 if they are the same; 0 otherwise.
1573 soup_address_equal (const gpointer p1, const gpointer p2)
1575 const SoupAddress* ia1 = (const SoupAddress*) p1;
1576 const SoupAddress* ia2 = (const SoupAddress*) p2;
1578 g_assert(p1 != NULL && p2 != NULL);
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));
1588 * soup_address_noport_equal:
1589 * @p1: Pointer to first SoupAddress.
1590 * @p2: Pointer to second SoupAddress.
1592 * Compare two #SoupAddress's, but does not compare the port numbers.
1594 * Returns: 1 if they are the same; 0 otherwise.
1597 soup_address_noport_equal (const gpointer p1, const gpointer p2)
1599 const SoupAddress* ia1 = (const SoupAddress*) p1;
1600 const SoupAddress* ia2 = (const SoupAddress*) p2;
1602 g_assert (p1 != NULL && p2 != NULL);
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);
1609 #ifndef SOUP_WIN32 /*********** Unix code ***********/
1612 * soup_address_gethostname:
1614 * Get the primary host's name.
1616 * Returns: the name of the host; NULL if there was an error. The
1617 * caller is responsible for deleting the returned string.
1620 soup_address_gethostname (void)
1623 struct utsname myname;
1625 if (uname (&myname) < 0) return NULL;
1627 if (!soup_gethostbyname (myname.nodename, NULL, &name)) return NULL;
1632 #else /*********** Windows code ***********/
1635 soup_address_gethostname (void)
1640 name = g_new0 (char, 256);
1641 error = gethostname (name, 256);
1650 #endif /*********** End Windows code ***********/
1653 * soup_address_gethostaddr:
1655 * Get the primary host's #SoupAddress.
1657 * Returns: the #SoupAddress of the host; NULL if there was an error.
1658 * The caller is responsible for deleting the returned #SoupAddress.
1661 soup_address_gethostaddr (void)
1664 struct sockaddr_in* sa_in, sa;
1665 SoupAddress* ia = NULL;
1667 name = soup_address_gethostname ();
1669 if (name && soup_gethostbyname(name, &sa, NULL)) {
1670 ia = g_new0 (SoupAddress, 1);
1671 ia->name = g_strdup (name);
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);
1685 soup_socket_connect_tcp_cb (SoupSocket* socket,
1686 SoupSocketConnectStatus status,
1689 SoupSocketConnectState* state = (SoupSocketConnectState*) data;
1691 if (status == SOUP_SOCKET_NEW_STATUS_OK)
1692 (*state->func) (socket,
1693 SOUP_SOCKET_CONNECT_ERROR_NONE,
1696 (*state->func) (NULL,
1697 SOUP_SOCKET_CONNECT_ERROR_NETWORK,
1704 soup_socket_connect_inetaddr_cb (SoupAddress* inetaddr,
1705 SoupAddressStatus status,
1708 SoupSocketConnectState* state = (SoupSocketConnectState*) data;
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,
1715 soup_address_unref (inetaddr);
1717 (*state->func) (NULL,
1718 SOUP_SOCKET_CONNECT_ERROR_ADDR_RESOLVE,
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.
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.
1738 * Returns: ID of the connection which can be used with
1739 * soup_socket_connect_cancel() to cancel it; NULL on
1743 soup_socket_connect (const gchar* hostname,
1745 SoupSocketConnectFn func,
1748 SoupSocketConnectState* state;
1751 g_return_val_if_fail (hostname != NULL, NULL);
1752 g_return_val_if_fail (func != NULL, NULL);
1754 state = g_new0 (SoupSocketConnectState, 1);
1758 id = soup_address_new (hostname,
1760 soup_socket_connect_inetaddr_cb,
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. */
1767 if (id == NULL) return NULL;
1769 state->inetaddr_id = id;
1775 * soup_socket_connect_cancel:
1776 * @id: Id of the connection.
1778 * Cancel an asynchronous connection that was started with
1779 * soup_socket_connect().
1782 soup_socket_connect_cancel (SoupSocketConnectId id)
1784 SoupSocketConnectState* state = (SoupSocketConnectState*) id;
1786 g_return_if_fail (state != NULL);
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);
1797 soup_socket_connect_sync_cb (SoupSocket *socket,
1798 SoupSocketConnectStatus status,
1801 SoupSocket **ret = data;
1806 soup_socket_connect_sync (const gchar *name,
1809 SoupSocket *ret = (SoupSocket *) 0xdeadbeef;
1811 soup_socket_connect (name, port, soup_socket_connect_sync_cb, &ret);
1814 g_main_iteration (TRUE);
1815 if (ret != (SoupSocket *) 0xdeadbeef) return ret;
1822 #ifndef SOUP_WIN32 /*********** Unix code ***********/
1825 soup_socket_new_cb (GIOChannel* iochannel,
1826 GIOCondition condition,
1829 SoupSocketState* state = (SoupSocketState*) data;
1832 gint len = sizeof (gint);
1834 /* Remove the watch now in case we don't return immediately */
1835 g_source_remove (state->connect_watch);
1837 if (condition & ~(G_IO_IN | G_IO_OUT)) goto ERROR;
1840 if (getsockopt (state->sockfd,
1844 &len) != 0) goto ERROR;
1846 if (error) goto ERROR;
1848 if (fcntl (state->sockfd, F_SETFL, state->flags) != 0)
1851 s = g_new0 (SoupSocket, 1);
1853 s->sockfd = state->sockfd;
1854 s->addr = state->addr;
1856 (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
1863 soup_address_unref (state->addr);
1864 (*state->func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, state->data);
1872 * @addr: Address to connect to.
1873 * @func: Callback function.
1874 * @data: User data passed when callback function is called.
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.
1881 * Returns: ID of the connection which can be used with
1882 * soup_socket_connect_cancel() to cancel it; NULL on
1886 soup_socket_new (SoupAddress *addr,
1887 SoupSocketNewFn func,
1892 SoupSocketState* state;
1895 g_return_val_if_fail(addr != NULL, NULL);
1896 g_return_val_if_fail(func != NULL, NULL);
1899 sockfd = socket (AF_INET, SOCK_STREAM, 0);
1901 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
1905 /* Get the flags (should all be 0?) */
1906 flags = fcntl (sockfd, F_GETFL, 0);
1908 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
1912 if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1) {
1913 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
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);
1926 /* Unref in soup_socket_new_cb if failure */
1927 soup_address_ref (addr);
1929 /* Connect succeeded, return immediately */
1931 SoupSocket *s = g_new0 (SoupSocket, 1);
1936 (*func) (s, SOUP_SOCKET_NEW_STATUS_OK, data);
1940 chan = SOUP_SOCKET_IOCHANNEL_NEW (sockfd);
1942 /* Wait for the connection */
1943 state = g_new0 (SoupSocketState, 1);
1944 state->sockfd = sockfd;
1948 state->flags = flags;
1949 state->connect_watch = g_io_add_watch (chan,
1950 SOUP_ANY_IO_CONDITION,
1954 g_io_channel_unref (chan);
1959 #else /*********** Windows code ***********/
1962 soup_socket_new_cb (GIOChannel* iochannel,
1963 GIOCondition condition,
1966 SoupSocketState* state = (SoupSocketState*) data;
1969 /* Remove the watch now in case we don't return immediately */
\r
1970 g_source_remove (state->connect_watch);
\r
1972 if (condition & ~(G_IO_IN | G_IO_OUT)) goto _ERROR;
\r
1974 s = g_new0 (SoupSocket, 1);
1976 s->sockfd = state->sockfd;
1977 s->addr = state->addr;
1979 (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
1984 soup_address_unref (state->addr);
\r
1985 (*state->func) ((SoupSocket *) NULL,
\r
1986 SOUP_SOCKET_NEW_STATUS_ERROR,
\r
1994 soup_socket_new (SoupAddress *addr,
1995 SoupSocketNewFn func,
2000 SoupSocketState* state = (SoupSocketState*) data;
\r
2004 g_return_val_if_fail (addr != NULL, NULL);
2005 g_return_val_if_fail (func != NULL, NULL);
2008 sockfd = socket (AF_INET, SOCK_STREAM, 0);
2009 if (sockfd == INVALID_SOCKET) {
2010 (func) (NULL, SOUP_SOCKET_NEW_STATUS_ERROR, data);
2014 /* Set non-blocking mode */
2015 ioctlsocket(sockfd, FIONBIO, &arg);
\r
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);
2027 soup_address_ref (addr);
2029 if (status != SOCKET_ERROR) {
2030 SoupSocket *s = g_new0 (SoupSocket, 1);
2035 (*state->func) (s, SOUP_SOCKET_NEW_STATUS_OK, state->data);
2039 chan = SOUP_SOCKET_IOCHANNEL_NEW (sockfd),
\r
2041 /* Wait for the connection */
2042 state = g_new0 (SoupSocketState, 1);
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
2052 g_io_channel_unref (chan);
\r
2057 #endif /*********** End Windows code ***********/
\r
2060 * soup_socket_new_cancel:
\r
2061 * @id: ID of the connection.
\r
2063 * Cancel an asynchronous connection that was started with
\r
2064 * soup_socket_new().
\r
2067 soup_socket_new_cancel (SoupSocketNewId id)
\r
2069 SoupSocketState* state = (SoupSocketState*) id;
\r
2071 g_source_remove (state->connect_watch);
\r
2072 soup_address_unref (state->addr);
\r
2077 soup_socket_new_sync_cb (SoupSocket* socket,
2078 SoupSocketNewStatus status,
2081 SoupSocket **ret = data;
2086 soup_socket_new_sync (SoupAddress *addr)
2088 SoupSocket *ret = (SoupSocket *) 0xdeadbeef;
2090 soup_socket_new (addr, soup_socket_new_sync_cb, &ret);
2093 g_main_iteration (TRUE);
2094 if (ret != (SoupSocket *) 0xdeadbeef) return ret;
2102 * @s: SoupSocket to reference
2104 * Increment the reference counter of the SoupSocket.
2107 soup_socket_ref (SoupSocket* s)
2109 g_return_if_fail (s != NULL);
2116 * @s: #SoupSocket to unreference
2118 * Remove a reference from the #SoupSocket. When reference count
2119 * reaches 0, the socket is deleted.
2122 soup_socket_unref (SoupSocket* s)
2124 g_return_if_fail(s != NULL);
2128 if (s->ref_count == 0) {
2129 SOUP_CLOSE_SOCKET (s->sockfd);
2131 if (s->addr) soup_address_unref (s->addr);
2133 if (s->iochannel) g_io_channel_unref (s->iochannel);
2140 * soup_socket_get_iochannel:
2141 * @socket: SoupSocket to get GIOChannel from.
2143 * Get the #GIOChannel for the #SoupSocket.
2145 * For a client socket, the #GIOChannel represents the data stream.
2146 * Use it like you would any other #GIOChannel.
2148 * For a server socket however, the #GIOChannel represents incoming
2149 * connections. If you can read from it, there's a connection
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.
2157 * Returns: A #GIOChannel; NULL on failure.
2161 soup_socket_get_iochannel (SoupSocket* socket)
2163 g_return_val_if_fail (socket != NULL, NULL);
2165 if (socket->iochannel == NULL)
2166 socket->iochannel = SOUP_SOCKET_IOCHANNEL_NEW (socket->sockfd);
2168 g_io_channel_ref (socket->iochannel);
2170 return socket->iochannel;
2174 * soup_socket_get_address:
2175 * @socket: #SoupSocket to get address of.
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
2184 * Returns: #SoupAddress of socket; NULL on failure.
2187 soup_socket_get_address (const SoupSocket* socket)
2189 g_return_val_if_fail (socket != NULL, NULL);
2190 g_return_val_if_fail (socket->addr != NULL, NULL);
2192 soup_address_ref (socket->addr);
2194 return socket->addr;
2198 * soup_socket_get_port:
2199 * @socket: SoupSocket to get the port number of.
2201 * Get the port number the socket is bound to.
2203 * Returns: Port number of the socket.
2206 soup_socket_get_port(const SoupSocket* socket)
2208 g_return_val_if_fail (socket != NULL, 0);
2210 return g_ntohs (SOUP_SOCKADDR_IN (socket->addr->sa).sin_port);
2214 * soup_socket_server_new:
2215 * @port: Port number for the socket (SOUP_SERVER_ANY_PORT if you don't care).
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
2222 * Returns: a new #SoupSocket, or NULL if there was a failure.
2225 soup_socket_server_new (const gint port)
2228 struct sockaddr_in* sa_in;
2232 s = g_new0 (SoupSocket, 1);
2235 if ((s->sockfd = socket (AF_INET, SOCK_STREAM, 0)) < 0) {
2240 s->addr = g_new0 (SoupAddress, 1);
2241 s->addr->ref_count = 1;
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);
2249 /* The socket is set to non-blocking mode later in the Windows
2256 /* Set REUSEADDR so we can reuse the port */
2257 if (setsockopt (s->sockfd,
2262 g_warning("Can't set reuse on tcp socket\n");
2264 /* Get the flags (should all be 0?) */
2265 flags = fcntl (s->sockfd, F_GETFL, 0);
2266 if (flags == -1) goto SETUP_ERROR;
2268 /* Make the socket non-blocking */
2269 if (fcntl (s->sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
2275 if (bind (s->sockfd, &s->addr->sa, sizeof (s->addr->sa)) != 0)
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);
2283 if (listen (s->sockfd, 10) != 0) goto SETUP_ERROR;
2294 #ifndef SOUP_WIN32 /*********** Unix code ***********/
2297 * soup_socket_server_accept:
2298 * @socket: #SoupSocket to accept connections from.
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.
2306 * Returns: a new #SoupSocket if there is another connect, or NULL if
2310 soup_socket_server_accept (SoupSocket *socket)
2319 g_return_val_if_fail (socket != NULL, NULL);
2323 FD_SET (socket->sockfd, &fdset);
2325 if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
2326 if (errno == EINTR) goto try_again;
2330 n = sizeof(s->addr->sa);
2332 if ((sockfd = accept (socket->sockfd, &sa, &n)) == -1) {
2333 if (errno == EWOULDBLOCK ||
2334 errno == ECONNABORTED ||
2335 #ifdef EPROTO /* OpenBSD does not have EPROTO */
2344 /* Get the flags (should all be 0?) */
2345 flags = fcntl (sockfd, F_GETFL, 0);
2346 if (flags == -1) return NULL;
2348 /* Make the socket non-blocking */
2349 if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
2352 s = g_new0 (SoupSocket, 1);
2356 s->addr = g_new0 (SoupAddress, 1);
2357 s->addr->ref_count = 1;
2358 memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
2364 * soup_socket_server_try_accept:
2365 * @socket: SoupSocket to accept connections from.
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.
2374 * Returns a new SoupSocket if there is another connect, or NULL
2378 soup_socket_server_try_accept (SoupSocket *socket)
2386 struct timeval tv = {0, 0};
2388 g_return_val_if_fail (socket != NULL, NULL);
2392 FD_SET (socket->sockfd, &fdset);
2394 if (select (socket->sockfd + 1, &fdset, NULL, NULL, &tv) == -1) {
2395 if (errno == EINTR) goto try_again;
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
2408 /* Get the flags (should all be 0?) */
2409 flags = fcntl (sockfd, F_GETFL, 0);
2410 if (flags == -1) return NULL;
2412 /* Make the socket non-blocking */
2413 if (fcntl (sockfd, F_SETFL, flags | O_NONBLOCK) == -1)
2416 s = g_new0 (SoupSocket, 1);
2420 s->addr = g_new0 (SoupAddress, 1);
2421 s->addr->ref_count = 1;
2422 memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
2427 #else /*********** Windows code ***********/
2430 soup_socket_server_accept (SoupSocket *socket)
2439 g_return_val_if_fail (socket != NULL, NULL);
2442 FD_SET ((unsigned)socket->sockfd, &fdset);
2444 if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
2448 /* make sure the socket is in blocking mode */
2451 if (ioctlsocket (socket->sockfd, FIONBIO, &arg))
2454 sockfd = accept (socket->sockfd, &sa, NULL);
2455 /* if it fails, looping isn't going to help */
2457 if (sockfd == INVALID_SOCKET) {
2461 s = g_new0 (SoupSocket, 1);
2465 s->addr = g_new0 (SoupAddress, 1);
2466 s->addr->ref_count = 1;
2467 memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
2473 soup_socket_server_try_accept (SoupSocket *socket)
2482 g_return_val_if_fail (socket != NULL, NULL);
2484 FD_SET ((unsigned)socket->sockfd, &fdset);
2486 if (select (socket->sockfd + 1, &fdset, NULL, NULL, NULL) == -1) {
2489 /* make sure the socket is in non-blocking mode */
2492 if (ioctlsocket (socket->sockfd, FIONBIO, &arg))
2495 sockfd = accept (socket->sockfd, &sa, NULL);
2496 /* if it fails, looping isn't going to help */
2498 if (sockfd == INVALID_SOCKET) {
2502 s = g_new0 (SoupSocket, 1);
2506 s->addr = g_new0 (SoupAddress, 1);
2507 s->addr->ref_count = 1;
2508 memcpy (&s->addr->sa, &sa, sizeof (s->addr->sa));
2512 #endif /*********** End Windows code ***********/
2514 #ifdef SOUP_WIN32 /*********** Windows code ***********/
2516 soup_MainCallBack (GIOChannel *iochannel,
2517 GIOCondition condition,
2523 SoupAddressState *IAstate;
2524 SoupAddressReverseState *IARstate;
2526 /*Take the msg off the message queue */
2527 PeekMessage (&msg, soup_hWnd, 0, 0, PM_REMOVE);
2529 switch (msg.message) {
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);
2536 IAstate = (SoupAddressState*) data;
2538 IAstate->errorcode = WSAGETASYNCERROR(msg.lParam);
2540 /* Now call the callback function */
2541 soup_address_new_cb (NULL, G_IO_IN, (gpointer) IAstate);
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);
2550 IARstate = (SoupAddressReverseState*) data;
2552 IARstate->errorcode = WSAGETASYNCERROR(msg.lParam);
2554 /* Now call the callback function */
2555 soup_address_get_name_cb (NULL,
2557 (gpointer) IARstate);
2565 SoupWndProc (HWND hwnd, /* handle to window */
2566 UINT uMsg, /* message identifier */
2567 WPARAM wParam, /* first message parameter */
2568 LPARAM lParam) /* second message parameter */
2571 case WM_CREATE: /* Initialize the window. */
2573 case WM_PAINT: /* Paint the window's client area. */
2575 case WM_SIZE: /* Set the size and position of the window. */
2577 case WM_DESTROY: /* Clean up window-specific data objects. */
2581 return DefWindowProc (hwnd, uMsg, wParam, lParam);
2586 DllMain (HINSTANCE hinstDLL, /* handle to DLL module */
2587 DWORD fdwReason, /* reason for calling functionm */
2588 LPVOID lpvReserved /* reserved */)
2590 WORD wVersionRequested;
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);
2601 err = WSAStartup (wVersionRequested, &wsaData);
2603 /* Tell the user that we could not find a usable
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 */
2614 if (LOBYTE(wsaData.wVersion) != 2 ||
2615 HIBYTE(wsaData.wVersion) != 0) {
2616 /* Tell the user that we could not find a usable */
2622 /* The WinSock DLL is acceptable. Proceed. */
2624 /* Setup and register a windows class that we use for out
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;
2639 if (!RegisterClassEx (&soupWndClass)) return FALSE;
2641 soup_hWnd = CreateWindowEx (0,
2644 WS_OVERLAPPEDWINDOW,
2654 if (!soup_hWnd) return FALSE;
2657 g_io_channel_win32_new_messages (
2658 (unsigned int) soup_hWnd);
2662 g_io_add_watch (soup_iochannel,
2663 G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL,
2667 soup_hash = g_hash_table_new (NULL, NULL);
2669 soup_Mutex = CreateMutex (NULL, FALSE, "soup_Mutex");
2670 if (soup_Mutex == NULL) return FALSE;
2672 soup_hostent_Mutex = CreateMutex (NULL,
2674 "soup_hostent_Mutex");
2675 if (soup_hostent_Mutex == NULL) return FALSE;
2678 case DLL_THREAD_ATTACH:
2680 case DLL_THREAD_DETACH:
2682 case DLL_PROCESS_DETACH:
2683 /* The DLL unmapped from process's address space. Do necessary
2685 g_source_remove (soup_io_watch_ID);
2686 g_free (soup_iochannel);
2687 DestroyWindow (soup_hWnd);
2697 #endif /*********** End Windows code ***********/