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