(no commit message)
[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   ret = send (desc->fd, buffer, length, flags);
569
570 #ifdef MINGW
571   if (SOCKET_ERROR == ret)
572     SetErrnoFromWinsockError (WSAGetLastError ());
573
574 #endif
575   return ret;
576 }
577
578
579 /**
580  * Send data to a particular destination (always non-blocking).
581  * This function only works for UDP sockets.
582  *
583  * @param desc socket
584  * @param message data to send
585  * @param length size of the data
586  * @param dest_addr destination address
587  * @param dest_len length of address
588  * @return number of bytes sent, GNUNET_SYSERR on error
589  */
590 ssize_t
591 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
592                               const void *message, size_t length,
593                               const struct sockaddr * dest_addr,
594                               socklen_t dest_len)
595 {
596   int ret;
597   int flags;
598   flags = 0;
599
600 #ifdef MSG_DONTWAIT
601   flags |= MSG_DONTWAIT;
602 #endif
603 #ifdef MSG_NOSIGNAL
604   flags |= MSG_NOSIGNAL;
605 #endif
606   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
607 #ifdef MINGW
608   if (SOCKET_ERROR == ret)
609     SetErrnoFromWinsockError (WSAGetLastError ());
610 #endif
611   return ret;
612 }
613
614
615 /**
616  * Set socket option
617  * @param fd socket
618  * @param level protocol level of the option
619  * @param option_name option identifier
620  * @param option_value value to set
621  * @param option_len size of option_value
622  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
623  */
624 int
625 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
626                                   int level, int option_name,
627                                   const void *option_value,
628                                   socklen_t option_len)
629 {
630   int ret;
631
632   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
633 #ifdef MINGW
634   if (SOCKET_ERROR == ret)
635     SetErrnoFromWinsockError (WSAGetLastError ());
636 #endif
637   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
638 }
639
640
641 /**
642  * Create a new socket.  Configure it for non-blocking IO and
643  * mark it as non-inheritable to child processes (set the
644  * close-on-exec flag).
645  *
646  * @param domain domain of the socket
647  * @param type socket type
648  * @param protocol network protocol
649  * @return new socket, NULL on error
650  */
651 struct GNUNET_NETWORK_Handle *
652 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
653 {
654   struct GNUNET_NETWORK_Handle *ret;
655
656   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
657   ret->af = domain;
658   ret->fd = socket (domain, type, protocol);
659   if (INVALID_SOCKET == ret->fd)
660     {
661 #ifdef MINGW
662       SetErrnoFromWinsockError (WSAGetLastError ());
663 #endif
664       GNUNET_free (ret);
665       return NULL;
666     }
667
668 #ifndef MINGW
669   if (ret->fd >= FD_SETSIZE)
670     {
671       GNUNET_break (0 == close (ret->fd));
672       GNUNET_free (ret);
673       errno = EMFILE;
674       return NULL;
675     }
676
677 #endif
678   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
679     {
680       /* we might want to treat this one as fatal... */
681       GNUNET_break (0);
682       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
683       return NULL;
684     }
685
686 #ifndef MINGW
687   if (GNUNET_OK != socket_set_inheritable (ret))
688     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
689                          "socket_set_inheritable");
690 #endif
691 #ifdef DARWIN
692   socket_set_nosigpipe (ret);
693 #endif
694   if ( (type == SOCK_STREAM) 
695 #ifdef AF_UNIX
696        && (domain != AF_UNIX) 
697 #endif
698        )
699     socket_set_nodelay (ret);
700   return ret;
701 }
702
703
704 /**
705  * Shut down socket operations
706  * @param desc socket
707  * @param how type of shutdown
708  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
709  */
710 int
711 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
712 {
713   int ret;
714
715   ret = shutdown (desc->fd, how);
716 #ifdef MINGW
717   if (ret != 0)
718     SetErrnoFromWinsockError (WSAGetLastError ());
719 #endif
720   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
721 }
722
723
724 /**
725  * Disable the "CORK" feature for communication with the given socket,
726  * forcing the OS to immediately flush the buffer on transmission
727  * instead of potentially buffering multiple messages.  Essentially
728  * reduces the OS send buffers to zero.
729  *
730  * @param desc socket
731  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
732  */
733 int
734 GNUNET_NETWORK_socket_disable_corking (struct GNUNET_NETWORK_Handle *desc)
735 {
736   int value = 0;
737   int ret = 0;
738
739   if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_SNDBUF, &value, sizeof (value))))
740     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
741   if (0 != (ret = setsockopt (desc->fd, SOL_SOCKET, SO_RCVBUF, &value, sizeof (value))))
742     GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "setsockopt");
743
744   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
745 }
746
747
748 /**
749  * Reset FD set
750  * @param fds fd set
751  */
752 void
753 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
754 {
755   FD_ZERO (&fds->sds);
756   fds->nsds = 0;
757 #ifdef MINGW
758   GNUNET_CONTAINER_slist_clear (fds->handles);
759 #endif
760 }
761
762 /**
763  * Add a socket to the FD set
764  * @param fds fd set
765  * @param desc socket to add
766  */
767 void
768 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
769                           const struct GNUNET_NETWORK_Handle *desc)
770 {
771   FD_SET (desc->fd, &fds->sds);
772   if (desc->fd + 1 > fds->nsds)
773     fds->nsds = desc->fd + 1;
774 }
775
776
777 /**
778  * Check whether a socket is part of the fd set
779  * @param fds fd set
780  * @param desc socket
781  * @return 0 if the FD is not set
782  */
783 int
784 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
785                             const struct GNUNET_NETWORK_Handle *desc)
786 {
787   return FD_ISSET (desc->fd, &fds->sds);
788 }
789
790
791 /**
792  * Add one fd set to another
793  * @param dst the fd set to add to
794  * @param src the fd set to add from
795  */
796 void
797 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
798                           const struct GNUNET_NETWORK_FDSet *src)
799 {
800   int nfds;
801   for (nfds = src->nsds; nfds > 0; nfds--)
802     if (FD_ISSET (nfds, &src->sds))
803
804       {
805         FD_SET (nfds, &dst->sds);
806         if (nfds + 1 > dst->nsds)
807           dst->nsds = nfds + 1;
808       }
809 #ifdef MINGW
810   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
811 #endif
812 }
813
814
815 /**
816  * Copy one fd set to another
817  *
818  * @param to destination
819  * @param from source
820  */
821 void
822 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
823                            const struct GNUNET_NETWORK_FDSet *from)
824 {
825   FD_COPY (&from->sds, &to->sds);
826   to->nsds = from->nsds;
827
828 #ifdef MINGW
829   GNUNET_CONTAINER_slist_clear (to->handles);
830   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
831 #endif
832 }
833
834
835 /**
836  * Return file descriptor for this network handle
837  *
838  * @param desc wrapper to process
839  * @return POSIX file descriptor
840  */
841 int
842 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
843 {
844   return desc->fd;
845 }
846
847
848 /**
849  * Copy a native fd set
850  *
851  * @param to destination
852  * @param from native source set
853  * @param nfds the biggest socket number in from + 1
854  */
855 void
856 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
857                                   const fd_set * from, int nfds)
858 {
859   FD_COPY (from, &to->sds);
860   to->nsds = nfds;
861 }
862
863
864 /**
865  * Set a native fd in a set
866  *
867  * @param to destination
868  * @param nfd native FD to set
869  */
870 void GNUNET_NETWORK_fdset_set_native (struct GNUNET_NETWORK_FDSet *to,
871                                       int nfd)
872 {
873   GNUNET_assert(nfd >= 0);
874   FD_SET (nfd, &to->sds);
875   to->nsds = GNUNET_MAX (nfd + 1, to->nsds);
876 }
877
878
879 /**
880  * Test native fd in a set
881  *
882  * @param to set to test, NULL for empty set
883  * @param nfd native FD to test, or -1 for none
884  * @return GNUNET_YES if FD is set in the set
885  */
886 int 
887 GNUNET_NETWORK_fdset_test_native (const struct GNUNET_NETWORK_FDSet *to,
888                                   int nfd)
889 {
890   if ( (nfd == -1) || (to == NULL) )
891     return GNUNET_NO;
892   return FD_ISSET (nfd, &to->sds) ? GNUNET_YES : GNUNET_NO;
893 }
894
895
896 /**
897  * Add a file handle to the fd set
898  * @param fds fd set
899  * @param h the file handle to add
900  */
901 void
902 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
903                                  const struct GNUNET_DISK_FileHandle *h)
904 {
905 #ifdef MINGW
906   GNUNET_CONTAINER_slist_add (fds->handles,
907                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
908                               h, sizeof (struct GNUNET_DISK_FileHandle));
909
910 #else
911   int fd;
912   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
913   FD_SET (fd, &fds->sds);
914   if (fd + 1 > fds->nsds)
915     fds->nsds = fd + 1;
916
917 #endif
918 }
919
920
921 /**
922  * Check if a file handle is part of an fd set
923  * @param fds fd set
924  * @param h file handle
925  * @return GNUNET_YES if the file handle is part of the set
926  */
927 int
928 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
929                                    const struct GNUNET_DISK_FileHandle *h)
930 {
931
932 #ifdef MINGW
933   return GNUNET_CONTAINER_slist_contains (fds->handles, h,
934                                           sizeof (struct GNUNET_DISK_FileHandle));
935 #else
936   return FD_ISSET (h->fd, &fds->sds);
937 #endif
938 }
939
940
941 /**
942  * Checks if two fd sets overlap
943  * @param fds1 first fd set
944  * @param fds2 second fd set
945  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
946  */
947 int
948 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
949                               const struct GNUNET_NETWORK_FDSet *fds2)
950 {
951 #ifndef MINGW
952   int nfds;
953
954   nfds = fds1->nsds;
955   if (nfds > fds2->nsds)
956     nfds = fds2->nsds;
957   while (nfds > 0)
958     {
959       nfds--;
960       if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
961         return GNUNET_YES;
962     }
963 #else
964   struct GNUNET_CONTAINER_SList_Iterator *it;
965   struct GNUNET_DISK_FileHandle *h;
966   int i;
967   int j;
968
969   /*This code is somewhat hacky, we are not supposed to know what's
970     inside of fd_set; also the O(n^2) is really bad... */
971
972   for (i = 0; i < fds1->sds.fd_count; i++)
973   {
974     for (j = 0; j < fds2->sds.fd_count; j++)
975     {
976       if (fds1->sds.fd_array[i] == fds2->sds.fd_array[j])
977         return GNUNET_YES;
978     }
979   }
980   it = GNUNET_CONTAINER_slist_begin (fds1->handles);
981   while (GNUNET_CONTAINER_slist_end (it) != GNUNET_YES)
982     {
983       h = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (it, NULL);
984       if (GNUNET_CONTAINER_slist_contains
985           (fds2->handles, h, sizeof (struct GNUNET_DISK_FileHandle)))
986         {
987           GNUNET_CONTAINER_slist_iter_destroy (it);
988           return GNUNET_YES;
989         }
990       GNUNET_CONTAINER_slist_next (it);
991     }
992   GNUNET_CONTAINER_slist_iter_destroy (it);
993 #endif
994   return GNUNET_NO;
995 }
996
997
998 /**
999  * Creates an fd set
1000  * @return a new fd set
1001  */
1002 struct GNUNET_NETWORK_FDSet *
1003 GNUNET_NETWORK_fdset_create ()
1004 {
1005   struct GNUNET_NETWORK_FDSet *fds;
1006   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
1007 #ifdef MINGW
1008   fds->handles = GNUNET_CONTAINER_slist_create ();
1009 #endif
1010   GNUNET_NETWORK_fdset_zero (fds);
1011   return fds;
1012 }
1013
1014
1015 /**
1016  * Releases the associated memory of an fd set
1017  * @param fds fd set
1018  */
1019 void
1020 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
1021 {
1022 #ifdef MINGW
1023   GNUNET_CONTAINER_slist_destroy (fds->handles);
1024 #endif
1025   GNUNET_free (fds);
1026 }
1027
1028 /**
1029  * Check if sockets meet certain conditions
1030  * @param rfds set of sockets to be checked for readability
1031  * @param wfds set of sockets to be checked for writability
1032  * @param efds set of sockets to be checked for exceptions
1033  * @param timeout relative value when to return
1034  * @return number of selected sockets, GNUNET_SYSERR on error
1035  */
1036 int
1037 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
1038                               struct GNUNET_NETWORK_FDSet *wfds,
1039                               struct GNUNET_NETWORK_FDSet *efds,
1040                               const struct GNUNET_TIME_Relative timeout)
1041 {
1042   int nfds;
1043 #ifdef MINGW
1044   int handles;
1045 #endif
1046   nfds = 0;
1047 #ifdef MINGW
1048   handles = 0;
1049 #endif
1050   if (NULL != rfds)
1051     {
1052       nfds = rfds->nsds;
1053 #ifdef MINGW
1054       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
1055 #endif
1056     }
1057   if (NULL != wfds)
1058     {
1059       nfds = GNUNET_MAX (nfds, wfds->nsds);
1060 #ifdef MINGW
1061       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
1062 #endif
1063     }
1064   if (NULL != efds)
1065     {
1066       nfds = GNUNET_MAX (nfds, efds->nsds);
1067 #ifdef MINGW
1068       handles += GNUNET_CONTAINER_slist_count (efds->handles);
1069 #endif
1070     }
1071
1072   struct timeval tv;
1073   tv.tv_sec = timeout.rel_value / GNUNET_TIME_UNIT_SECONDS.rel_value;
1074   tv.tv_usec =
1075     1000 * (timeout.rel_value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.rel_value));
1076   if ((nfds == 0) && (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1077 #ifdef MINGW
1078       && handles == 0
1079 #endif
1080     )
1081     {
1082       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
1083                   _
1084                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
1085                   "select");
1086       GNUNET_break (0);
1087     }
1088 #ifndef MINGW
1089   return select (nfds,
1090                  (rfds != NULL) ? &rfds->sds : NULL,
1091                  (wfds != NULL) ? &wfds->sds : NULL,
1092                  (efds != NULL) ? &efds->sds : NULL,
1093                  (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1094                  ? NULL : &tv);
1095
1096 #else
1097   DWORD limit;
1098   fd_set sock_read, sock_write, sock_except;
1099   fd_set aread, awrite, aexcept;
1100   struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
1101     *handles_except;
1102
1103   int i;
1104   struct timeval tvslice;
1105   int retcode;
1106   DWORD ms_total;
1107
1108 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
1109
1110   /* calculate how long we need to wait in milliseconds */
1111   if (timeout.rel_value == GNUNET_TIME_UNIT_FOREVER_REL.rel_value)
1112     ms_total = INFINITE;
1113
1114   else
1115     ms_total = timeout.rel_value / GNUNET_TIME_UNIT_MILLISECONDS.rel_value;
1116
1117   /* select() may be used as a portable way to sleep */
1118   if (!(rfds || wfds || efds))
1119
1120     {
1121       Sleep (ms_total);
1122       return 0;
1123     }
1124
1125   handles_read = GNUNET_CONTAINER_slist_create ();
1126   handles_write = GNUNET_CONTAINER_slist_create ();
1127   handles_except = GNUNET_CONTAINER_slist_create ();
1128
1129   if (rfds)
1130     sock_read = rfds->sds;
1131   else
1132     FD_ZERO (&sock_read);
1133   if (wfds)
1134     sock_write = wfds->sds;
1135   else
1136     FD_ZERO (&sock_write);
1137   if (efds)
1138     sock_except = efds->sds;
1139   else
1140     FD_ZERO (&sock_except);
1141
1142   /* multiplex between winsock select() and waiting on the handles */
1143   FD_ZERO (&aread);
1144   FD_ZERO (&awrite);
1145   FD_ZERO (&aexcept);
1146   limit = GetTickCount () + ms_total;
1147
1148   do
1149     {
1150       retcode = 0;
1151       if (nfds > 0)
1152
1153         {
1154
1155           /* overwrite the zero'd sets here; the select call
1156            * will clear those that are not active */
1157           FD_COPY (&sock_read, &aread);
1158           FD_COPY (&sock_write, &awrite);
1159           FD_COPY (&sock_except, &aexcept);
1160           tvslice.tv_sec = 0;
1161           tvslice.tv_usec = 100000;
1162           if ((retcode =
1163                select (nfds + 1, &aread, &awrite, &aexcept,
1164                        &tvslice)) == SOCKET_ERROR)
1165
1166             {
1167               SetErrnoFromWinsockError (WSAGetLastError ());
1168               if (errno == ENOTSOCK)
1169                 errno = EBADF;
1170
1171 #if DEBUG_NETWORK
1172               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
1173
1174 #endif
1175               goto select_loop_end;
1176             }
1177         }
1178
1179       /* Poll read pipes */
1180       if (rfds)
1181
1182         {
1183           struct GNUNET_CONTAINER_SList_Iterator *i;
1184           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1185                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1186                GNUNET_CONTAINER_slist_next (i))
1187
1188             {
1189               struct GNUNET_DISK_FileHandle *fh;
1190               DWORD dwBytes;
1191               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1192               if (fh->type == GNUNET_PIPE)
1193                 {
1194                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1195                     {
1196                       DWORD error_code = GetLastError ();
1197                       switch (error_code)
1198                       {
1199                       case ERROR_BROKEN_PIPE:
1200                         GNUNET_CONTAINER_slist_add (handles_read,
1201                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1202                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1203                         retcode++;
1204                         break;
1205                       default:
1206                         retcode = -1;
1207                         SetErrnoFromWinError (error_code);
1208
1209     #if DEBUG_NETWORK
1210                         GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1211                                              "PeekNamedPipe");
1212
1213     #endif
1214                         goto select_loop_end;
1215                       }
1216                     }
1217                   else if (dwBytes)
1218
1219                     {
1220                       GNUNET_CONTAINER_slist_add (handles_read,
1221                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1222                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1223                       retcode++;
1224                     }
1225                 }
1226               else
1227                 {
1228                   /* Should we wait for more bytes to read here (in case of previous EOF)? */
1229                   GNUNET_CONTAINER_slist_add (handles_read,
1230                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1231                                               fh, sizeof (struct GNUNET_DISK_FileHandle));
1232                 }
1233             }
1234           GNUNET_CONTAINER_slist_iter_destroy (i);
1235         }
1236
1237       /* Poll for faulty pipes */
1238       if (efds)
1239
1240         {
1241           struct GNUNET_CONTAINER_SList_Iterator *i;
1242           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1243                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1244                GNUNET_CONTAINER_slist_next (i))
1245
1246             {
1247               struct GNUNET_DISK_FileHandle *fh;
1248               DWORD dwBytes;
1249
1250               fh = (struct GNUNET_DISK_FileHandle *) GNUNET_CONTAINER_slist_get (i, NULL);
1251               if (fh->type == GNUNET_PIPE)
1252                 {
1253                   if (!PeekNamedPipe (fh->h, NULL, 0, NULL, &dwBytes, NULL))
1254
1255                     {
1256                       GNUNET_CONTAINER_slist_add (handles_except,
1257                                                   GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1258                                                   fh, sizeof (struct GNUNET_DISK_FileHandle));
1259                       retcode++;
1260                     }
1261                 }
1262             }
1263           GNUNET_CONTAINER_slist_iter_destroy (i);
1264         }
1265
1266       if (wfds)
1267         {
1268           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1269           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1270         }
1271
1272       /* Check for closed sockets */
1273       for (i = 0; i < nfds; i++)
1274
1275         {
1276           if (SAFE_FD_ISSET (i, &sock_read))
1277
1278             {
1279               struct sockaddr addr;
1280               int len;
1281               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1282
1283                 {
1284                   int err, len;
1285                   len = sizeof (err);
1286                   if (getsockopt
1287                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1288                       && err == WSAENOTCONN)
1289
1290                     {
1291                       if (!SAFE_FD_ISSET (i, &aread))
1292
1293                         {
1294                           FD_SET (i, &aread);
1295                           retcode++;
1296                         }
1297                     }
1298                 }
1299             }
1300         }
1301     select_loop_end:
1302       if (retcode == 0 && nfds == 0)
1303         Sleep (GNUNET_MIN (100, limit - GetTickCount ()));
1304     }
1305   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1306
1307   if (retcode != -1)
1308     {
1309       if (rfds)
1310         {
1311           GNUNET_NETWORK_fdset_zero (rfds);
1312           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1313           GNUNET_CONTAINER_slist_clear (rfds->handles);
1314           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1315         }
1316       if (wfds)
1317         {
1318           GNUNET_NETWORK_fdset_zero (wfds);
1319           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1320           GNUNET_CONTAINER_slist_clear (wfds->handles);
1321           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1322         }
1323       if (efds)
1324         {
1325           GNUNET_NETWORK_fdset_zero (efds);
1326           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1327           GNUNET_CONTAINER_slist_clear (efds->handles);
1328           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1329         }
1330     }
1331
1332   GNUNET_CONTAINER_slist_destroy (handles_read);
1333   GNUNET_CONTAINER_slist_destroy (handles_write);
1334   GNUNET_CONTAINER_slist_destroy (handles_except);
1335
1336   return retcode;
1337 #endif
1338 }
1339
1340
1341 /* end of network.c */