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