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