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