fd6687c0f7c5f58657fe7679f5d5e7ae81b41fd0
[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   int nfds;
900
901   for (nfds = src->nsds; nfds > 0; nfds--)
902     if (FD_ISSET (nfds, &src->sds))
903
904     {
905       FD_SET (nfds, &dst->sds);
906       if (nfds + 1 > dst->nsds)
907         dst->nsds = nfds + 1;
908     }
909 #ifdef MINGW
910   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
911 #endif
912 }
913
914
915 /**
916  * Copy one fd set to another
917  *
918  * @param to destination
919  * @param from source
920  */
921 void
922 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
923                            const struct GNUNET_NETWORK_FDSet *from)
924 {
925   FD_COPY (&from->sds, &to->sds);
926   to->nsds = from->nsds;
927
928 #ifdef MINGW
929   GNUNET_CONTAINER_slist_clear (to->handles);
930   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
931 #endif
932 }
933
934
935 /**
936  * Return file descriptor for this network handle
937  *
938  * @param desc wrapper to process
939  * @return POSIX file descriptor
940  */
941 int
942 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
943 {
944   return desc->fd;
945 }
946
947 /**
948  * Return sockaddr for this network handle
949  *
950  * @param desc wrapper to process
951  * @return sockaddr
952  */
953 struct sockaddr*
954 GNUNET_NETWORK_get_addr (struct GNUNET_NETWORK_Handle *desc)
955 {
956   return desc->addr;
957 }
958
959 /**
960  * Return sockaddr length for this network handle
961  *
962  * @param desc wrapper to process
963  * @return socklen_t for sockaddr
964  */
965 socklen_t
966 GNUNET_NETWORK_get_addrlen (struct GNUNET_NETWORK_Handle *desc)
967 {
968   return desc->addrlen;
969 }
970 /**
971  * Copy a native fd set
972  *
973  * @param to destination
974  * @param from native source set
975  * @param nfds the biggest socket number in from + 1
976  */
977 void
978 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
979                                   const fd_set * from, int nfds)
980 {
981   FD_COPY (from, &to->sds);
982   to->nsds = nfds;
983 }
984
985
986 /**
987  * Set a native fd in a set
988  *
989  * @param to destination
990  * @param nfd native FD to set
991  */
992 void
993 GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to, int nfd)
994 {
995   GNUNET_assert ((nfd >= 0) && (nfd < FD_SETSIZE));
996   FD_SET (nfd, &to->sds);
997   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
998 }
999
1000
1001 /**
1002  * Test native fd in a set
1003  *
1004  * @param to set to test, NULL for empty set
1005  * @param nfd native FD to test, or -1 for none
1006  * @return GNUNET_YES if FD is set in the set
1007  */
1008 int
1009 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
1010                                   int nfd)
1011 {
1012   if ((nfd == -1) || (to == NULL))
1013     return GNUNET_NO;
1014   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
1015 }
1016
1017
1018 /**
1019  * Add a file handle to the fd set
1020  * @param fds fd set
1021  * @param h the file handle to add
1022  */
1023 void
1024 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
1025                                  const struct GNUNET_DISK_FileHandle *h)
1026 {
1027 #ifdef MINGW
1028   GNUNET_CONTAINER_slist_add (fds->handles,
1029                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, h,
1030                               sizeof (struct GNUNET_DISK_FileHandle));
1031
1032 #else
1033   int fd;
1034
1035   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
1036   FD_SET (fd, &fds->sds);
1037   if (fd + 1 > fds->nsds)
1038     fds->nsds = fd + 1;
1039
1040 #endif
1041 }
1042
1043
1044 /**
1045  * Check if a file handle is part of an fd set
1046  * @param fds fd set
1047  * @param h file handle
1048  * @return GNUNET_YES if the file handle is part of the set
1049  */
1050 int
1051 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
1052                                    const struct GNUNET_DISK_FileHandle *h)
1053 {
1054
1055 #ifdef MINGW
1056   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
1057                                           sizeof (struct
1058                                                   GNUNET_DISK_FileHandle));
1059 #else
1060   return FD_ISSET (h->fd, &fds->sds);
1061 #endif
1062 }
1063
1064
1065 /**
1066  * Checks if two fd sets overlap
1067  * @param fds1 first fd set
1068  * @param fds2 second fd set
1069  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
1070  */
1071 int
1072 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
1073                               const struct GNUNET_NETWORK_FDSet *fds2)
1074 {
1075 #ifndef MINGW
1076   int nfds;
1077
1078   nfds = fds1->nsds;
1079   if (nfds > fds2->nsds)
1080     nfds = fds2->nsds;
1081   while (nfds > 0)
1082   {
1083     nfds--;
1084     if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
1085       return GNUNET_YES;
1086   }
1087 #else
1088   struct GNUNET_CONTAINER_SList_Iterator it;
1089   struct GNUNET_DISK_FileHandle *h;
1090   int i;
1091   int j;
1092
1093   /*This code is somewhat hacky, we are not supposed to know what's
1094    * inside of fd_set; also the O(n^2) is really bad... */
1095
1096   for (i = 0; i < fds1->sds.fd_count; i++)
1097   {
1098     for (j = 0; j < fds2->sds.fd_count; j++)
1099     {
1100       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
1101         return GNUNET_YES;
1102     }
1103   }
1104   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
1105   while (GNUNET_CONTAINER_slist_end (&it) != GNUNET_YES)
1106   {
1107 #if DEBUG_NETWORK
1108     struct GNUNET_CONTAINER_SList_Iterator t;
1109 #endif
1110     h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&it,
1111                                                                       NULL);
1112 #if DEBUG_NETWORK
1113     LOG (GNUNET_ERROR_TYPE_DEBUG, "Checking that FD 0x%x is in another set:\n",
1114          h->h);
1115     for (t = GNUNET_CONTAINER_slist_begin (fds2->handles);
1116          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1117          GNUNET_CONTAINER_slist_next (&t))
1118     {
1119       struct GNUNET_DISK_FileHandle *fh;
1120
1121       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1122                                                                          NULL);
1123       LOG (GNUNET_ERROR_TYPE_DEBUG, "0x%x\n", fh->h);
1124     }
1125 #endif
1126     if (GNUNET_CONTAINER_slist_contains
1127         (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
1128     {
1129       return GNUNET_YES;
1130     }
1131     GNUNET_CONTAINER_slist_next (&it);
1132   }
1133 #endif
1134   return GNUNET_NO;
1135 }
1136
1137
1138 /**
1139  * Creates an fd set
1140  * @return a new fd set
1141  */
1142 struct GNUNET_NETWORK_FDSet *
1143 GNUNET_NETWORK_fdset_create ()
1144 {
1145   struct GNUNET_NETWORK_FDSet *fds;
1146
1147   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1148 #ifdef MINGW
1149   fds->handles = GNUNET_CONTAINER_slist_create ();
1150 #endif
1151   GNUNET_NETWORK_fdset_zero (fds);
1152   return fds;
1153 }
1154
1155
1156 /**
1157  * Releases the associated memory of an fd set
1158  * @param fds fd set
1159  */
1160 void
1161 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1162 {
1163 #ifdef MINGW
1164   GNUNET_CONTAINER_slist_destroy (fds->handles);
1165 #endif
1166   GNUNET_free (fds);
1167 }
1168
1169 #if MINGW
1170 struct _select_params
1171 {
1172   fd_set *r;
1173   fd_set *w;
1174   fd_set *e;
1175   struct timeval *tv;
1176   HANDLE wakeup;
1177   HANDLE standby;
1178   SOCKET wakeup_socket;
1179   int status;
1180 };
1181
1182 static DWORD WINAPI
1183 _selector (LPVOID p)
1184 {
1185   struct _select_params *sp = p;
1186   int i;
1187   while (1)
1188   {
1189     WaitForSingleObject (sp->standby, INFINITE);
1190     ResetEvent (sp->standby);
1191     sp->status = select (1, sp->r, sp->w, sp->e, sp->tv);
1192     if (FD_ISSET (sp->wakeup_socket, sp->r))
1193     {
1194       FD_CLR (sp->wakeup_socket, sp->r);
1195       sp->status -= 1;
1196     }
1197     SetEvent (sp->wakeup);
1198   }
1199   return 0;
1200 }
1201 #endif
1202
1203 /**
1204  * Check if sockets or pipes meet certain conditions
1205  * @param rfds set of sockets or pipes to be checked for readability
1206  * @param wfds set of sockets or pipes to be checked for writability
1207  * @param efds set of sockets or pipes to be checked for exceptions
1208  * @param timeout relative value when to return
1209  * @return number of selected sockets or pipes, GNUNET_SYSERR on error
1210  */
1211 int
1212 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1213                               struct GNUNET_NETWORK_FDSet *wfds,
1214                               struct GNUNET_NETWORK_FDSet *efds,
1215                               const struct GNUNET_TIME_Relative timeout)
1216 {
1217   int nfds = 0;
1218 #ifdef MINGW
1219   int handles = 0;
1220   int ex_handles = 0;
1221   int read_handles = 0;
1222   int write_handles = 0;
1223
1224   int i = 0;
1225   int retcode = 0;
1226   DWORD ms_total = 0;
1227
1228   int nhandles = 0;
1229
1230   static HANDLE hEventPipeWrite = 0;
1231   static HANDLE hEventReadReady = 0;
1232
1233   static struct _select_params sp;
1234   static HANDLE select_thread = NULL;
1235   static HANDLE select_finished_event = NULL;
1236   static HANDLE select_standby_event = NULL;
1237   static SOCKET select_wakeup_socket = -1;
1238   static SOCKET select_send_socket = -1;
1239   static struct timeval select_timeout;
1240
1241   int readPipes = 0;
1242   int writePipePos = 0;
1243
1244   HANDLE handle_array[FD_SETSIZE + 2];
1245   int returncode = -1;
1246   int returnedpos = 0;
1247
1248   struct GNUNET_CONTAINER_SList *handles_read;
1249   struct GNUNET_CONTAINER_SList *handles_write;
1250   struct GNUNET_CONTAINER_SList *handles_except;
1251
1252   int selectret = 0;
1253
1254   fd_set aread;
1255   fd_set awrite;
1256   fd_set aexcept;
1257
1258 #if DEBUG_NETWORK
1259   fd_set bread;
1260   fd_set bwrite;
1261   fd_set bexcept;
1262 #endif
1263
1264   /* TODO: Make this growable */
1265   struct GNUNET_DISK_FileHandle *readArray[50];
1266 #else
1267   struct timeval tv;
1268 #endif
1269   if (NULL != rfds)
1270   {
1271     nfds = rfds->nsds;
1272 #ifdef MINGW
1273     handles += read_handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1274 #if DEBUG_NETWORK
1275     {
1276       struct GNUNET_CONTAINER_SList_Iterator t;
1277
1278       for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1279            GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1280            GNUNET_CONTAINER_slist_next (&t))
1281       {
1282         struct GNUNET_DISK_FileHandle *fh;
1283
1284         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1285                                                                            NULL);
1286         LOG (GNUNET_ERROR_TYPE_DEBUG, "FD 0x%x (0x%x) is SET in rfds\n", fh->h,
1287              fh);
1288       }
1289     }
1290 #endif
1291 #endif
1292   }
1293   if (NULL != wfds)
1294   {
1295     nfds = GNUNET_MAX (nfds, wfds->nsds);
1296 #ifdef MINGW
1297     handles += write_handles = GNUNET_CONTAINER_slist_count (wfds->handles);
1298 #endif
1299   }
1300   if (NULL != efds)
1301   {
1302     nfds = GNUNET_MAX (nfds, efds->nsds);
1303 #ifdef MINGW
1304     handles += ex_handles = GNUNET_CONTAINER_slist_count (efds->handles);
1305 #endif
1306   }
1307
1308   if ((nfds == 0) &&
1309       (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1310 #ifdef MINGW
1311       && handles == 0
1312 #endif
1313       )
1314   {
1315     GNUNET_break (0);
1316     LOG (GNUNET_ERROR_TYPE_ERROR,
1317          _
1318          ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1319          "select");
1320   }
1321 #ifndef MINGW
1322   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1323   tv.tv_usec =
1324       1000 * (timeout.rel_value -
1325               (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1326   return select (nfds, (rfds != NULL) ? &rfds->sds : NULL,
1327                  (wfds != NULL) ? &wfds->sds : NULL,
1328                  (efds != NULL) ? &efds->sds : NULL,
1329                  (timeout.rel_value ==
1330                   GNUNET_TIME_UNIT_FOREVER_REL.rel_value) ? NULL : &tv);
1331
1332 #else
1333 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1334   /* calculate how long we need to wait in milliseconds */
1335   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1336     ms_total = INFINITE;
1337   else
1338   {
1339     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1340     if (timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value > 0xFFFFFFFFLL - 1)
1341     {
1342       GNUNET_break (0);
1343       ms_total = 0xFFFFFFFF - 1;
1344     }
1345   }
1346   /* select() may be used as a portable way to sleep */
1347   if (!(rfds || wfds || efds))
1348   {
1349     Sleep (ms_total);
1350     return 0;
1351   }
1352
1353   if (select_thread == NULL)
1354   {
1355     SOCKET select_listening_socket = -1;
1356     struct sockaddr_in s_in;
1357     int alen;
1358     int res;
1359     unsigned long p;
1360
1361     select_standby_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1362     select_finished_event = CreateEvent (NULL, TRUE, FALSE, NULL);
1363
1364     select_wakeup_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1365
1366     select_listening_socket = WSASocket (AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
1367
1368     p = 1;
1369     res = ioctlsocket (select_wakeup_socket, FIONBIO, &p);
1370
1371     alen = sizeof (s_in);
1372     s_in.sin_family = AF_INET;
1373     s_in.sin_port = 0;
1374     s_in.sin_addr.S_un.S_un_b.s_b1 = 127;
1375     s_in.sin_addr.S_un.S_un_b.s_b2 = 0;
1376     s_in.sin_addr.S_un.S_un_b.s_b3 = 0;
1377     s_in.sin_addr.S_un.S_un_b.s_b4 = 1;
1378     res = bind (select_listening_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1379
1380     res = getsockname (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1381
1382     res = listen (select_listening_socket, SOMAXCONN);
1383
1384     res = connect (select_wakeup_socket, (const struct sockaddr *) &s_in, sizeof (s_in));
1385
1386     select_send_socket = accept (select_listening_socket, (struct sockaddr *) &s_in, &alen);
1387
1388     closesocket (select_listening_socket);
1389
1390     sp.wakeup = select_finished_event;
1391     sp.standby = select_standby_event;
1392     sp.wakeup_socket = select_wakeup_socket;
1393
1394     select_thread = CreateThread (NULL, 0, _selector, &sp, 0, NULL);
1395   }
1396
1397
1398   handles_read = GNUNET_CONTAINER_slist_create ();
1399   handles_write = GNUNET_CONTAINER_slist_create ();
1400   handles_except = GNUNET_CONTAINER_slist_create ();
1401   FD_ZERO (&aread);
1402   FD_ZERO (&awrite);
1403   FD_ZERO (&aexcept);
1404 #if DEBUG_NETWORK
1405   FD_ZERO (&bread);
1406   FD_ZERO (&bwrite);
1407   FD_ZERO (&bexcept);
1408 #endif
1409   if (rfds)
1410   {
1411     FD_COPY (&rfds->sds, &aread);
1412 #if DEBUG_NETWORK
1413     FD_COPY (&rfds->sds, &bread);
1414 #endif
1415   }
1416   if (wfds)
1417   {
1418     FD_COPY (&wfds->sds, &awrite);
1419 #if DEBUG_NETWORK
1420     FD_COPY (&wfds->sds, &bwrite);
1421 #endif
1422   }
1423   if (efds)
1424   {
1425     FD_COPY (&efds->sds, &aexcept);
1426 #if DEBUG_NETWORK
1427     FD_COPY (&efds->sds, &bexcept);
1428 #endif
1429   }
1430
1431   /* Start by doing a fast check on sockets and pipes (without waiting). It is cheap, and is sufficient most of the time.
1432      By profiling we detected that to be true in 90% of the cases.
1433   */
1434
1435   /* Do the select now */
1436   select_timeout.tv_sec = 0;
1437   select_timeout.tv_usec = 0;
1438
1439   /* Copy all the writes to the except, so we can detect connect() errors */
1440   for (i = 0; i < awrite.fd_count; i++)
1441   {
1442       if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1443           FD_SET (awrite.fd_array[i], &aexcept);
1444   }
1445   if (aread.fd_count > 0 || awrite.fd_count > 0 || aexcept.fd_count > 0)
1446     selectret = select (1, (rfds != NULL) ? &aread : NULL,
1447         (wfds != NULL) ? &awrite : NULL, &aexcept, &select_timeout);
1448   else
1449     selectret = 0;
1450   if (selectret == -1)
1451   {
1452     /* Throw an error early on, while we still have the context. */
1453     LOG (GNUNET_ERROR_TYPE_ERROR, "W32 select(%d, %d, %d) failed: %lu\n",
1454         rfds ? aread.fd_count : 0, wfds ? awrite.fd_count : 0, aexcept.fd_count, GetLastError ());
1455     GNUNET_abort ();
1456   }
1457
1458   /* Check aexcept, add its contents to awrite
1459      This is technically wrong (aexcept might have its own descriptors), we should
1460      have checked that descriptors were in awrite originally before re-adding them from
1461      aexcept. Luckily, GNUnet never uses aexcept for anything, so this does not become a problem (yet). */
1462   for (i = 0; i < aexcept.fd_count; i++)
1463   {
1464     if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1465       FD_SET (aexcept.fd_array[i], &awrite);
1466   }
1467
1468   /* If our select returned something or is a 0-timed request, then also check the pipes and get out of here! */
1469   /* Sadly, it means code duplication :( */
1470   if ((selectret > 0) || (ms_total == 0))
1471   {
1472     /* Read Pipes */
1473     if (rfds && read_handles)
1474     {
1475       struct GNUNET_CONTAINER_SList_Iterator i;
1476
1477       for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1478           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1479           GNUNET_CONTAINER_slist_next (&i))
1480       {
1481         struct GNUNET_DISK_FileHandle *fh;
1482
1483         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,NULL);
1484         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1485         {
1486           DWORD error;
1487           BOOL bret;
1488
1489           SetLastError (0);
1490           DWORD waitstatus = 0;
1491           bret = PeekNamedPipe (fh->h, NULL, 0, NULL, &waitstatus, NULL);
1492           error = GetLastError ();
1493           LOG (GNUNET_ERROR_TYPE_DEBUG, "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1494               i, fh->h, bret, waitstatus, error);
1495           if (bret == 0)
1496           {
1497             /* TODO: either add more errors to this condition, or eliminate it
1498              * entirely (failed to peek -> pipe is in serious trouble, should
1499              * be selected as readable).
1500              */
1501             if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1502               continue;
1503           }
1504           else if (waitstatus <= 0)
1505             continue;
1506           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1507               fh, sizeof (struct GNUNET_DISK_FileHandle));
1508           retcode++;
1509           LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1510               fh, fh->h);
1511         }
1512         else
1513         {
1514           GNUNET_CONTAINER_slist_add (handles_read, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1515               fh, sizeof (struct GNUNET_DISK_FileHandle));
1516           retcode++;
1517         }
1518       }
1519     }
1520     if (wfds && write_handles)
1521     {
1522       LOG (GNUNET_ERROR_TYPE_DEBUG,
1523           "Adding the write ready event to the array as %d\n", nhandles);
1524       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1525       retcode += write_handles;
1526     }
1527     if (efds && ex_handles)
1528     {
1529       struct GNUNET_CONTAINER_SList_Iterator i;
1530
1531       for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1532           GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1533           GNUNET_CONTAINER_slist_next (&i))
1534       {
1535         struct GNUNET_DISK_FileHandle *fh;
1536         DWORD dwBytes;
1537
1538         fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i, NULL);
1539         if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1540         {
1541           if (PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1542             continue;
1543           GNUNET_CONTAINER_slist_add (handles_except, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1544               fh, sizeof (struct GNUNET_DISK_FileHandle));
1545           retcode++;
1546         }
1547       }
1548     }
1549
1550     /* Add our select() result.*/
1551     if (selectret >= 0)
1552       retcode += selectret;
1553
1554     if (rfds)
1555     {
1556       GNUNET_NETWORK_fdset_zero (rfds);
1557       if (selectret != -1)
1558         GNUNET_NETWORK_fdset_copy_native (rfds, &aread, selectret);
1559       GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1560     }
1561     if (wfds)
1562     {
1563       GNUNET_NETWORK_fdset_zero (wfds);
1564       if (selectret != -1)
1565         GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, selectret);
1566       GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1567     }
1568     if (efds)
1569     {
1570       GNUNET_NETWORK_fdset_zero (efds);
1571       if (selectret != -1)
1572         GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, selectret);
1573       GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1574     }
1575     GNUNET_CONTAINER_slist_destroy (handles_read);
1576     GNUNET_CONTAINER_slist_destroy (handles_write);
1577     GNUNET_CONTAINER_slist_destroy (handles_except);
1578
1579     if (selectret == -1)
1580       return -1;
1581     return retcode;
1582   }
1583
1584   /* If we got this far, use slower implementation that is able to do a waiting select
1585      on both sockets and pipes simultaneously */
1586
1587   /* Events for pipes */
1588   if (!hEventReadReady)
1589     hEventReadReady = CreateEvent (NULL, TRUE, TRUE, NULL);
1590   if (!hEventPipeWrite)
1591     hEventPipeWrite = CreateEvent (NULL, TRUE, TRUE, NULL);
1592   readPipes = 0;
1593   writePipePos = -1;
1594
1595   retcode = 0;
1596
1597   FD_ZERO (&aread);
1598   FD_ZERO (&awrite);
1599   FD_ZERO (&aexcept);
1600 #if DEBUG_NETWORK
1601   FD_ZERO (&bread);
1602   FD_ZERO (&bwrite);
1603   FD_ZERO (&bexcept);
1604 #endif
1605   if (rfds)
1606   {
1607     FD_COPY (&rfds->sds, &aread);
1608 #if DEBUG_NETWORK
1609     FD_COPY (&rfds->sds, &bread);
1610 #endif
1611   }
1612   if (wfds)
1613   {
1614     FD_COPY (&wfds->sds, &awrite);
1615 #if DEBUG_NETWORK
1616     FD_COPY (&wfds->sds, &bwrite);
1617 #endif
1618   }
1619   if (efds)
1620   {
1621     FD_COPY (&efds->sds, &aexcept);
1622 #if DEBUG_NETWORK
1623     FD_COPY (&efds->sds, &bexcept);
1624 #endif
1625   }
1626   /* We will first Add the PIPES to the events */
1627   /* Read Pipes */
1628   if (rfds && read_handles)
1629   {
1630     struct GNUNET_CONTAINER_SList_Iterator i;
1631
1632     for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1633          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1634          GNUNET_CONTAINER_slist_next (&i))
1635     {
1636       struct GNUNET_DISK_FileHandle *fh;
1637
1638       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1639                                                                          NULL);
1640       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1641       {
1642         /* Read zero bytes to check the status of the pipe */
1643         LOG (GNUNET_ERROR_TYPE_DEBUG, "Reading 0 bytes from the pipe 0x%x\n",
1644              fh->h);
1645         if (!ReadFile (fh->h, NULL, 0, NULL, fh->oOverlapRead))
1646         {
1647           DWORD error_code = GetLastError ();
1648
1649           if (error_code == ERROR_IO_PENDING)
1650           {
1651             LOG (GNUNET_ERROR_TYPE_DEBUG,
1652                  "Adding the pipe's 0x%x overlapped event to the array as %d\n",
1653                  fh->h, nhandles);
1654             handle_array[nhandles++] = fh->oOverlapRead->hEvent;
1655             readArray[readPipes++] = fh;
1656           }
1657           else
1658           {
1659             LOG (GNUNET_ERROR_TYPE_DEBUG,
1660                  "Read failed, adding the read ready event to the array as %d\n", nhandles);
1661             handle_array[nhandles++] = hEventReadReady;
1662             readArray[readPipes++] = fh;
1663           }
1664         }
1665         else
1666         {
1667           LOG (GNUNET_ERROR_TYPE_DEBUG,
1668                "Adding the read ready event to the array as %d\n", nhandles);
1669           handle_array[nhandles++] = hEventReadReady;
1670           readArray[readPipes++] = fh;
1671         }
1672       }
1673       else
1674       {
1675         GNUNET_CONTAINER_slist_add (handles_read,
1676                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1677                                     fh, sizeof (struct GNUNET_DISK_FileHandle));
1678       }
1679     }
1680   }
1681   if (wfds && write_handles)
1682   {
1683     LOG (GNUNET_ERROR_TYPE_DEBUG,
1684          "Adding the write ready event to the array as %d\n", nhandles);
1685     handle_array[nhandles++] = hEventPipeWrite;
1686     writePipePos = nhandles;
1687   }
1688   if (efds && ex_handles)
1689   {
1690     struct GNUNET_CONTAINER_SList_Iterator i;
1691
1692     for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1693          GNUNET_CONTAINER_slist_end (&i) != GNUNET_YES;
1694          GNUNET_CONTAINER_slist_next (&i))
1695     {
1696       struct GNUNET_DISK_FileHandle *fh;
1697       DWORD dwBytes;
1698
1699       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&i,
1700                                                                          NULL);
1701       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1702       {
1703         if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1704         {
1705           GNUNET_CONTAINER_slist_add (handles_except,
1706                                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1707                                       fh,
1708                                       sizeof (struct GNUNET_DISK_FileHandle));
1709         }
1710       }
1711     }
1712   }
1713
1714   sp.status = 0;
1715
1716   if (nfds > 0)
1717   {
1718     LOG (GNUNET_ERROR_TYPE_DEBUG,
1719          "Adding the socket event to the array as %d\n", nhandles);
1720     handle_array[nhandles++] = select_finished_event;
1721     if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1722       sp.tv = NULL;
1723     else
1724     {
1725       select_timeout.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1726       select_timeout.tv_usec = 1000 * (timeout.rel_value -
1727           (select_timeout.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1728       sp.tv = &select_timeout;
1729     }
1730     FD_SET (select_wakeup_socket, &aread);
1731     sp.r = &aread;
1732     sp.w = &awrite;
1733     sp.e = &aexcept;
1734     /* Failed connections cause sockets to be set in errorfds on W32,
1735      * but on POSIX it should set them in writefds.
1736      * First copy all awrite sockets to aexcept, later we'll
1737      * check aexcept and set its contents in awrite as well
1738      * Sockets are also set in errorfds when OOB data is available,
1739      * but we don't use OOB data.
1740      */
1741     for (i = 0; i < awrite.fd_count; i++)
1742     {
1743       if (awrite.fd_array[i] != 0 && awrite.fd_array[i] != -1)
1744         FD_SET (awrite.fd_array[i], &aexcept);
1745     }
1746     ResetEvent (select_finished_event);
1747     SetEvent (select_standby_event);
1748   }
1749
1750   handle_array[nhandles] = NULL;
1751   LOG (GNUNET_ERROR_TYPE_DEBUG, "nfds: %d, handles: %d, will wait: %llu ms\n", 
1752        nfds, nhandles, (unsigned long long) ms_total);
1753   if (nhandles)
1754   {
1755     returncode =
1756         WaitForMultipleObjects (nhandles, handle_array, FALSE, ms_total);
1757     LOG (GNUNET_ERROR_TYPE_DEBUG, "WaitForMultipleObjects Returned : %d\n",
1758          returncode);
1759   }
1760   else if (nfds > 0)
1761   {
1762     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1763     returncode = WAIT_TIMEOUT;
1764   }
1765   else
1766   {
1767     /* Shouldn't come this far. If it does - investigate. */
1768     GNUNET_assert (0);
1769   }
1770
1771   if (nfds > 0)
1772   {
1773     /* Don't wake up select-thread when delay is 0, it should return immediately
1774      * and wake up by itself.
1775      */
1776     if (ms_total != 0)
1777       i = send (select_send_socket, (const char *) &returnedpos, 1, 0);
1778     i = (int) WaitForSingleObject (select_finished_event, INFINITE);
1779     LOG (GNUNET_ERROR_TYPE_DEBUG, "Finished waiting for the select thread: %d %d\n", i, sp.status);
1780     if (ms_total != 0)
1781     {
1782       do
1783       {
1784         i = recv (select_wakeup_socket, (char *) &returnedpos, 1, 0);
1785       } while (i == 1);
1786     }
1787     /* Check aexcept, add its contents to awrite */
1788     for (i = 0; i < aexcept.fd_count; i++)
1789     {
1790       if (aexcept.fd_array[i] != 0 && aexcept.fd_array[i] != -1)
1791         FD_SET (aexcept.fd_array[i], &awrite);
1792     }
1793   }
1794
1795   returnedpos = returncode - WAIT_OBJECT_0;
1796   LOG (GNUNET_ERROR_TYPE_DEBUG, "return pos is : %d\n", returnedpos);
1797
1798   if (nhandles && (returnedpos < nhandles))
1799   {
1800     DWORD waitstatus;
1801
1802     if (sp.status > 0)
1803       retcode += sp.status;
1804
1805     if ((writePipePos != -1) && (returnedpos < writePipePos))
1806     {
1807       GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1808       retcode += write_handles;
1809       LOG (GNUNET_ERROR_TYPE_DEBUG, "Added write pipe\n");
1810     }
1811     LOG (GNUNET_ERROR_TYPE_DEBUG, "ReadPipes is : %d\n", readPipes);
1812     /* We have some pipes ready for read. */
1813     if (returnedpos < readPipes)
1814     {
1815       for (i = 0; i < readPipes; i++)
1816       {
1817         DWORD error;
1818         BOOL bret;
1819
1820         SetLastError (0);
1821         waitstatus = 0;
1822         bret =
1823             PeekNamedPipe (readArray[i]->h, NULL, 0, NULL, &waitstatus, NULL);
1824         error = GetLastError ();
1825         LOG (GNUNET_ERROR_TYPE_DEBUG,
1826              "Peek at read pipe %d (0x%x) returned %d (%d bytes available) GLE %u\n",
1827              i, readArray[i]->h, bret, waitstatus, error);
1828         if (bret == 0)
1829         {
1830           /* TODO: either add more errors to this condition, or eliminate it
1831            * entirely (failed to peek -> pipe is in serious trouble, should
1832            * be selected as readable).
1833            */
1834           if (error != ERROR_BROKEN_PIPE && error != ERROR_INVALID_HANDLE)
1835             continue;
1836         }
1837         else if (waitstatus <= 0)
1838           continue;
1839         GNUNET_CONTAINER_slist_add (handles_read,
1840                                     GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1841                                     readArray[i],
1842                                     sizeof (struct GNUNET_DISK_FileHandle));
1843         retcode++;
1844         LOG (GNUNET_ERROR_TYPE_DEBUG, "Added read Pipe 0x%x (0x%x)\n",
1845              readArray[i], readArray[i]->h);
1846       }
1847     }
1848   }
1849   if (!nhandles || (returnedpos >= nhandles))
1850     LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning from _select() with nothing!\n");
1851   if (rfds)
1852   {
1853     struct GNUNET_CONTAINER_SList_Iterator t;
1854
1855     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1856          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1857          GNUNET_CONTAINER_slist_next (&t))
1858     {
1859       struct GNUNET_DISK_FileHandle *fh;
1860
1861       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1862                                                                          NULL);
1863       if (fh->type == GNUNET_DISK_HANLDE_TYPE_PIPE)
1864       {
1865         CancelIo (fh->h);
1866       }
1867     }
1868     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing rfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1869     GNUNET_NETWORK_fdset_zero (rfds);
1870     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1871       GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1872     GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1873   }
1874   if (wfds)
1875   {
1876     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing wfds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1877     GNUNET_NETWORK_fdset_zero (wfds);
1878     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1879       GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1880     GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1881   }
1882   if (efds)
1883   {
1884     LOG (GNUNET_ERROR_TYPE_DEBUG, "Zeroing efds%s\n", (retcode != -1 && nhandles && (returnedpos < nhandles)) ? ", copying fdset" : "");
1885     GNUNET_NETWORK_fdset_zero (efds);
1886     if (retcode != -1 && nhandles && (returnedpos < nhandles))
1887       GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1888     GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1889   }
1890   GNUNET_CONTAINER_slist_destroy (handles_read);
1891   GNUNET_CONTAINER_slist_destroy (handles_write);
1892   GNUNET_CONTAINER_slist_destroy (handles_except);
1893 #if DEBUG_NETWORK
1894   if (rfds)
1895   {
1896     struct GNUNET_CONTAINER_SList_Iterator t;
1897
1898     LOG (GNUNET_ERROR_TYPE_DEBUG, "rfds:\n");
1899     for (i = 0; i < rfds->sds.fd_count; i++)
1900     {
1901       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", rfds->sds.fd_array[i]);
1902     }
1903     for (t = GNUNET_CONTAINER_slist_begin (rfds->handles);
1904          GNUNET_CONTAINER_slist_end (&t) != GNUNET_YES;
1905          GNUNET_CONTAINER_slist_next (&t))
1906     {
1907       struct GNUNET_DISK_FileHandle *fh;
1908
1909       fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (&t,
1910                                                                          NULL);
1911       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", fh->h);
1912     }
1913   }
1914   if (wfds)
1915   {
1916     LOG (GNUNET_ERROR_TYPE_DEBUG, "wfds:\n");
1917     for (i = 0; i < wfds->sds.fd_count; i++)
1918     {
1919       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", wfds->sds.fd_array[i]);
1920     }
1921   }
1922   if (efds)
1923   {
1924     LOG (GNUNET_ERROR_TYPE_DEBUG, "efds:\n");
1925     for (i = 0; i < efds->sds.fd_count; i++)
1926     {
1927       LOG (GNUNET_ERROR_TYPE_DEBUG, "%d\n", efds->sds.fd_array[i]);
1928     }
1929   }
1930   LOG (GNUNET_ERROR_TYPE_DEBUG, "Returning %d or 0\n", retcode);
1931 #endif
1932   if (nhandles && (returnedpos < nhandles))
1933     return retcode;
1934   else
1935 #endif
1936     return 0;
1937 }
1938
1939 /* end of network.c */