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