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