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