comments
[oweals/gnunet.git] / src / util / network.c
1 /*
2      This file is part of GNUnet.
3      (C) 2009 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  */
26
27 #include "platform.h"
28 #include "gnunet_disk_lib.h"
29 #include "disk.h"
30 #include "gnunet_container_lib.h"
31
32 #define DEBUG_NETWORK GNUNET_NO
33
34 #define DEBUG_W32_CYCLES GNUNET_NO
35
36 #ifndef INVALID_SOCKET
37 #define INVALID_SOCKET -1
38 #endif
39
40
41 struct GNUNET_NETWORK_Handle
42 {
43 #ifndef MINGW
44   int fd;
45
46 #else
47   SOCKET fd;
48 #endif
49
50   /**
51    * Address family / domain.
52    */
53   int af;
54
55   /**
56    * Number of bytes in addr.
57    */
58   socklen_t addrlen;
59
60   /**
61    * Address we were bound to, or NULL.
62    */
63   struct sockaddr *addr;
64
65 };
66
67
68 struct GNUNET_NETWORK_FDSet
69 {
70
71   /**
72    * Maximum number of any socket socket descriptor in the set (plus one)
73    */
74   int nsds;
75
76   /**
77    * Bitset with the descriptors.
78    */
79   fd_set sds;
80
81 #ifdef WINDOWS
82   /**
83    * Linked list of handles
84    */
85   struct GNUNET_CONTAINER_SList *handles;
86 #endif
87
88 };
89
90 #ifndef FD_COPY
91 #define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))
92 #endif
93
94
95 /**
96  * Set if a socket should use blocking or non-blocking IO.
97  * @param fd socket
98  * @param doBlock blocking mode
99  * @return GNUNET_OK on success, GNUNET_SYSERR on error
100  */
101 static int
102 socket_set_blocking (struct GNUNET_NETWORK_Handle *fd, int doBlock)
103 {
104
105 #if MINGW
106   u_long mode;
107   mode = !doBlock;
108   if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)
109
110     {
111       SetErrnoFromWinsockError (WSAGetLastError ());
112       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");
113       return GNUNET_SYSERR;
114     }
115   return GNUNET_OK;
116
117 #else
118   /* not MINGW */
119   int flags = fcntl (fd->fd, F_GETFL);
120   if (flags == -1)
121
122     {
123       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
124       return GNUNET_SYSERR;
125     }
126   if (doBlock)
127     flags &= ~O_NONBLOCK;
128
129   else
130     flags |= O_NONBLOCK;
131   if (0 != fcntl (fd->fd, F_SETFL, flags))
132
133     {
134       GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");
135       return GNUNET_SYSERR;
136     }
137   return GNUNET_OK;
138 #endif
139 }
140
141
142 #ifndef MINGW
143 /**
144  * Make a socket non-inheritable to child processes
145  *
146  * @param h the socket to make non-inheritable
147  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
148  * @warning Not implemented on Windows
149  */
150 static int
151 socket_set_inheritable (const struct GNUNET_NETWORK_Handle *h)
152 {
153   int i;
154
155   i = fcntl (h->fd, F_GETFD);  
156   if (i < 0)
157     return GNUNET_SYSERR;
158   if (i == (i | FD_CLOEXEC))
159     return GNUNET_OK;
160   i |= FD_CLOEXEC;
161   if (fcntl (h->fd, F_SETFD, i) < 0)
162     return GNUNET_SYSERR;
163   return GNUNET_OK;
164 }
165 #endif
166
167
168 #ifdef DARWIN
169 /**
170  * The MSG_NOSIGNAL equivalent on Mac OS X
171  *
172  * @param h the socket to make non-delaying
173  */
174 static void
175 socket_set_nosigpipe (const struct GNUNET_NETWORK_Handle *h)
176 {
177   int abs_value = 1;
178   if (0 !=
179       setsockopt (h->fd, SOL_SOCKET, SO_NOSIGPIPE, &abs_value, sizeof (abs_value)))
180     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
181 }
182 #endif
183
184
185 /**
186  * Disable delays when sending data via the socket.
187  * (GNUnet makes sure that messages are as big as
188  * possible already).
189  *
190  * @param h the socket to make non-delaying
191  */
192 static void
193 socket_set_nodelay (const struct GNUNET_NETWORK_Handle *h)
194 {
195 #ifndef WINDOWS  
196   int value = 1;
197   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof (value)))
198     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
199 #else
200   const char * abs_value = "1";
201   if (0 != setsockopt (h->fd, IPPROTO_TCP, TCP_NODELAY, abs_value, sizeof (abs_value)))
202     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
203 #endif  
204 }
205
206
207 /**
208  * accept a new connection on a socket
209  *
210  * @param desc bound socket
211  * @param address address of the connecting peer, may be NULL
212  * @param address_len length of address
213  * @return client socket
214  */
215 struct GNUNET_NETWORK_Handle *
216 GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Handle *desc,
217                               struct sockaddr *address,
218                               socklen_t * address_len)
219 {
220   struct GNUNET_NETWORK_Handle *ret;
221
222   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
223   ret->fd = accept (desc->fd, address, address_len);
224   if (address != NULL)
225     ret->af = address->sa_family;
226   else
227     ret->af = desc->af;
228   if (ret->fd == INVALID_SOCKET)
229     {
230 #ifdef MINGW
231       SetErrnoFromWinsockError (WSAGetLastError ());
232 #endif
233       GNUNET_free (ret);
234       return NULL;
235     }
236 #ifndef MINGW
237   if (ret->fd >= FD_SETSIZE)
238     {
239       GNUNET_break (0 == close (ret->fd));
240       GNUNET_free (ret);
241       errno = EMFILE;
242       return NULL;
243     }
244 #endif
245   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
246
247     {
248
249       /* we might want to treat this one as fatal... */
250       GNUNET_break (0);
251       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
252       return NULL;
253     }
254
255 #ifndef MINGW
256   if (GNUNET_OK != socket_set_inheritable (ret))
257     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
258                          "socket_set_inheritable");
259 #endif
260 #ifdef DARWIN
261   socket_set_nosigpipe (ret);
262 #endif
263 #ifdef AF_UNIX
264   if (ret->af != AF_UNIX)
265 #endif
266     socket_set_nodelay (ret);
267   return ret;
268 }
269
270
271 /**
272  * Bind to a connected socket
273  * @param desc socket
274  * @param address address to be bound
275  * @param address_len length of address
276  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
277  */
278 int
279 GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Handle *desc,
280                             const struct sockaddr *address,
281                             socklen_t address_len)
282 {
283   int ret;
284   
285 #ifdef IPV6_V6ONLY 
286 #ifdef IPPROTO_IPV6
287   const int on = 1;
288   if (desc->af == AF_INET6)
289     if (0 != setsockopt (desc->fd, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof (on)))
290       GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
291 #if 0
292   /* is this needed or desired? or done elsewhere? */
293   if (0 != setsockopt (desc->fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)))
294     GNUNET_log_strerror (GNUNET_ERROR_TYPE_DEBUG, "setsockopt");
295 #endif
296 #endif
297 #endif
298 #ifndef LINUX
299 #ifndef MINGW
300   if (address->sa_family == AF_UNIX)
301     {
302       const struct sockaddr_un *un = (const struct sockaddr_un*) address;
303       (void) unlink (un->sun_path);
304     }
305 #endif
306 #endif
307   ret = bind (desc->fd, address, address_len);
308 #ifdef MINGW
309   if (SOCKET_ERROR == ret)
310     SetErrnoFromWinsockError (WSAGetLastError ());
311 #endif
312   if (ret != 0)
313           return GNUNET_SYSERR;
314 #ifndef MINGW
315 #ifndef LINUX
316   desc->addr = GNUNET_malloc (address_len);
317   memcpy (desc->addr, address, address_len);
318   desc->addrlen = address_len;
319 #endif
320 #endif
321   return GNUNET_OK;
322 }
323
324
325 /**
326  * Close a socket
327  * @param desc socket
328  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
329  */
330 int
331 GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Handle *desc)
332 {
333   int ret;
334
335 #ifdef MINGW
336   ret = closesocket (desc->fd);
337   SetErrnoFromWinsockError (WSAGetLastError ());
338 #else
339   ret = close (desc->fd);
340 #endif
341 #ifndef LINUX
342 #ifndef MINGW
343   if ( (desc->af == AF_UNIX) && (NULL != desc->addr) )
344     {
345       const struct sockaddr_un *un = (const struct sockaddr_un*) desc->addr;
346       if (0 != unlink (un->sun_path))
347           GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING,
348                                   "unlink",
349                                   un->sun_path);
350     }
351 #endif
352 #endif
353    GNUNET_free_non_null (desc->addr);
354   GNUNET_free (desc);
355   return (ret == 0) ? GNUNET_OK : GNUNET_SYSERR;
356 }
357
358
359 /**
360  * Box a native socket (and check that it is a socket).
361  *
362  * @param fd socket to box
363  * @return NULL on error (including not supported on target platform)
364  */
365 struct GNUNET_NETWORK_Handle *
366 GNUNET_NETWORK_socket_box_native (int fd)
367 {
368 #if MINGW
369   return NULL;
370 #else
371   struct GNUNET_NETWORK_Handle *ret;
372
373   if (fcntl (fd, F_GETFD) < 0)
374     return NULL; /* invalid FD */
375   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle)); 
376   ret->fd = fd;
377   ret->af = AF_UNSPEC;
378   return ret;
379 #endif
380 }
381
382
383 /**
384  * Connect a socket
385  * @param desc socket
386  * @param address peer address
387  * @param address_len length of address
388  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
389  */
390 int
391 GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Handle *desc,
392                                const struct sockaddr *address,
393                                socklen_t address_len)
394 {
395   int ret;
396   ret = connect (desc->fd, address, address_len);
397
398 #ifdef MINGW
399   if (SOCKET_ERROR == ret)
400     {
401       SetErrnoFromWinsockError (WSAGetLastError ());
402       if (errno == EWOULDBLOCK)
403         errno = EINPROGRESS;
404     }
405 #endif
406   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
407 }
408
409
410 /**
411  * Get socket options
412  *
413  * @param desc socket
414  * @param level protocol level of the option
415  * @param optname identifier of the option
416  * @param optval options
417  * @param optlen length of optval
418  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
419  */
420 int
421 GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Handle *desc,
422                                   int level, int optname, void *optval,
423                                   socklen_t * optlen)
424 {
425   int ret;
426   ret = getsockopt (desc->fd, level, optname, optval, optlen);
427
428 #ifdef MINGW
429   if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)
430     *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));
431
432   else if (SOCKET_ERROR == ret)
433     SetErrnoFromWinsockError (WSAGetLastError ());
434
435 #endif
436   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
437 }
438
439
440 /**
441  * Listen on a socket
442  * @param desc socket
443  * @param backlog length of the listen queue
444  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
445  */
446 int
447 GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Handle *desc,
448                               int backlog)
449 {
450   int ret;
451   ret = listen (desc->fd, backlog);
452
453 #ifdef MINGW
454   if (SOCKET_ERROR == ret)
455     SetErrnoFromWinsockError (WSAGetLastError ());
456
457 #endif
458   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
459 }
460
461
462 /**
463  * How much data is available to be read on this descriptor?
464  *
465  * Returns GNUNET_NO if no data is available, or on error!
466  * @param desc socket
467  */
468 ssize_t
469 GNUNET_NETWORK_socket_recvfrom_amount (const struct GNUNET_NETWORK_Handle
470                                        *desc)
471 {
472   int error;
473
474   /* How much is there to be read? */
475 #ifndef WINDOWS
476   int pending;
477   error = ioctl (desc->fd, FIONREAD, &pending);
478   if (error == 0)
479 #else
480   u_long pending;
481   error = ioctlsocket (desc->fd, FIONREAD, &pending);
482   if (error != SOCKET_ERROR)
483 #endif
484     return pending;
485   else
486     return GNUNET_NO;
487 }
488
489
490 /**
491  * Read data from a connected socket (always non-blocking).
492  * @param desc socket
493  * @param buffer buffer
494  * @param length length of buffer
495  * @param src_addr either the source to recv from, or all zeroes
496  *        to be filled in by recvfrom
497  * @param addrlen length of the addr
498  */
499 ssize_t
500 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
501                                 void *buffer, size_t length,
502                                 struct sockaddr * src_addr,
503                                 socklen_t * addrlen)
504 {
505   int ret;
506   int flags;
507   flags = 0;
508
509 #ifdef MSG_DONTWAIT
510   flags |= MSG_DONTWAIT;
511
512 #endif
513   ret = recvfrom (desc->fd, buffer, length, flags, src_addr, addrlen);
514 #ifdef MINGW
515   if (SOCKET_ERROR == ret)
516     SetErrnoFromWinsockError (WSAGetLastError ());
517 #endif 
518   return ret;
519 }
520
521
522 /**
523  * Read data from a connected socket (always non-blocking).
524  * @param desc socket
525  * @param buffer buffer
526  * @param length length of buffer
527  */
528 ssize_t
529 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
530                             void *buffer, size_t length)
531 {
532   int ret;
533   int flags;
534   flags = 0;
535
536 #ifdef MSG_DONTWAIT
537   flags |= MSG_DONTWAIT;
538 #endif
539   ret = recv (desc->fd, buffer, length, flags);
540 #ifdef MINGW
541   if (SOCKET_ERROR == ret)
542     SetErrnoFromWinsockError (WSAGetLastError ());
543 #endif
544   return ret;
545 }
546
547
548 /**
549  * Send data (always non-blocking).
550  *
551  * @param desc socket
552  * @param buffer data to send
553  * @param length size of the buffer
554  * @return number of bytes sent, GNUNET_SYSERR on error
555  */
556 ssize_t
557 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
558                             const void *buffer, size_t length)
559 {
560   int ret;
561   int flags;
562   flags = 0;
563
564 #ifdef MSG_DONTWAIT
565   flags |= MSG_DONTWAIT;
566
567 #endif
568 #ifdef MSG_NOSIGNAL
569   flags |= MSG_NOSIGNAL;
570
571 #endif
572   ret = send (desc->fd, buffer, length, flags);
573
574 #ifdef MINGW
575   if (SOCKET_ERROR == ret)
576     SetErrnoFromWinsockError (WSAGetLastError ());
577
578 #endif
579   return ret;
580 }
581
582
583 /**
584  * Send data to a particular destination (always non-blocking).
585  * This function only works for UDP sockets.
586  *
587  * @param desc socket
588  * @param message data to send
589  * @param length size of the data
590  * @param dest_addr destination address
591  * @param dest_len length of address
592  * @return number of bytes sent, GNUNET_SYSERR on error
593  */
594 ssize_t
595 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
596                               const void *message, size_t length,
597                               const struct sockaddr * dest_addr,
598                               socklen_t dest_len)
599 {
600   int ret;
601   int flags;
602   flags = 0;
603
604 #ifdef MSG_DONTWAIT
605   flags |= MSG_DONTWAIT;
606 #endif
607 #ifdef MSG_NOSIGNAL
608   flags |= MSG_NOSIGNAL;
609 #endif
610   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
611 #ifdef MINGW
612   if (SOCKET_ERROR == ret)
613     SetErrnoFromWinsockError (WSAGetLastError ());
614 #endif
615   return ret;
616 }
617
618
619 /**
620  * Set socket option
621  * @param fd socket
622  * @param level protocol level of the option
623  * @param option_name option identifier
624  * @param option_value value to set
625  * @param option_len size of option_value
626  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
627  */
628 int
629 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
630                                   int level, int option_name,
631                                   const void *option_value,
632                                   socklen_t option_len)
633 {
634   int ret;
635
636   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
637 #ifdef MINGW
638   if (SOCKET_ERROR == ret)
639     SetErrnoFromWinsockError (WSAGetLastError ());
640 #endif
641   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
642 }
643
644
645 /**
646  * Create a new socket.  Configure it for non-blocking IO and
647  * mark it as non-inheritable to child processes (set the
648  * close-on-exec flag).
649  *
650  * @param domain domain of the socket
651  * @param type socket type
652  * @param protocol network protocol
653  * @return new socket, NULL on error
654  */
655 struct GNUNET_NETWORK_Handle *
656 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
657 {
658   struct GNUNET_NETWORK_Handle *ret;
659
660   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
661   ret->af = domain;
662   ret->fd = socket (domain, type, protocol);
663   if (INVALID_SOCKET == ret->fd)
664     {
665 #ifdef MINGW
666       SetErrnoFromWinsockError (WSAGetLastError ());
667 #endif
668       GNUNET_free (ret);
669       return NULL;
670     }
671
672 #ifndef MINGW
673   if (ret->fd >= FD_SETSIZE)
674     {
675       GNUNET_break (0 == close (ret->fd));
676       GNUNET_free (ret);
677       errno = EMFILE;
678       return NULL;
679     }
680
681 #endif
682   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
683     {
684       /* we might want to treat this one as fatal... */
685       GNUNET_break (0);
686       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
687       return NULL;
688     }
689
690 #ifndef MINGW
691   if (GNUNET_OK != socket_set_inheritable (ret))
692     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
693                          "socket_set_inheritable");
694 #endif
695 #ifdef DARWIN
696   socket_set_nosigpipe (ret);
697 #endif
698   if ( (type == SOCK_STREAM) 
699 #ifdef AF_UNIX
700        && (domain != AF_UNIX) 
701 #endif
702        )
703     socket_set_nodelay (ret);
704   return ret;
705 }
706
707
708 /**
709  * Shut down socket operations
710  * @param desc socket
711  * @param how type of shutdown
712  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
713  */
714 int
715 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
716 {
717   int ret;
718
719   ret = shutdown (desc->fd, how);
720 #ifdef MINGW
721   if (ret != 0)
722     SetErrnoFromWinsockError (WSAGetLastError ());
723 #endif
724   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
725 }
726
727
728 /**
729  * Disable the "CORK" feature for communication with the given socket,
730  * forcing the OS to immediately flush the buffer on transmission
731  * instead of potentially buffering multiple messages.  Essentially
732  * reduces the OS send buffers to zero.
733  *
734  * @param desc socket
735  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
736  */
737 int
738 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
739 {
740   int value = 0;
741   int ret = 0;
742
743   if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
744     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
745   if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
746     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
747
748   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
749 }
750
751
752 /**
753  * Reset FD set
754  * @param fds fd set
755  */
756 void
757 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
758 {
759   FD_ZERO (&fds->sds);
760   fds->nsds = 0;
761 #ifdef MINGW
762   GNUNET_CONTAINER_slist_clear (fds->handles);
763 #endif
764 }
765
766 /**
767  * Add a socket to the FD set
768  * @param fds fd set
769  * @param desc socket to add
770  */
771 void
772 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
773                           const struct GNUNET_NETWORK_Handle *desc)
774 {
775   FD_SET (desc->fd, &fds->sds);
776   if (desc->fd + 1 > fds->nsds)
777     fds->nsds = desc->fd + 1;
778 }
779
780
781 /**
782  * Check whether a socket is part of the fd set
783  * @param fds fd set
784  * @param desc socket
785  * @return 0 if the FD is not set
786  */
787 int
788 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
789                             const struct GNUNET_NETWORK_Handle *desc)
790 {
791   return FD_ISSET (desc->fd, &fds->sds);
792 }
793
794
795 /**
796  * Add one fd set to another
797  * @param dst the fd set to add to
798  * @param src the fd set to add from
799  */
800 void
801 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
802                           const struct GNUNET_NETWORK_FDSet *src)
803 {
804   int nfds;
805   for (nfds = src->nsds; nfds > 0; nfds--)
806     if (FD_ISSET (nfds, &src->sds))
807
808       {
809         FD_SET (nfds, &dst->sds);
810         if (nfds + 1 > dst->nsds)
811           dst->nsds = nfds + 1;
812       }
813 #ifdef MINGW
814   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
815 #endif
816 }
817
818
819 /**
820  * Copy one fd set to another
821  *
822  * @param to destination
823  * @param from source
824  */
825 void
826 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
827                            const struct GNUNET_NETWORK_FDSet *from)
828 {
829   FD_COPY (&from->sds, &to->sds);
830   to->nsds = from->nsds;
831
832 #ifdef MINGW
833   GNUNET_CONTAINER_slist_clear (to->handles);
834   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
835 #endif
836 }
837
838
839 /**
840  * Return file descriptor for this network handle
841  *
842  * @param desc wrapper to process
843  * @return POSIX file descriptor
844  */
845 int
846 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
847 {
848   return desc->fd;
849 }
850
851
852 /**
853  * Copy a native fd set
854  *
855  * @param to destination
856  * @param from native source set
857  * @param nfds the biggest socket number in from + 1
858  */
859 void
860 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
861                                   const fd_set * from, int nfds)
862 {
863   FD_COPY (from, &to->sds);
864   to->nsds = nfds;
865 }
866
867
868 /**
869  * Set a native fd in a set
870  *
871  * @param to destination
872  * @param nfd native FD to set
873  */
874 void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
875                                       int nfd)
876 {
877   GNUNET_assert((nfd >= 0) && (nfd < FD_SETSIZE));
878   FD_SET (nfd, &to->sds);
879   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
880 }
881
882
883 /**
884  * Test native fd in a set
885  *
886  * @param to set to test, NULL for empty set
887  * @param nfd native FD to test, or -1 for none
888  * @return GNUNET_YES if FD is set in the set
889  */
890 int 
891 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
892                                   int nfd)
893 {
894   if ( (nfd == -1) || (to == NULL) )
895     return GNUNET_NO;
896   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
897 }
898
899
900 /**
901  * Add a file handle to the fd set
902  * @param fds fd set
903  * @param h the file handle to add
904  */
905 void
906 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
907                                  const struct GNUNET_DISK_FileHandle *h)
908 {
909 #ifdef MINGW
910   GNUNET_CONTAINER_slist_add (fds->handles,
911                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
912                               h, sizeof (struct GNUNET_DISK_FileHandle));
913
914 #else
915   int fd;
916   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
917   FD_SET (fd, &fds->sds);
918   if (fd + 1 > fds->nsds)
919     fds->nsds = fd + 1;
920
921 #endif
922 }
923
924
925 /**
926  * Check if a file handle is part of an fd set
927  * @param fds fd set
928  * @param h file handle
929  * @return GNUNET_YES if the file handle is part of the set
930  */
931 int
932 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
933                                    const struct GNUNET_DISK_FileHandle *h)
934 {
935
936 #ifdef MINGW
937   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
938                                           sizeof (struct GNUNET_DISK_FileHandle));
939 #else
940   return FD_ISSET (h->fd, &fds->sds);
941 #endif
942 }
943
944
945 /**
946  * Checks if two fd sets overlap
947  * @param fds1 first fd set
948  * @param fds2 second fd set
949  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
950  */
951 int
952 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
953                               const struct GNUNET_NETWORK_FDSet *fds2)
954 {
955 #ifndef MINGW
956   int nfds;
957
958   nfds = fds1->nsds;
959   if (nfds > fds2->nsds)
960     nfds = fds2->nsds;
961   while (nfds > 0)
962     {
963       nfds--;
964       if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
965         return GNUNET_YES;
966     }
967 #else
968   struct GNUNET_CONTAINER_SList_Iterator *it;
969   struct GNUNET_DISK_FileHandle *h;
970   int i;
971   int j;
972
973   /*This code is somewhat hacky, we are not supposed to know what's
974     inside of fd_set; also the O(n^2) is really bad... */
975
976   for (i = 0; i < fds1->sds.fd_count; i++)
977   {
978     for (j = 0; j < fds2->sds.fd_count; j++)
979     {
980       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
981         return GNUNET_YES;
982     }
983   }
984   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
985   while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES)
986     {
987       h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL);
988       if (GNUNET_CONTAINER_slist_contains
989           (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
990         {
991           GNUNET_CONTAINER_slist_iter_destroy (it);
992           return GNUNET_YES;
993         }
994       GNUNET_CONTAINER_slist_next (it);
995     }
996   GNUNET_CONTAINER_slist_iter_destroy (it);
997 #endif
998   return GNUNET_NO;
999 }
1000
1001
1002 /**
1003  * Creates an fd set
1004  * @return a new fd set
1005  */
1006 struct GNUNET_NETWORK_FDSet *
1007 GNUNET_NETWORK_fdset_create ()
1008 {
1009   struct GNUNET_NETWORK_FDSet *fds;
1010   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1011 #ifdef MINGW
1012   fds->handles = GNUNET_CONTAINER_slist_create ();
1013 #endif
1014   GNUNET_NETWORK_fdset_zero (fds);
1015   return fds;
1016 }
1017
1018
1019 /**
1020  * Releases the associated memory of an fd set
1021  * @param fds fd set
1022  */
1023 void
1024 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1025 {
1026 #ifdef MINGW
1027   GNUNET_CONTAINER_slist_destroy (fds->handles);
1028 #endif
1029   GNUNET_free (fds);
1030 }
1031
1032 /**
1033  * Check if sockets meet certain conditions
1034  * @param rfds set of sockets to be checked for readability
1035  * @param wfds set of sockets to be checked for writability
1036  * @param efds set of sockets to be checked for exceptions
1037  * @param timeout relative value when to return
1038  * @return number of selected sockets, GNUNET_SYSERR on error
1039  */
1040 int
1041 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1042                               struct GNUNET_NETWORK_FDSet *wfds,
1043                               struct GNUNET_NETWORK_FDSet *efds,
1044                               const struct GNUNET_TIME_Relative timeout)
1045 {
1046   int nfds;
1047 #ifdef MINGW
1048   int handles;
1049 #endif
1050   nfds = 0;
1051 #ifdef MINGW
1052   handles = 0;
1053 #endif
1054   if (NULL != rfds)
1055     {
1056       nfds = rfds->nsds;
1057 #ifdef MINGW
1058       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1059 #endif
1060     }
1061   if (NULL != wfds)
1062     {
1063       nfds = GNUNET_MAX (nfds, wfds->nsds);
1064 #ifdef MINGW
1065       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
1066 #endif
1067     }
1068   if (NULL != efds)
1069     {
1070       nfds = GNUNET_MAX (nfds, efds->nsds);
1071 #ifdef MINGW
1072       handles += GNUNET_CONTAINER_slist_count (efds->handles);
1073 #endif
1074     }
1075
1076   struct timeval tv;
1077   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1078   tv.tv_usec =
1079     1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1080   if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1081 #ifdef MINGW
1082       && handles == 0
1083 #endif
1084     )
1085     {
1086       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1087                   _
1088                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1089                   "select");
1090       GNUNET_break (0);
1091     }
1092 #ifndef MINGW
1093   return select (nfds,
1094                  (rfds != NULL) ? &rfds->sds : NULL,
1095                  (wfds != NULL) ? &wfds->sds : NULL,
1096                  (efds != NULL) ? &efds->sds : NULL,
1097                  (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1098                  ? NULL : &tv);
1099
1100 #else
1101   DWORD limit;
1102   fd_set sock_read, sock_write, sock_except;
1103   fd_set aread, awrite, aexcept;
1104   struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
1105     *handles_except;
1106
1107   int i;
1108   struct timeval tvslice;
1109   int retcode;
1110   DWORD ms_total;
1111   /* Number of milliseconds per cycle. Adapted on the fly */
1112   static unsigned int cycle_delay = 20;
1113
1114 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1115
1116   /* calculate how long we need to wait in milliseconds */
1117   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1118     ms_total = INFINITE;
1119
1120   else
1121     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1122
1123   /* select() may be used as a portable way to sleep */
1124   if (!(rfds || wfds || efds))
1125
1126     {
1127       Sleep (ms_total);
1128       return 0;
1129     }
1130
1131   handles_read = GNUNET_CONTAINER_slist_create ();
1132   handles_write = GNUNET_CONTAINER_slist_create ();
1133   handles_except = GNUNET_CONTAINER_slist_create ();
1134
1135   if (rfds)
1136     sock_read = rfds->sds;
1137   else
1138     FD_ZERO (&sock_read);
1139   if (wfds)
1140     sock_write = wfds->sds;
1141   else
1142     FD_ZERO (&sock_write);
1143   if (efds)
1144     sock_except = efds->sds;
1145   else
1146     FD_ZERO (&sock_except);
1147
1148   /* multiplex between winsock select() and waiting on the handles */
1149   FD_ZERO (&aread);
1150   FD_ZERO (&awrite);
1151   FD_ZERO (&aexcept);
1152
1153 #if DEBUG_W32_CYCLES
1154   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1155               "Starting a cycle, delay is %dms. nfds is %d.\n", cycle_delay, nfds);
1156 #endif
1157
1158   limit = GetTickCount () + ms_total;
1159
1160   do
1161     {
1162       retcode = 0;
1163       if (nfds > 0)
1164
1165         {
1166
1167           /* overwrite the zero'd sets here; the select call
1168            * will clear those that are not active */
1169           FD_COPY (&sock_read, &aread);
1170           FD_COPY (&sock_write, &awrite);
1171           FD_COPY (&sock_except, &aexcept);
1172           tvslice.tv_sec = 0;
1173           tvslice.tv_usec = cycle_delay;
1174 #if DEBUG_W32_CYCLES
1175           {
1176             for (i = 0; i < nfds; i++)
1177             {
1178               if (SAFE_FD_ISSET (i, &sock_read))
1179               {
1180                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1181                      "Going to select socket %d for reading\n", i);
1182               }
1183               if (SAFE_FD_ISSET (i, &sock_write))
1184               {
1185                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1186                      "Going to select socket %d for writing\n", i);
1187               }
1188               if (SAFE_FD_ISSET (i, &sock_except))
1189               {
1190                 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1191                      "Going to select socket %d for exceptions\n", i);
1192               }
1193             }
1194           }
1195           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1196                      "Waiting for %d microseconds, %d left\n", cycle_delay, (limit - GetTickCount ())*1000);
1197 #endif
1198           if ((retcode =
1199                select (nfds + 1, &aread, &awrite, &aexcept,
1200                        &tvslice)) == SOCKET_ERROR)
1201
1202             {
1203               SetErrnoFromWinsockError (WSAGetLastError ());
1204               if (errno == ENOTSOCK)
1205                 errno = EBADF;
1206
1207 #if DEBUG_NETWORK
1208               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
1209
1210 #endif
1211               goto select_loop_end;
1212             }
1213 #if DEBUG_W32_CYCLES
1214           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1215                      "Select () returned %d, GLE is %d\n", retcode, GetLastError ());
1216 #endif
1217         }
1218
1219       /* Poll read pipes */
1220       if (rfds)
1221         {
1222           struct GNUNET_CONTAINER_SList_Iterator *i;
1223 #if DEBUG_W32_CYCLES
1224           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1225                      "Polling rfds for readable pipes\n");
1226 #endif
1227           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1228                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1229                GNUNET_CONTAINER_slist_next (i))
1230
1231             {
1232               struct GNUNET_DISK_FileHandle *fh;
1233               DWORD dwBytes;
1234               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1235               if (fh->type == GNUNET_PIPE)
1236                 {
1237 #if DEBUG_W32_CYCLES
1238                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1239                      "Polling pipe 0x%x (0x%x)\n", fh, fh->h);
1240 #endif
1241                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1242                     {
1243                       DWORD error_code = GetLastError ();
1244                       switch (error_code)
1245                       {
1246                       case ERROR_BROKEN_PIPE:
1247                         GNUNET_CONTAINER_slist_add (handles_read,
1248                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1249                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1250                         retcode++;
1251                         break;
1252                       default:
1253                         retcode = -1;
1254                         SetErrnoFromWinError (error_code);
1255
1256     #if DEBUG_NETWORK
1257                         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1258                                              "PeekNamedPipe");
1259
1260     #endif
1261                         goto select_loop_end;
1262                       }
1263                     }
1264                   else if (dwBytes)
1265
1266                     {
1267                       GNUNET_CONTAINER_slist_add (handles_read,
1268                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1269                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1270                       retcode++;
1271                     }
1272                 }
1273               else
1274                 {
1275                   /* Should we wait for more bytes to read here (in case of previous EOF)? */
1276                   GNUNET_CONTAINER_slist_add (handles_read,
1277                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1278                                               fh, sizeof (struct GNUNET_DISK_FileHandle));
1279                 }
1280             }
1281           GNUNET_CONTAINER_slist_iter_destroy (i);
1282         }
1283
1284       /* Poll for faulty pipes */
1285       if (efds)
1286
1287         {
1288 #if DEBUG_W32_CYCLES
1289           GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1290                      "Polling efds for broken pipes\n");
1291 #endif
1292           struct GNUNET_CONTAINER_SList_Iterator *i;
1293           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1294                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1295                GNUNET_CONTAINER_slist_next (i))
1296
1297             {
1298               struct GNUNET_DISK_FileHandle *fh;
1299               DWORD dwBytes;
1300
1301               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1302               if (fh->type == GNUNET_PIPE)
1303                 {
1304 #if DEBUG_W32_CYCLES
1305                   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1306                               "Polling pipe 0x%x (0x%x)\n", fh, fh->h);
1307 #endif
1308                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1309
1310                     {
1311                       GNUNET_CONTAINER_slist_add (handles_except,
1312                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1313                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1314                       retcode++;
1315                     }
1316                 }
1317             }
1318           GNUNET_CONTAINER_slist_iter_destroy (i);
1319         }
1320
1321       if (wfds)
1322         {
1323           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1324           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1325         }
1326
1327       /* Check for closed sockets */
1328       for (i = 0; i < nfds; i++)
1329
1330         {
1331           if (SAFE_FD_ISSET (i, &sock_read))
1332
1333             {
1334               struct sockaddr addr;
1335               int len;
1336               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1337
1338                 {
1339                   int err, len;
1340                   len = sizeof (err);
1341                   if (getsockopt
1342                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1343                       && err == WSAENOTCONN)
1344
1345                     {
1346                       if (!SAFE_FD_ISSET (i, &aread))
1347
1348                         {
1349                           FD_SET (i, &aread);
1350                           retcode++;
1351                         }
1352                     }
1353                 }
1354             }
1355         }
1356     select_loop_end:
1357       if (retcode == 0)
1358       {
1359         /* For pipes, there have been no select() call, so the poll is
1360          * more likely to miss first time around. For now just don't increase
1361          * the delay for pipes only.
1362          */
1363         if (nfds != 0)
1364           cycle_delay = cycle_delay * 2 > 250000 ? 250000 : cycle_delay * 1.4;
1365         /* Missed an I/O - double the cycle time */
1366 #if DEBUG_W32_CYCLES
1367         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1368                     "The cycle missed, increased the delay to %dms\n", cycle_delay);
1369 #endif
1370       }
1371       else
1372       {
1373         /* Successfully selected something - decrease the cycle time */
1374         /* Minimum is 5 microseconds. Decrease the delay by half,
1375          * or by 5000 - whichever is higher.
1376          */
1377         cycle_delay -= cycle_delay > 5000 ? GNUNET_MAX (5000, cycle_delay / 2) : cycle_delay - 5;
1378 #if DEBUG_W32_CYCLES
1379         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1380                     "The cycle hit, decreased the delay to %dms\n", cycle_delay);
1381 #endif
1382       }
1383       if (retcode == 0 && nfds == 0)
1384       {
1385         long long diff = limit - GetTickCount ();
1386         diff = diff > 0 ? diff : 0;
1387 #if DEBUG_W32_CYCLES
1388         GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
1389                     "No sockets, sleeping for %d or %d ms\n", cycle_delay / 1000, diff);
1390 #endif
1391         Sleep (GNUNET_MIN (cycle_delay / 1000, diff));
1392       }
1393     }
1394   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1395
1396   if (retcode != -1)
1397     {
1398       if (rfds)
1399         {
1400           GNUNET_NETWORK_fdset_zero (rfds);
1401           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1402           GNUNET_CONTAINER_slist_clear (rfds->handles);
1403           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1404         }
1405       if (wfds)
1406         {
1407           GNUNET_NETWORK_fdset_zero (wfds);
1408           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1409           GNUNET_CONTAINER_slist_clear (wfds->handles);
1410           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1411         }
1412       if (efds)
1413         {
1414           GNUNET_NETWORK_fdset_zero (efds);
1415           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1416           GNUNET_CONTAINER_slist_clear (efds->handles);
1417           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1418         }
1419     }
1420
1421   GNUNET_CONTAINER_slist_destroy (handles_read);
1422   GNUNET_CONTAINER_slist_destroy (handles_write);
1423   GNUNET_CONTAINER_slist_destroy (handles_except);
1424
1425   return retcode;
1426 #endif
1427 }
1428
1429
1430 /* end of network.c */