398f2b51a8cf14d8bf9a7a3c8fbdb9d51aa8feee
[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 * desc)
365 {
366   int error;
367   unsigned int pending;
368
369   /* How much is there to be read? */
370   error = ioctl(desc->fd, FIONREAD, &pending);
371   GNUNET_log_from(GNUNET_ERROR_TYPE_INFO, "udp", _
372             ("pending is %u bytes, error is %d\n"), pending, error);
373
374   if (error == 0)
375     return pending;
376   else
377     return GNUNET_NO;
378 }
379
380 /**
381  * Read data from a connected socket (always non-blocking).
382  * @param desc socket
383  * @param buffer buffer
384  * @param length length of buffer
385  * @param src_addr either the source to recv from, or all zeroes
386  *        to be filled in by recvfrom
387  * @param addrlen length of the addr
388  */
389 ssize_t
390 GNUNET_NETWORK_socket_recvfrom (const struct GNUNET_NETWORK_Handle * desc,
391                                 void *buffer, size_t length,
392                                 struct sockaddr *src_addr, 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, GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &hw, sizeof (HANDLE));
737
738 #else
739   int fd;
740   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
741   FD_SET (fd, &fds->sds);
742   if (fd + 1 > fds->nsds)
743     fds->nsds = fd + 1;
744
745 #endif
746 }
747
748
749 /**
750  * Check if a file handle is part of an fd set
751  * @param fds fd set
752  * @param h file handle
753  * @return GNUNET_YES if the file handle is part of the set
754  */
755 int
756 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
757                                    const struct GNUNET_DISK_FileHandle *h)
758 {
759
760 #ifdef MINGW
761   return GNUNET_CONTAINER_slist_contains (fds->handles, &h->h,
762                                           sizeof (HANDLE));
763 #else
764   return FD_ISSET (h->fd, &fds->sds);
765 #endif
766 }
767
768
769 /**
770  * Checks if two fd sets overlap
771  * @param fds1 first fd set
772  * @param fds2 second fd set
773  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
774  */
775 int
776 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
777                               const struct GNUNET_NETWORK_FDSet *fds2)
778 {
779   int nfds;
780   nfds = fds1->nsds;
781   if (nfds < fds2->nsds)
782     nfds = fds2->nsds;
783   for (; nfds >= 0; nfds--)
784     if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
785       return GNUNET_YES;
786 #ifdef MINGW
787   {
788       struct GNUNET_CONTAINER_SList_Iterator *it;
789
790       for(it = GNUNET_CONTAINER_slist_begin (fds1->handles); GNUNET_CONTAINER_slist_end (it) != GNUNET_YES; GNUNET_CONTAINER_slist_next (it))
791         {
792           HANDLE *h;
793
794           h = GNUNET_CONTAINER_slist_get (it, NULL);
795           if (GNUNET_CONTAINER_slist_contains (fds2->handles, h, sizeof (HANDLE)))
796             {
797               GNUNET_CONTAINER_slist_iter_destroy (it);
798               return GNUNET_YES;
799             }
800         }
801       GNUNET_CONTAINER_slist_iter_destroy (it);
802   }
803 #endif
804   return GNUNET_NO;
805 }
806
807
808 /**
809  * Creates an fd set
810  * @return a new fd set
811  */
812 struct GNUNET_NETWORK_FDSet *
813 GNUNET_NETWORK_fdset_create ()
814 {
815   struct GNUNET_NETWORK_FDSet *fds;
816   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
817 #ifdef MINGW
818   fds->handles = GNUNET_CONTAINER_slist_create ();
819 #endif
820   GNUNET_NETWORK_fdset_zero (fds);
821   return fds;
822 }
823
824
825 /**
826  * Releases the associated memory of an fd set
827  * @param fds fd set
828  */
829 void
830 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
831 {
832 #ifdef MINGW
833   GNUNET_CONTAINER_slist_destroy (fds->handles);
834 #endif
835   GNUNET_free (fds);
836 }
837
838 /**
839  * Check if sockets meet certain conditions
840  * @param rfds set of sockets to be checked for readability
841  * @param wfds set of sockets to be checked for writability
842  * @param efds set of sockets to be checked for exceptions
843  * @param timeout relative value when to return
844  * @return number of selected sockets, GNUNET_SYSERR on error
845  */
846 int
847 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
848                               struct GNUNET_NETWORK_FDSet *wfds,
849                               struct GNUNET_NETWORK_FDSet *efds,
850                               const struct GNUNET_TIME_Relative timeout)
851 {
852   int nfds;
853 #ifdef MINGW
854   int handles;
855 #endif
856   nfds = 0;
857 #ifdef MINGW
858   handles = 0;
859 #endif
860   if (NULL != rfds)
861     {
862       nfds = rfds->nsds;
863 #ifdef MINGW
864       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
865 #endif
866     }
867   if (NULL != wfds)
868     {
869       nfds = GNUNET_MAX (nfds, wfds->nsds);
870 #ifdef MINGW
871       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
872 #endif
873     }
874   if (NULL != efds)
875     {
876       nfds = GNUNET_MAX (nfds, efds->nsds);
877 #ifdef MINGW
878       handles += GNUNET_CONTAINER_slist_count (efds->handles);
879 #endif
880     }
881
882   struct timeval tv;
883   tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value;
884   tv.tv_usec =
885     1000 * (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value));
886   if ((nfds == 0) && (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
887 #ifdef MINGW
888       && handles == 0
889 #endif
890     )
891     {
892       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
893                   _
894                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
895                   "select");
896       GNUNET_break (0);
897     }
898 #ifndef MINGW
899   return select (nfds + 1,
900                  (rfds != NULL) ? &rfds->sds : NULL,
901                  (wfds != NULL) ? &wfds->sds : NULL,
902                  (efds != NULL) ? &efds->sds : NULL,
903                  (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
904                  ? NULL : &tv);
905
906 #else
907   DWORD limit;
908   fd_set sock_read, sock_write, sock_except;
909   fd_set aread, awrite, aexcept;
910   struct GNUNET_CONTAINER_SList *handles_read, *handles_write, *handles_except;
911
912   int i;
913   struct timeval tvslice;
914   int retcode;
915   DWORD ms_total;
916
917 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
918
919   /* calculate how long we need to wait in milliseconds */
920   if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
921     ms_total = INFINITE;
922
923   else
924     ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value;
925
926   /* select() may be used as a portable way to sleep */
927   if (!(rfds || wfds || efds))
928
929     {
930       Sleep (ms_total);
931       return 0;
932     }
933
934   handles_read = GNUNET_CONTAINER_slist_create ();
935   handles_write = GNUNET_CONTAINER_slist_create ();
936   handles_except = GNUNET_CONTAINER_slist_create ();
937
938   if (rfds)
939     sock_read = rfds->sds;
940   else
941     FD_ZERO (&sock_read);
942   if (wfds)
943     sock_write = wfds->sds;
944   else
945     FD_ZERO (&sock_write);
946   if (efds)
947     sock_except = efds->sds;
948   else
949     FD_ZERO (&sock_except);
950
951   /* multiplex between winsock select() and waiting on the handles */
952   FD_ZERO (&aread);
953   FD_ZERO (&awrite);
954   FD_ZERO (&aexcept);
955   limit = GetTickCount () + ms_total;
956
957   do
958     {
959       retcode = 0;
960       if (nfds > 0)
961
962         {
963
964           /* overwrite the zero'd sets here; the select call
965            * will clear those that are not active */
966           FD_COPY (&sock_read, &aread);
967           FD_COPY (&sock_write, &awrite);
968           FD_COPY (&sock_except, &aexcept);
969           tvslice.tv_sec = 0;
970           tvslice.tv_usec = 100000;
971           if ((retcode =
972                select (nfds + 1, &aread, &awrite, &aexcept,
973                        &tvslice)) == SOCKET_ERROR)
974
975             {
976               SetErrnoFromWinsockError (WSAGetLastError ());
977               if (errno == ENOTSOCK)
978                 errno = EBADF;
979
980 #if DEBUG_NETWORK
981               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
982
983 #endif
984               goto select_loop_end;
985             }
986         }
987
988       /* Poll read pipes */
989       if (rfds)
990
991         {
992           struct GNUNET_CONTAINER_SList_Iterator *i;
993           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
994                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
995                GNUNET_CONTAINER_slist_next (i))
996
997             {
998               HANDLE h;
999               DWORD dwBytes;
1000               h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL);
1001               if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL))
1002                 {
1003                   retcode = -1;
1004                   SetErrnoFromWinError (GetLastError ());
1005
1006 #if DEBUG_NETWORK
1007                   GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1008                                        "PeekNamedPipe");
1009
1010 #endif
1011                   goto select_loop_end;
1012                 }
1013               else if (dwBytes)
1014
1015                 {
1016                   GNUNET_CONTAINER_slist_add (handles_read,
1017                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &h,
1018                       sizeof (HANDLE));
1019                   retcode++;
1020                 }
1021             }
1022           GNUNET_CONTAINER_slist_iter_destroy (i);
1023         }
1024
1025       /* Poll for faulty pipes */
1026       if (efds)
1027
1028         {
1029           struct GNUNET_CONTAINER_SList_Iterator *i;
1030           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1031                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1032                GNUNET_CONTAINER_slist_next (i))
1033
1034             {
1035               HANDLE h;
1036               DWORD dwBytes;
1037               h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL);
1038               if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL))
1039
1040                 {
1041                   GNUNET_CONTAINER_slist_add (handles_except,
1042                       GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT, &h,
1043                       sizeof (HANDLE));
1044                   retcode++;
1045                 }
1046             }
1047           GNUNET_CONTAINER_slist_iter_destroy (i);
1048         }
1049
1050       if (wfds)
1051         {
1052           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1053           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1054         }
1055
1056       /* Check for closed sockets */
1057       for (i = 0; i < nfds; i++)
1058
1059         {
1060           if (SAFE_FD_ISSET (i, &sock_read))
1061
1062             {
1063               struct sockaddr addr;
1064               int len;
1065               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1066
1067                 {
1068                   int err, len;
1069                   len = sizeof (err);
1070                   if (getsockopt
1071                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1072                       && err == WSAENOTCONN)
1073
1074                     {
1075                       if (!SAFE_FD_ISSET (i, &aread))
1076
1077                         {
1078                           FD_SET (i, &aread);
1079                           retcode++;
1080                         }
1081                     }
1082                 }
1083             }
1084         }
1085     select_loop_end:
1086       if (retcode == 0 && nfds == 0)
1087         Sleep (GNUNET_MIN (100, limit - GetTickCount ()));
1088     }
1089   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1090
1091   if (retcode != -1)
1092
1093     {
1094       if (rfds)
1095
1096         {
1097           GNUNET_NETWORK_fdset_zero (rfds);
1098           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1099           GNUNET_CONTAINER_slist_clear (rfds->handles);
1100           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1101
1102         }
1103       if (wfds)
1104
1105         {
1106           GNUNET_NETWORK_fdset_zero (wfds);
1107           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1108           GNUNET_CONTAINER_slist_clear (wfds->handles);
1109           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1110         }
1111       if (efds)
1112
1113         {
1114           GNUNET_NETWORK_fdset_zero (efds);
1115           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1116           GNUNET_CONTAINER_slist_clear (efds->handles);
1117           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1118         }
1119     }
1120
1121   GNUNET_CONTAINER_slist_destroy (handles_read);
1122   GNUNET_CONTAINER_slist_destroy (handles_write);
1123   GNUNET_CONTAINER_slist_destroy (handles_except);
1124
1125   return retcode;
1126 #endif
1127 }
1128
1129
1130 /* end of network.c */