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