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