125eaca8bcce741686bc220180553cb6896476b6
[oweals/gnunet.git] / src / util / network.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009, 2012 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/network.c
23  * @brief basic, low-level networking interface
24  * @author Nils Durner
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "disk.h"
29 #include "gnunet_util_lib.h"
30
31 #define LOG(kind,...) GNUNET_log_from (kind, "util", __VA_ARGS__)
32 #define LOG_STRERROR_FILE(kind,syscall,filename) GNUNET_log_from_strerror_file (kind, "util", syscall, filename)
33 #define LOG_STRERROR(kind,syscall) GNUNET_log_from_strerror (kind, "util", syscall)
34
35 #define DEBUG_NETWORK GNUNET_EXTRA_LOGGING
36
37
38 #ifndef INVALID_SOCKET
39 #define INVALID_SOCKET -1
40 #endif
41
42
43 struct GNUNET_NETWORK_Handle
44 {
45 #ifndef MINGW
46   int fd;
47 #else
48   SOCKET fd;
49 #endif
50
51   /**
52    * Address family / domain.
53    */
54   int af;
55
56   /**
57    * Number of bytes in addr.
58    */
59   socklen_t addrlen;
60
61   /**
62    * Address we were bound to, or NULL.
63    */
64   struct sockaddr *addr;
65
66 };
67
68
69 /**
70  * Test if the given protocol family is supported by this system.
71  *
72  * @param pf protocol family to test (PF_INET, PF_INET6, PF_UNIX)
73  * @return GNUNET_OK if the PF is supported
74  */
75 int
76 GNUNET_NETWORK_test_pf (int pf)
77 {
78   int s;
79
80   s = socket (pf, SOCK_STREAM, 0);
81   if (-1 == s)
82   {
83     if (EAFNOSUPPORT == errno)
84       return GNUNET_NO;
85     fprintf (stderr, "Failed to create test socket: %s\n", STRERROR (errno));
86     return GNUNET_SYSERR;
87   }
88 #if WINDOWS
89   closesocket (s);
90 #else
91   close (s);
92 #endif
93   return GNUNET_OK;
94 }
95
96
97 /**
98  * Given a unixpath that is too long (larger than UNIX_PATH_MAX),
99  * shorten it to an acceptable length while keeping it unique
100  * and making sure it remains a valid filename (if possible).
101  *
102  * @param unixpath long path, will be freed (or same pointer returned
103  *        with moved 0-termination).
104  * @return shortened unixpath, NULL on error
105  */
106 char *
107 GNUNET_NETWORK_shorten_unixpath (char *unixpath)
108 {
109   struct sockaddr_un dummy;
110   size_t slen;
111   char *end;
112   struct GNUNET_CRYPTO_ShortHashCode sh;
113   struct GNUNET_CRYPTO_ShortHashAsciiEncoded ae;
114   size_t upm;
115
116   upm = sizeof (dummy.sun_path);   
117   slen = strlen (unixpath);
118   if (slen < upm)
119     return unixpath; /* no shortening required */
120   GNUNET_CRYPTO_short_hash (unixpath, slen, &sh);
121   while (sizeof (struct GNUNET_CRYPTO_ShortHashAsciiEncoded) + 
122          strlen (unixpath) >= upm)
123   {
124     if (NULL == (end = strrchr (unixpath, '/')))
125     {
126       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
127                   _("Unable to shorten unix path `%s' while keeping name unique\n"),
128                   unixpath);
129       GNUNET_free (unixpath);
130       return NULL;
131     }
132     *end = '\0';
133   }
134   GNUNET_CRYPTO_short_hash_to_enc (&sh, &ae);
135   strcat (unixpath, (char*) ae.short_encoding);
136   return unixpath;
137 }
138
139
140 #ifndef FD_COPY
141 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
142 #endif
143
144
145 /**
146  * Set if a socket should use blocking or non-blocking IO.
147  * @param fd socket
148  * @param doBlock blocking mode
149  * @return GNUNET_OK on success, GNUNET_SYSERR on error
150  */
151 static int
152 socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
153 {
154
155 #if MINGW
156   u_long mode;
157
158   mode = !doBlock;
159   if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
160
161   {
162     SetErrnoFromWinsockError (WSAGetLastError ());
163     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
164     return GNUNET_SYSERR;
165   }
166   return GNUNET_OK;
167
168 #else
169   /* not MINGW */
170   int flags = fcntl (fd->fd, F_GETFL);
171
172   if (flags == -1)
173
174   {
175     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
176     return GNUNET_SYSERR;
177   }
178   if (doBlock)
179     flags &= ~O_NONBLOCK;
180
181   else
182     flags |= O_NONBLOCK;
183   if (0 != fcntl (fd->fd, F_SETFL, flags))
184
185   {
186     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "fcntl");
187     return GNUNET_SYSERR;
188   }
189   return GNUNET_OK;
190 #endif
191 }
192
193
194 /**
195  * Make a socket non-inheritable to child processes
196  *
197  * @param h the socket to make non-inheritable
198  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
199  * @warning Not implemented on Windows
200  */
201 static int
202 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
203 {
204 #ifndef MINGW
205   int i;
206   i = fcntl (h->fd, F_GETFD);
207   if (i < 0)
208     return GNUNET_SYSERR;
209   if (i == (i | FD_CLOEXEC))
210     return GNUNET_OK;
211   i |= FD_CLOEXEC;
212   if (fcntl (h->fd, F_SETFD, i) < 0)
213     return GNUNET_SYSERR;
214 #else
215   BOOL b;
216   SetLastError (0);
217   b = SetHandleInformation (h->fd, HANDLE_FLAG_INHERIT, 0);
218   if (!b)
219   {
220     SetErrnoFromWinsockError (WSAGetLastError ());
221     return GNUNET_SYSERR;
222   }
223 #endif
224   return GNUNET_OK;
225 }
226
227
228 #ifdef DARWIN
229 /**
230  * The MSG_NOSIGNAL equivalent on Mac OS X
231  *
232  * @param h the socket to make non-delaying
233  */
234 static void
235 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
236 {
237   int abs_value = 1;
238
239   if (0 !=
240       setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value,
241                   sizeof (abs_value)))
242     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
243 }
244 #endif
245
246
247 /**
248  * Disable delays when sending data via the socket.
249  * (GNUnet makes sure that messages are as big as
250  * possible already).
251  *
252  * @param h the socket to make non-delaying
253  */
254 static void
255 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
256 {
257 #ifndef WINDOWS
258   int value = 1;
259
260   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
261     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
262 #else
263   const char *abs_value = "1";
264
265   if (0 !=
266       setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value,
267                   sizeof (abs_value)))
268     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
269 #endif
270 }
271
272
273 /**
274  * Perform proper canonical initialization for a network handle.
275  * Set it to non-blocking, make it non-inheritable to child
276  * processes, disable SIGPIPE, enable "nodelay" (if non-UNIX
277  * stream socket) and check that it is smaller than FS_SETSIZE.
278  *
279  * @param h socket to initialize
280  * @param af address family of the socket
281  * @param type socket type
282  * @return GNUNET_OK on success, GNUNET_SYSERR if initialization
283  *         failed and the handle was destroyed
284  */
285 static int
286 initialize_network_handle (struct GNUNET_NETWORK_Handle *h,
287                            int af, int type)
288 {
289   h->af = af;
290   if (h->fd == INVALID_SOCKET)
291   {
292 #ifdef MINGW
293     SetErrnoFromWinsockError (WSAGetLastError ());
294 #endif
295     GNUNET_free (h);
296     return GNUNET_SYSERR;
297   }
298 #ifndef MINGW
299   if (h->fd >= FD_SETSIZE)
300   {
301     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
302     errno = EMFILE;
303     return GNUNET_SYSERR;
304   }
305 #endif
306   if (GNUNET_OK != socket_set_inheritable (h))
307     LOG_STRERROR (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
308                   "socket_set_inheritable");
309
310   if (GNUNET_SYSERR == socket_set_blocking (h, GNUNET_NO))
311   {
312     GNUNET_break (0);
313     GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (h));
314     return GNUNET_SYSERR;
315   }
316 #ifdef DARWIN
317   socket_set_nosigpipe (h);
318 #endif
319   if ( (type == SOCK_STREAM) 
320 #ifdef AF_UNIX
321        && (af != AF_UNIX)
322 #endif
323        )
324     socket_set_nodelay (h);
325   return GNUNET_OK;
326 }
327
328
329 /**
330  * accept a new connection on a socket
331  *
332  * @param desc bound socket
333  * @param address address of the connecting peer, may be NULL
334  * @param address_len length of address
335  * @return client socket
336  */
337 struct GNUNET_NETWORK_Handle *
338 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
339                               struct sockaddr *address, socklen_t * address_len)
340 {
341   struct GNUNET_NETWORK_Handle *ret;
342
343   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
344 #if DEBUG_NETWORK
345   {
346     struct sockaddr name;
347     socklen_t namelen = sizeof (name);
348     int gsn = getsockname (desc->fd, &name, &namelen);
349
350     if (gsn == 0)
351       LOG (GNUNET_ERROR_TYPE_DEBUG, "Accepting connection on `%s'\n",
352            GNUNET_a2s (&name, namelen));
353   }
354 #endif
355   ret->fd = accept (desc->fd, address, address_len);
356   if (GNUNET_OK != initialize_network_handle (ret,
357                                               (NULL != address) ? address->sa_family : desc->af,
358                                               SOCK_STREAM))
359     return NULL;
360   return ret;
361 }
362
363
364 /**
365  * Bind to a connected socket
366  * @param desc socket
367  * @param address address to be bound
368  * @param address_len length of address
369  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
370  */
371 int
372 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
373                             const struct sockaddr *address,
374                             socklen_t address_len)
375 {
376   int ret;
377
378 #ifdef IPV6_V6ONLY
379 #ifdef IPPROTO_IPV6
380   const int on = 1;
381
382   if (desc->af == AF_INET6)
383     if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
384       LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
385 #endif
386 #endif
387 #ifndef WINDOWS
388   /* This is required, and required here, but only on UNIX */
389   if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
390     LOG_STRERROR (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
391 #endif
392 #ifndef LINUX
393 #ifndef MINGW
394   if (address->sa_family == AF_UNIX)
395   {
396     const struct sockaddr_un *un = (const struct sockaddr_un *) address;
397
398     (void) unlink (un->sun_path);
399   }
400 #endif
401 #endif
402   ret = bind (desc->fd, address, address_len);
403 #ifdef MINGW
404   if (SOCKET_ERROR == ret)
405     SetErrnoFromWinsockError (WSAGetLastError ());
406 #endif
407   if (ret != 0)
408     return GNUNET_SYSERR;
409 #ifndef MINGW
410 #ifndef LINUX
411   desc->addr = GNUNET_malloc (address_len);
412   memcpy (desc->addr, address, address_len);
413   desc->addrlen = address_len;
414 #endif
415 #endif
416   return GNUNET_OK;
417 }
418
419
420 /**
421  * Close a socket
422  * @param desc socket
423  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
424  */
425 int
426 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
427 {
428   int ret;
429
430 #ifdef MINGW
431   DWORD error = 0;
432
433   SetLastError (0);
434   ret = closesocket (desc->fd);
435   error = WSAGetLastError ();
436   SetErrnoFromWinsockError (error);
437   LOG (GNUNET_ERROR_TYPE_DEBUG,
438        "Closed 0x%x, closesocket() returned %d, GLE is %u\n", desc->fd, ret,
439        error);
440 #else
441   ret = close (desc->fd);
442 #endif
443 #ifndef LINUX
444 #ifndef MINGW
445   if ((desc->af == AF_UNIX) && (NULL != desc->addr))
446   {
447     const struct sockaddr_un *un = (const struct sockaddr_un *) desc->addr;
448
449     if (0 != unlink (un->sun_path))
450       LOG_STRERROR_FILE (GNUNET_ERROR_TYPE_WARNING, "unlink", un->sun_path);
451   }
452 #endif
453 #endif
454   GNUNET_free_non_null (desc->addr);
455   GNUNET_free (desc);
456   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
457 }
458
459
460 /**
461  * Box a native socket (and check that it is a socket).
462  *
463  * @param fd socket to box
464  * @return NULL on error (including not supported on target platform)
465  */
466 struct GNUNET_NETWORK_Handle *
467 GNUNET_NETWORK_socket_box_native (SOCKTYPE fd)
468 {
469   struct GNUNET_NETWORK_Handle *ret;
470 #if MINGW
471   unsigned long i;
472   DWORD d;
473   /* FIXME: Find a better call to check that FD is valid */
474   if (WSAIoctl (fd, FIONBIO, (void *) &i, sizeof (i), NULL, 0, &d, NULL, NULL) != 0)
475     return NULL;                /* invalid FD */
476   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
477   ret->fd = fd;
478   ret->af = AF_UNSPEC;
479   return ret;
480 #else
481   if (fcntl (fd, F_GETFD) < 0)
482     return NULL;                /* invalid FD */
483   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
484   ret->fd = fd;
485   ret->af = AF_UNSPEC;
486   return ret;
487 #endif
488 }
489
490
491 /**
492  * Connect a socket
493  * @param desc socket
494  * @param address peer address
495  * @param address_len length of address
496  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
497  */
498 int
499 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
500                                const struct sockaddr *address,
501                                socklen_t address_len)
502 {
503   int ret;
504
505   ret = connect (desc->fd, address, address_len);
506
507 #ifdef MINGW
508   if (SOCKET_ERROR == ret)
509   {
510     SetErrnoFromWinsockError (WSAGetLastError ());
511     if (errno == EWOULDBLOCK)
512       errno = EINPROGRESS;
513   }
514 #endif
515   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
516 }
517
518
519 /**
520  * Get socket options
521  *
522  * @param desc socket
523  * @param level protocol level of the option
524  * @param optname identifier of the option
525  * @param optval options
526  * @param optlen length of optval
527  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
528  */
529 int
530 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
531                                   int level, int optname, void *optval,
532                                   socklen_t * optlen)
533 {
534   int ret;
535
536   ret = getsockopt (desc->fd, level, optname, optval, optlen);
537
538 #ifdef MINGW
539   if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
540     *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
541
542   else if (SOCKET_ERROR == ret)
543     SetErrnoFromWinsockError (WSAGetLastError ());
544 #endif
545   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
546 }
547
548
549 /**
550  * Listen on a socket
551  * @param desc socket
552  * @param backlog length of the listen queue
553  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
554  */
555 int
556 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
557                               int backlog)
558 {
559   int ret;
560
561   ret = listen (desc->fd, backlog);
562
563 #ifdef MINGW
564   if (SOCKET_ERROR == ret)
565     SetErrnoFromWinsockError (WSAGetLastError ());
566
567 #endif
568   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
569 }
570
571
572 /**
573  * How much data is available to be read on this descriptor?
574  *
575  * Returns GNUNET_NO if no data is available, or on error!
576  * @param desc socket
577  */
578 ssize_t
579 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle *
580                                        desc)
581 {
582   int error;
583
584   /* How much is there to be read? */
585 #ifndef WINDOWS
586   int pending;
587
588   error = ioctl (desc->fd, FIONREAD, &pending);
589   if (error == 0)
590     return (ssize_t) pending;
591   return GNUNET_NO;
592 #else
593   u_long pending;
594
595   error = ioctlsocket (desc->fd, FIONREAD, &pending);
596   if (error != SOCKET_ERROR)
597     return (ssize_t) pending;
598   return GNUNET_NO;
599 #endif
600 }
601
602
603 /**
604  * Read data from a connected socket (always non-blocking).
605  * @param desc socket
606  * @param buffer buffer
607  * @param length length of buffer
608  * @param src_addr either the source to recv from, or all zeroes
609  *        to be filled in by recvfrom
610  * @param addrlen length of the addr
611  */
612 ssize_t
613 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
614                                 void *buffer, size_t length,
615                                 struct sockaddr * src_addr, socklen_t * addrlen)
616 {
617   int ret;
618   int flags;
619
620   flags = 0;
621
622 #ifdef MSG_DONTWAIT
623   flags |= MSG_DONTWAIT;
624
625 #endif
626   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
627 #ifdef MINGW
628   if (SOCKET_ERROR == ret)
629     SetErrnoFromWinsockError (WSAGetLastError ());
630 #endif
631   return ret;
632 }
633
634
635 /**
636  * Read data from a connected socket (always non-blocking).
637  * @param desc socket
638  * @param buffer buffer
639  * @param length length of buffer
640  */
641 ssize_t
642 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
643                             void *buffer, size_t length)
644 {
645   int ret;
646   int flags;
647
648   flags = 0;
649
650 #ifdef MSG_DONTWAIT
651   flags |= MSG_DONTWAIT;
652 #endif
653   ret = recv (desc->fd, buffer, length, flags);
654 #ifdef MINGW
655   if (SOCKET_ERROR == ret)
656     SetErrnoFromWinsockError (WSAGetLastError ());
657 #endif
658   return ret;
659 }
660
661
662 /**
663  * Send data (always non-blocking).
664  *
665  * @param desc socket
666  * @param buffer data to send
667  * @param length size of the buffer
668  * @return number of bytes sent, GNUNET_SYSERR on error
669  */
670 ssize_t
671 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
672                             const void *buffer, size_t length)
673 {
674   int ret;
675   int flags;
676
677   flags = 0;
678
679 #ifdef MSG_DONTWAIT
680   flags |= MSG_DONTWAIT;
681
682 #endif
683 #ifdef MSG_NOSIGNAL
684   flags |= MSG_NOSIGNAL;
685
686 #endif
687   ret = send (desc->fd, buffer, length, flags);
688
689 #ifdef MINGW
690   if (SOCKET_ERROR == ret)
691     SetErrnoFromWinsockError (WSAGetLastError ());
692
693 #endif
694   return ret;
695 }
696
697
698 /**
699  * Send data to a particular destination (always non-blocking).
700  * This function only works for UDP sockets.
701  *
702  * @param desc socket
703  * @param message data to send
704  * @param length size of the data
705  * @param dest_addr destination address
706  * @param dest_len length of address
707  * @return number of bytes sent, GNUNET_SYSERR on error
708  */
709 ssize_t
710 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
711                               const void *message, size_t length,
712                               const struct sockaddr * dest_addr,
713                               socklen_t dest_len)
714 {
715   int ret;
716   int flags;
717
718   flags = 0;
719
720 #ifdef MSG_DONTWAIT
721   flags |= MSG_DONTWAIT;
722 #endif
723 #ifdef MSG_NOSIGNAL
724   flags |= MSG_NOSIGNAL;
725 #endif
726   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
727 #ifdef MINGW
728   if (SOCKET_ERROR == ret)
729     SetErrnoFromWinsockError (WSAGetLastError ());
730 #endif
731   return ret;
732 }
733
734
735 /**
736  * Set socket option
737  * @param fd socket
738  * @param level protocol level of the option
739  * @param option_name option identifier
740  * @param option_value value to set
741  * @param option_len size of option_value
742  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
743  */
744 int
745 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd, int level,
746                                   int option_name, const void *option_value,
747                                   socklen_t option_len)
748 {
749   int ret;
750
751   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
752 #ifdef MINGW
753   if (SOCKET_ERROR == ret)
754     SetErrnoFromWinsockError (WSAGetLastError ());
755 #endif
756   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
757 }
758
759
760 /**
761  * Create a new socket.  Configure it for non-blocking IO and
762  * mark it as non-inheritable to child processes (set the
763  * close-on-exec flag).
764  *
765  * @param domain domain of the socket
766  * @param type socket type
767  * @param protocol network protocol
768  * @return new socket, NULL on error
769  */
770 struct GNUNET_NETWORK_Handle *
771 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
772 {
773   struct GNUNET_NETWORK_Handle *ret;
774
775   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
776   ret->fd = socket (domain, type, protocol);
777   if (GNUNET_OK !=
778       initialize_network_handle (ret, domain, type))
779     return NULL;
780   return ret;
781 }
782
783
784 /**
785  * Shut down socket operations
786  * @param desc socket
787  * @param how type of shutdown
788  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
789  */
790 int
791 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
792 {
793   int ret;
794
795   ret = shutdown (desc->fd, how);
796 #ifdef MINGW
797   if (ret != 0)
798     SetErrnoFromWinsockError (WSAGetLastError ());
799 #endif
800   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
801 }
802
803
804 /**
805  * Disable the "CORK" feature for communication with the given socket,
806  * forcing the OS to immediately flush the buffer on transmission
807  * instead of potentially buffering multiple messages.  Essentially
808  * reduces the OS send buffers to zero.
809  *
810  * @param desc socket
811  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
812  */
813 int
814 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
815 {
816   int ret = 0;
817
818 #if WINDOWS
819   int value = 0;
820
821   if (0 !=
822       (ret =
823        setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, (char *) &value,
824                    sizeof (value))))
825     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
826   if (0 !=
827       (ret =
828        setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, (char *) &value,
829                    sizeof (value))))
830     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
831 #elif LINUX
832   int value = 0;
833
834   if (0 !=
835       (ret =
836        setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
837     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
838   if (0 !=
839       (ret =
840        setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
841     LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
842 #endif
843   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
844 }
845
846
847 /**
848  * Reset FD set
849  * @param fds fd set
850  */
851 void
852 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
853 {
854   FD_ZERO (&fds->sds);
855   fds->nsds = 0;
856 #ifdef MINGW
857   GNUNET_CONTAINER_slist_clear (fds->handles);
858 #endif
859 }
860
861 /**
862  * Add a socket to the FD set
863  * @param fds fd set
864  * @param desc socket to add
865  */
866 void
867 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
868                           const struct GNUNET_NETWORK_Handle *desc)
869 {
870   FD_SET (desc->fd, &fds->sds);
871   if (desc->fd + 1 > fds->nsds)
872     fds->nsds = desc->fd + 1;
873 }
874
875
876 /**
877  * Check whether a socket is part of the fd set
878  * @param fds fd set
879  * @param desc socket
880  * @return 0 if the FD is not set
881  */
882 int
883 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
884                             const struct GNUNET_NETWORK_Handle *desc)
885 {
886   return FD_ISSET (desc->fd, &fds->sds);
887 }
888
889
890 /**
891  * Add one fd set to another
892  * @param dst the fd set to add to
893  * @param src the fd set to add from
894  */
895 void
896 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
897                           const struct GNUNET_NETWORK_FDSet *src)
898 {
899 #ifndef MINGW
900   int nfds;
901
902   for (nfds = src->nsds; nfds > 0; nfds--)
903     if (FD_ISSET (nfds, &src->sds))
904
905     {
906       FD_SET (nfds, &dst->sds);
907       if (nfds + 1 > dst->nsds)
908         dst->nsds = nfds + 1;
909     }
910 #else
911   /* This is MinGW32-specific implementation that relies on the code that
912    * winsock2.h defines for FD_SET. Namely, it relies on FD_SET checking
913    * that fd being added is not already in the set.
914    * Also relies on us knowing what's inside fd_set (fd_count and fd_array).
915    */
916   int i;
917   for (i = 0; i < src->sds.fd_count; i++)
918     FD_SET (src->sds.fd_array[i], &dst->sds);
919   if (src->nsds > dst->nsds)
920     dst->nsds = src->nsds;
921
922   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
923 #endif
924 }
925
926
927 /**
928  * Copy one fd set to another
929  *
930  * @param to destination
931  * @param from source
932  */
933 void
934 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
935                            const struct GNUNET_NETWORK_FDSet *from)
936 {
937   FD_COPY (&from->sds, &to->sds);
938   to->nsds = from->nsds;
939
940 #ifdef MINGW
941   GNUNET_CONTAINER_slist_clear (to->handles);
942   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
943 #endif
944 }
945
946
947 /**
948  * Return file descriptor for this network handle
949  *
950  * @param desc wrapper to process
951  * @return POSIX file descriptor
952  */
953 int
954 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
955 {
956   return desc->fd;
957 }
958
959 /**
960  * Return sockaddr for this network handle
961  *
962  * @param desc wrapper to process
963  * @return sockaddr
964  */
965 struct sockaddr*
966 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
967 {
968   return desc->addr;
969 }
970
971 /**
972  * Return sockaddr length for this network handle
973  *
974  * @param desc wrapper to process
975  * @return socklen_t for sockaddr
976  */
977 socklen_t
978 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
979 {
980   return desc->addrlen;
981 }
982 /**
983  * Copy a native fd set
984  *
985  * @param to destination
986  * @param from native source set
987  * @param nfds the biggest socket number in from + 1
988  */
989 void
990 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
991                                   const fd_set * from, int nfds)
992 {
993   FD_COPY (from, &to->sds);
994   to->nsds = nfds;
995 }
996
997
998 /**
999  * Set a native fd in a set
1000  *
1001  * @param to destination
1002  * @param nfd native FD to set
1003  */
1004 void
1005 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
1006 {
1007   GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
1008   FD_SET (nfd, &to->sds);
1009   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
1010 }
1011
1012
1013 /**
1014  * Test native fd in a set
1015  *
1016  * @param to set to test, NULL for empty set
1017  * @param nfd native FD to test, or -1 for none
1018  * @return GNUNET_YES if FD is set in the set
1019  */
1020 int
1021 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1022                                   int nfd)
1023 {
1024   if ((nfd == -1) || (to == NULL))
1025     return GNUNET_NO;
1026   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1027 }
1028
1029
1030 /**
1031  * Add a file handle to the fd set
1032  * @param fds fd set
1033  * @param h the file handle to add
1034  */
1035 void
1036 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1037                                  const struct GNUNET_DISK_FileHandle *h)
1038 {
1039 #ifdef MINGW
1040   GNUNET_CONTAINER_slist_add (fds->handles,
1041                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1042                               sizeof (struct GNUNET_DISK_FileHandle));
1043
1044 #else
1045   int fd;
1046
1047   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1048   FD_SET (fd, &fds->sds);
1049   if (fd + 1 > fds->nsds)
1050     fds->nsds = fd + 1;
1051
1052 #endif
1053 }
1054
1055
1056 /**
1057  * Check if a file handle is part of an fd set
1058  * @param fds fd set
1059  * @param h file handle
1060  * @return GNUNET_YES if the file handle is part of the set
1061  */
1062 int
1063 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1064                                    const struct GNUNET_DISK_FileHandle *h)
1065 {
1066
1067 #ifdef MINGW
1068   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1069                                           sizeof (struct
1070                                                   GNUNET_DISK_FileHandle));
1071 #else
1072   return FD_ISSET (h->fd, &fds->sds);
1073 #endif
1074 }
1075
1076
1077 /**
1078  * Checks if two fd sets overlap
1079  * @param fds1 first fd set
1080  * @param fds2 second fd set
1081  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1082  */
1083 int
1084 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1085                               const struct GNUNET_NETWORK_FDSet *fds2)
1086 {
1087 #ifndef MINGW
1088   int nfds;
1089
1090   nfds = fds1->nsds;
1091   if (nfds > fds2->nsds)
1092     nfds = fds2->nsds;
1093   while (nfds > 0)
1094   {
1095     nfds--;
1096     if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1097       return GNUNET_YES;
1098   }
1099 #else
1100   struct GNUNET_CONTAINER_SList_Iterator it;
1101   struct GNUNET_DISK_FileHandle *h;
1102   int i;
1103   int j;
1104
1105   /*This code is somewhat hacky, we are not supposed to know what's
1106    * inside of fd_set; also the O(n^2) is really bad... */
1107
1108   for (i = 0; i < fds1->sds.fd_count; i++)
1109   {
1110     for (j = 0; j < fds2->sds.fd_count; j++)
1111     {
1112       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1113         return GNUNET_YES;
1114     }
1115   }
1116   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1117   while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1118   {
1119 #if DEBUG_NETWORK
1120     struct GNUNET_CONTAINER_SList_Iterator t;
1121 #endif
1122     h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1123                                                                       NULL);
1124 #if DEBUG_NETWORK
1125     LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1126          h->h);
1127     for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1128          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1129          GNUNET_CONTAINER_slist_next (&t))
1130     {
1131       struct GNUNET_DISK_FileHandle *fh;
1132
1133       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1134                                                                          NULL);
1135       LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1136     }
1137 #endif
1138     if (GNUNET_CONTAINER_slist_contains
1139         (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1140     {
1141       return GNUNET_YES;
1142     }
1143     GNUNET_CONTAINER_slist_next (&it);
1144   }
1145 #endif
1146   return GNUNET_NO;
1147 }
1148
1149
1150 /**
1151  * Creates an fd set
1152  * @return a new fd set
1153  */
1154 struct GNUNET_NETWORK_FDSet *
1155 GNUNET_NETWORK_fdset_create ()
1156 {
1157   struct GNUNET_NETWORK_FDSet *fds;
1158
1159   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1160 #ifdef MINGW
1161   fds->handles = GNUNET_CONTAINER_slist_create ();
1162 #endif
1163   GNUNET_NETWORK_fdset_zero (fds);
1164   return fds;
1165 }
1166
1167
1168 /**
1169  * Releases the associated memory of an fd set
1170  * @param fds fd set
1171  */
1172 void
1173 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1174 {
1175 #ifdef MINGW
1176   GNUNET_CONTAINER_slist_destroy (fds->handles);
1177 #endif
1178   GNUNET_free (fds);
1179 }
1180
1181 #if MINGW
1182 struct _select_params
1183 {
1184   fd_set *r;
1185   fd_set *w;
1186   fd_set *e;
1187   struct timeval *tv;
1188   HANDLE wakeup;
1189   HANDLE standby;
1190   SOCKET wakeup_socket;
1191   int status;
1192 };
1193
1194 static DWORD WINAPI
1195 _selector (LPVOID p)
1196 {
1197   struct _select_params *sp = p;
1198   int i;
1199   while (1)
1200   {
1201     WaitForSingleObject (sp->standby, INFINITE);
1202     ResetEvent (sp->standby);
1203     sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1204     if (FD_ISSET (sp->wakeup_socket, sp->r))
1205     {
1206       FD_CLR (sp->wakeup_socket, sp->r);
1207       sp->status -= 1;
1208     }
1209     SetEvent (sp->wakeup);
1210   }
1211   return 0;
1212 }
1213 #endif
1214
1215 /**
1216  * Check if sockets or pipes meet certain conditions
1217  * @param rfds set of sockets or pipes to be checked for readability
1218  * @param wfds set of sockets or pipes to be checked for writability
1219  * @param efds set of sockets or pipes to be checked for exceptions
1220  * @param timeout relative value when to return
1221  * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1222  */
1223 int
1224 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1225                               struct GNUNET_NETWORK_FDSet *wfds,
1226                               struct GNUNET_NETWORK_FDSet *efds,
1227                               const struct GNUNET_TIME_Relative timeout)
1228 {
1229   int nfds = 0;
1230 #ifdef MINGW
1231   int handles = 0;
1232   int ex_handles = 0;
1233   int read_handles = 0;
1234   int write_handles = 0;
1235
1236   int i = 0;
1237   int retcode = 0;
1238   DWORD ms_total = 0;
1239
1240   int nhandles = 0;
1241
1242   static HANDLE hEventPipeWrite = 0;
1243   static HANDLE hEventReadReady = 0;
1244
1245   static struct _select_params sp;
1246   static HANDLE select_thread = NULL;
1247   static HANDLE select_finished_event = NULL;
1248   static HANDLE select_standby_event = NULL;
1249   static SOCKET select_wakeup_socket = -1;
1250   static SOCKET select_send_socket = -1;
1251   static struct timeval select_timeout;
1252
1253   int readPipes = 0;
1254   int writePipePos = 0;
1255
1256   HANDLE handle_array[FD_SETSIZE + 2];
1257   int returncode = -1;
1258   int returnedpos = 0;
1259
1260   struct GNUNET_CONTAINER_SList *handles_read;
1261   struct GNUNET_CONTAINER_SList *handles_write;
1262   struct GNUNET_CONTAINER_SList *handles_except;
1263
1264   int selectret = 0;
1265
1266   fd_set aread;
1267   fd_set awrite;
1268   fd_set aexcept;
1269
1270 #if DEBUG_NETWORK
1271   fd_set bread;
1272   fd_set bwrite;
1273   fd_set bexcept;
1274 #endif
1275
1276   /* TODO: Make this growable */
1277   struct GNUNET_DISK_FileHandle *readArray[50];
1278 #else
1279   struct timeval tv;
1280 #endif
1281   if (NULL != rfds)
1282   {
1283     nfds = rfds->nsds;
1284 #ifdef MINGW
1285     handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1286 #if DEBUG_NETWORK
1287     {
1288       struct GNUNET_CONTAINER_SList_Iterator t;
1289
1290       for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1291            GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1292            GNUNET_CONTAINER_slist_next (&t))
1293       {
1294         struct GNUNET_DISK_FileHandle *fh;
1295
1296         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1297                                                                            NULL);
1298         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1299              fh);
1300       }
1301     }
1302 #endif
1303 #endif
1304   }
1305   if (NULL != wfds)
1306   {
1307     nfds = GNUNET_MAX (nfds, wfds->nsds);
1308 #ifdef MINGW
1309     handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1310 #endif
1311   }
1312   if (NULL != efds)
1313   {
1314     nfds = GNUNET_MAX (nfds, efds->nsds);
1315 #ifdef MINGW
1316     handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1317 #endif
1318   }
1319
1320   if ((nfds == 0) &&
1321       (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1322 #ifdef MINGW
1323       && handles == 0
1324 #endif
1325       )
1326   {
1327     GNUNET_break (0);
1328     LOG (GNUNET_ERROR_TYPE_ERROR,
1329          _
1330          ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1331          "select");
1332   }
1333 #ifndef MINGW
1334   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1335   tv.tv_usec =
1336       1000 * (timeout.rel_value -
1337               (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1338   return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1339                  (wfds != NULL) ? &wfds->sds : NULL,
1340                  (efds != NULL) ? &efds->sds : NULL,
1341                  (timeout.rel_value ==
1342                   GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1343
1344 #else
1345 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1346   /* calculate how long we need to wait in milliseconds */
1347   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1348     ms_total = INFINITE;
1349   else
1350   {
1351     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1352     if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1)
1353     {
1354       GNUNET_break (0);
1355       ms_total = 0xFFFFFFFF - 1;
1356     }
1357   }
1358   /* select() may be used as a portable way to sleep */
1359   if (!(rfds || wfds || efds))
1360   {
1361     Sleep (ms_total);
1362     return 0;
1363   }
1364
1365   if (select_thread == NULL)
1366   {
1367     SOCKET select_listening_socket = -1;
1368     struct sockaddr_in s_in;
1369     int alen;
1370     int res;
1371     unsigned long p;
1372
1373     select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1374     select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1375
1376     select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1377
1378     select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1379
1380     p = 1;
1381     res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1382
1383     alen = sizeof (s_in);
1384     s_in.sin_family = AF_INET;
1385     s_in.sin_port = 0;
1386     s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1387     s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1388     s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1389     s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1390     res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1391
1392     res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1393
1394     res = listen (select_listening_socket, SOMAXCONN);
1395
1396     res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1397
1398     select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1399
1400     closesocket (select_listening_socket);
1401
1402     sp.wakeup = select_finished_event;
1403     sp.standby = select_standby_event;
1404     sp.wakeup_socket = select_wakeup_socket;
1405
1406     select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1407   }
1408
1409
1410   handles_read = GNUNET_CONTAINER_slist_create ();
1411   handles_write = GNUNET_CONTAINER_slist_create ();
1412   handles_except = GNUNET_CONTAINER_slist_create ();
1413   FD_ZERO (&aread);
1414   FD_ZERO (&awrite);
1415   FD_ZERO (&aexcept);
1416 #if DEBUG_NETWORK
1417   FD_ZERO (&bread);
1418   FD_ZERO (&bwrite);
1419   FD_ZERO (&bexcept);
1420 #endif
1421   if (rfds)
1422   {
1423     FD_COPY (&rfds->sds, &aread);
1424 #if DEBUG_NETWORK
1425     FD_COPY (&rfds->sds, &bread);
1426 #endif
1427   }
1428   if (wfds)
1429   {
1430     FD_COPY (&wfds->sds, &awrite);
1431 #if DEBUG_NETWORK
1432     FD_COPY (&wfds->sds, &bwrite);
1433 #endif
1434   }
1435   if (efds)
1436   {
1437     FD_COPY (&efds->sds, &aexcept);
1438 #if DEBUG_NETWORK
1439     FD_COPY (&efds->sds, &bexcept);
1440 #endif
1441   }
1442
1443   /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1444      By profiling we detected that to be true in 90% of the cases.
1445   */
1446
1447   /* Do the select now */
1448   select_timeout.tv_sec = 0;
1449   select_timeout.tv_usec = 0;
1450
1451   /* Copy all the writes to the except, so we can detect connect() errors */
1452   for (i = 0; i < awrite.fd_count; i++)
1453   {
1454       if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1455           FD_SET (awrite.fd_array[i], &aexcept);
1456   }
1457   if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1458     selectret = select (1, (rfds != NULL) ? &aread : NULL,
1459         (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1460   else
1461     selectret = 0;
1462   if (selectret == -1)
1463   {
1464     /* Throw an error early on, while we still have the context. */
1465     LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1466         rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1467     GNUNET_abort ();
1468   }
1469
1470   /* Check aexcept, add its contents to awrite
1471      This is technically wrong (aexcept might have its own descriptors), we should
1472      have checked that descriptors were in awrite originally before re-adding them from
1473      aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1474   for (i = 0; i < aexcept.fd_count; i++)
1475   {
1476     if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1477       FD_SET (aexcept.fd_array[i], &awrite);
1478   }
1479
1480   /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1481   /* Sadly, it means code duplication :( */
1482   if ((selectret > 0) || (ms_total == 0))
1483   {
1484     /* Read Pipes */
1485     if (rfds && read_handles)
1486     {
1487       struct GNUNET_CONTAINER_SList_Iterator i;
1488
1489       for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1490           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1491           GNUNET_CONTAINER_slist_next (&i))
1492       {
1493         struct GNUNET_DISK_FileHandle *fh;
1494
1495         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1496         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1497         {
1498           DWORD error;
1499           BOOL bret;
1500
1501           SetLastError (0);
1502           DWORD waitstatus = 0;
1503           bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1504           error = GetLastError ();
1505           LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1506               i, fh->h, bret, waitstatus, error);
1507           if (bret == 0)
1508           {
1509             /* TODO: either add more errors to this condition, or eliminate it
1510              * entirely (failed to peek -> pipe is in serious trouble, should
1511              * be selected as readable).
1512              */
1513             if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1514               continue;
1515           }
1516           else if (waitstatus <= 0)
1517             continue;
1518           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1519               fh, sizeof (struct GNUNET_DISK_FileHandle));
1520           retcode++;
1521           LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1522               fh, fh->h);
1523         }
1524         else
1525         {
1526           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1527               fh, sizeof (struct GNUNET_DISK_FileHandle));
1528           retcode++;
1529         }
1530       }
1531     }
1532     if (wfds && write_handles)
1533     {
1534       LOG (GNUNET_ERROR_TYPE_DEBUG,
1535           "Adding the write ready event to the array as %d\n", nhandles);
1536       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1537       retcode += write_handles;
1538     }
1539     if (efds && ex_handles)
1540     {
1541       struct GNUNET_CONTAINER_SList_Iterator i;
1542
1543       for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1544           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1545           GNUNET_CONTAINER_slist_next (&i))
1546       {
1547         struct GNUNET_DISK_FileHandle *fh;
1548         DWORD dwBytes;
1549
1550         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1551         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1552         {
1553           if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1554             continue;
1555           GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1556               fh, sizeof (struct GNUNET_DISK_FileHandle));
1557           retcode++;
1558         }
1559       }
1560     }
1561
1562     /* Add our select() result.*/
1563     if (selectret >= 0)
1564       retcode += selectret;
1565
1566     if (rfds)
1567     {
1568       GNUNET_NETWORK_fdset_zero (rfds);
1569       if (selectret != -1)
1570         GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1571       GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1572     }
1573     if (wfds)
1574     {
1575       GNUNET_NETWORK_fdset_zero (wfds);
1576       if (selectret != -1)
1577         GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1578       GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1579     }
1580     if (efds)
1581     {
1582       GNUNET_NETWORK_fdset_zero (efds);
1583       if (selectret != -1)
1584         GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1585       GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1586     }
1587     GNUNET_CONTAINER_slist_destroy (handles_read);
1588     GNUNET_CONTAINER_slist_destroy (handles_write);
1589     GNUNET_CONTAINER_slist_destroy (handles_except);
1590
1591     if (selectret == -1)
1592       return -1;
1593     return retcode;
1594   }
1595
1596   /* If we got this far, use slower implementation that is able to do a waiting select
1597      on both sockets and pipes simultaneously */
1598
1599   /* Events for pipes */
1600   if (!hEventReadReady)
1601     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1602   if (!hEventPipeWrite)
1603     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1604   readPipes = 0;
1605   writePipePos = -1;
1606
1607   retcode = 0;
1608
1609   FD_ZERO (&aread);
1610   FD_ZERO (&awrite);
1611   FD_ZERO (&aexcept);
1612 #if DEBUG_NETWORK
1613   FD_ZERO (&bread);
1614   FD_ZERO (&bwrite);
1615   FD_ZERO (&bexcept);
1616 #endif
1617   if (rfds)
1618   {
1619     FD_COPY (&rfds->sds, &aread);
1620 #if DEBUG_NETWORK
1621     FD_COPY (&rfds->sds, &bread);
1622 #endif
1623   }
1624   if (wfds)
1625   {
1626     FD_COPY (&wfds->sds, &awrite);
1627 #if DEBUG_NETWORK
1628     FD_COPY (&wfds->sds, &bwrite);
1629 #endif
1630   }
1631   if (efds)
1632   {
1633     FD_COPY (&efds->sds, &aexcept);
1634 #if DEBUG_NETWORK
1635     FD_COPY (&efds->sds, &bexcept);
1636 #endif
1637   }
1638   /* We will first Add the PIPES to the events */
1639   /* Read Pipes */
1640   if (rfds && read_handles)
1641   {
1642     struct GNUNET_CONTAINER_SList_Iterator i;
1643
1644     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1645          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1646          GNUNET_CONTAINER_slist_next (&i))
1647     {
1648       struct GNUNET_DISK_FileHandle *fh;
1649
1650       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1651                                                                          NULL);
1652       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1653       {
1654         /* Read zero bytes to check the status of the pipe */
1655         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1656              fh->h);
1657         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1658         {
1659           DWORD error_code = GetLastError ();
1660
1661           if (error_code == ERROR_IO_PENDING)
1662           {
1663             LOG (GNUNET_ERROR_TYPE_DEBUG,
1664                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1665                  fh->h, nhandles);
1666             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1667             readArray[readPipes++] = fh;
1668           }
1669           else
1670           {
1671             LOG (GNUNET_ERROR_TYPE_DEBUG,
1672                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1673             handle_array[nhandles++] = hEventReadReady;
1674             readArray[readPipes++] = fh;
1675           }
1676         }
1677         else
1678         {
1679           LOG (GNUNET_ERROR_TYPE_DEBUG,
1680                "Adding the read ready event to the array as %d\n", nhandles);
1681           handle_array[nhandles++] = hEventReadReady;
1682           readArray[readPipes++] = fh;
1683         }
1684       }
1685       else
1686       {
1687         GNUNET_CONTAINER_slist_add (handles_read,
1688                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1689                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1690       }
1691     }
1692   }
1693   if (wfds && write_handles)
1694   {
1695     LOG (GNUNET_ERROR_TYPE_DEBUG,
1696          "Adding the write ready event to the array as %d\n", nhandles);
1697     handle_array[nhandles++] = hEventPipeWrite;
1698     writePipePos = nhandles;
1699   }
1700   if (efds && ex_handles)
1701   {
1702     struct GNUNET_CONTAINER_SList_Iterator i;
1703
1704     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1705          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1706          GNUNET_CONTAINER_slist_next (&i))
1707     {
1708       struct GNUNET_DISK_FileHandle *fh;
1709       DWORD dwBytes;
1710
1711       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1712                                                                          NULL);
1713       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1714       {
1715         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1716         {
1717           GNUNET_CONTAINER_slist_add (handles_except,
1718                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1719                                       fh,
1720                                       sizeof (struct GNUNET_DISK_FileHandle));
1721         }
1722       }
1723     }
1724   }
1725
1726   sp.status = 0;
1727
1728   if (nfds > 0)
1729   {
1730     LOG (GNUNET_ERROR_TYPE_DEBUG,
1731          "Adding the socket event to the array as %d\n", nhandles);
1732     handle_array[nhandles++] = select_finished_event;
1733     if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1734       sp.tv = NULL;
1735     else
1736     {
1737       select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1738       select_timeout.tv_usec = 1000 * (timeout.rel_value -
1739           (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1740       sp.tv = &select_timeout;
1741     }
1742     FD_SET (select_wakeup_socket, &aread);
1743     sp.r = &aread;
1744     sp.w = &awrite;
1745     sp.e = &aexcept;
1746     /* Failed connections cause sockets to be set in errorfds on W32,
1747      * but on POSIX it should set them in writefds.
1748      * First copy all awrite sockets to aexcept, later we'll
1749      * check aexcept and set its contents in awrite as well
1750      * Sockets are also set in errorfds when OOB data is available,
1751      * but we don't use OOB data.
1752      */
1753     for (i = 0; i < awrite.fd_count; i++)
1754     {
1755       if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1756         FD_SET (awrite.fd_array[i], &aexcept);
1757     }
1758     ResetEvent (select_finished_event);
1759     SetEvent (select_standby_event);
1760   }
1761
1762   handle_array[nhandles] = NULL;
1763   LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n", 
1764        nfds, nhandles, (unsigned long long) ms_total);
1765   if (nhandles)
1766   {
1767     returncode =
1768         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1769     LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1770          returncode);
1771   }
1772   else if (nfds > 0)
1773   {
1774     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1775     returncode = WAIT_TIMEOUT;
1776   }
1777   else
1778   {
1779     /* Shouldn't come this far. If it does - investigate. */
1780     GNUNET_assert (0);
1781   }
1782
1783   if (nfds > 0)
1784   {
1785     /* Don't wake up select-thread when delay is 0, it should return immediately
1786      * and wake up by itself.
1787      */
1788     if (ms_total != 0)
1789       i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1790     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1791     LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1792     if (ms_total != 0)
1793     {
1794       do
1795       {
1796         i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1797       } while (i == 1);
1798     }
1799     /* Check aexcept, add its contents to awrite */
1800     for (i = 0; i < aexcept.fd_count; i++)
1801     {
1802       if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1803         FD_SET (aexcept.fd_array[i], &awrite);
1804     }
1805   }
1806
1807   returnedpos = returncode - WAIT_OBJECT_0;
1808   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1809
1810   if (nhandles && (returnedpos < nhandles))
1811   {
1812     DWORD waitstatus;
1813
1814     if (sp.status > 0)
1815       retcode += sp.status;
1816
1817     if ((writePipePos != -1) && (returnedpos < writePipePos))
1818     {
1819       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1820       retcode += write_handles;
1821       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1822     }
1823     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1824     /* We have some pipes ready for read. */
1825     if (returnedpos < readPipes)
1826     {
1827       for (i = 0; i < readPipes; i++)
1828       {
1829         DWORD error;
1830         BOOL bret;
1831
1832         SetLastError (0);
1833         waitstatus = 0;
1834         bret =
1835             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1836         error = GetLastError ();
1837         LOG (GNUNET_ERROR_TYPE_DEBUG,
1838              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1839              i, readArray[i]->h, bret, waitstatus, error);
1840         if (bret == 0)
1841         {
1842           /* TODO: either add more errors to this condition, or eliminate it
1843            * entirely (failed to peek -> pipe is in serious trouble, should
1844            * be selected as readable).
1845            */
1846           if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1847             continue;
1848         }
1849         else if (waitstatus <= 0)
1850           continue;
1851         GNUNET_CONTAINER_slist_add (handles_read,
1852                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1853                                     readArray[i],
1854                                     sizeof (struct GNUNET_DISK_FileHandle));
1855         retcode++;
1856         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1857              readArray[i], readArray[i]->h);
1858       }
1859     }
1860   }
1861   if (!nhandles || (returnedpos >= nhandles))
1862     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1863   if (rfds)
1864   {
1865     struct GNUNET_CONTAINER_SList_Iterator t;
1866
1867     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1868          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1869          GNUNET_CONTAINER_slist_next (&t))
1870     {
1871       struct GNUNET_DISK_FileHandle *fh;
1872
1873       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1874                                                                          NULL);
1875       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1876       {
1877         CancelIo (fh->h);
1878       }
1879     }
1880     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1881     GNUNET_NETWORK_fdset_zero (rfds);
1882     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1883       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1884     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1885   }
1886   if (wfds)
1887   {
1888     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1889     GNUNET_NETWORK_fdset_zero (wfds);
1890     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1891       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1892     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1893   }
1894   if (efds)
1895   {
1896     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1897     GNUNET_NETWORK_fdset_zero (efds);
1898     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1899       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1900     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1901   }
1902   GNUNET_CONTAINER_slist_destroy (handles_read);
1903   GNUNET_CONTAINER_slist_destroy (handles_write);
1904   GNUNET_CONTAINER_slist_destroy (handles_except);
1905 #if DEBUG_NETWORK
1906   if (rfds)
1907   {
1908     struct GNUNET_CONTAINER_SList_Iterator t;
1909
1910     LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1911     for (i = 0; i < rfds->sds.fd_count; i++)
1912     {
1913       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1914     }
1915     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1916          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1917          GNUNET_CONTAINER_slist_next (&t))
1918     {
1919       struct GNUNET_DISK_FileHandle *fh;
1920
1921       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1922                                                                          NULL);
1923       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1924     }
1925   }
1926   if (wfds)
1927   {
1928     LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1929     for (i = 0; i < wfds->sds.fd_count; i++)
1930     {
1931       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1932     }
1933   }
1934   if (efds)
1935   {
1936     LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1937     for (i = 0; i < efds->sds.fd_count; i++)
1938     {
1939       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1940     }
1941   }
1942   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1943 #endif
1944   if (nhandles && (returnedpos < nhandles))
1945     return retcode;
1946   else
1947 #endif
1948     return 0;
1949 }
1950
1951 /* end of network.c */