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