stuff
[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 #ifdef MINGW
412   if (SOCKET_ERROR == ret)
413     SetErrnoFromWinsockError (WSAGetLastError ());
414 #endif 
415   return ret;
416 }
417
418
419 /**
420  * Read data from a connected socket (always non-blocking).
421  * @param desc socket
422  * @param buffer buffer
423  * @param length length of buffer
424  */
425 ssize_t
426 GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Handle * desc,
427                             void *buffer, size_t length)
428 {
429   int ret;
430   int flags;
431   flags = 0;
432
433 #ifdef MSG_DONTWAIT
434   flags |= MSG_DONTWAIT;
435 #endif
436   ret = recv (desc->fd, buffer, length, flags);
437 #ifdef MINGW
438   if (SOCKET_ERROR == ret)
439     SetErrnoFromWinsockError (WSAGetLastError ());
440 #endif
441   return ret;
442 }
443
444
445 /**
446  * Send data (always non-blocking).
447  *
448  * @param desc socket
449  * @param buffer data to send
450  * @param length size of the buffer
451  * @return number of bytes sent, GNUNET_SYSERR on error
452  */
453 ssize_t
454 GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Handle * desc,
455                             const void *buffer, size_t length)
456 {
457   int ret;
458   int flags;
459   flags = 0;
460
461 #ifdef MSG_DONTWAIT
462   flags |= MSG_DONTWAIT;
463
464 #endif /*  */
465 #ifdef MSG_NOSIGNAL
466   flags |= MSG_NOSIGNAL;
467
468 #endif /*  */
469   ret = send (desc->fd, buffer, length, flags);
470
471 #ifdef MINGW
472   if (SOCKET_ERROR == ret)
473     SetErrnoFromWinsockError (WSAGetLastError ());
474
475 #endif /*  */
476   return ret;
477 }
478
479
480 /**
481  * Send data to a particular destination (always non-blocking).
482  * This function only works for UDP sockets.
483  *
484  * @param desc socket
485  * @param message data to send
486  * @param length size of the data
487  * @param dest_addr destination address
488  * @param dest_len length of address
489  * @return number of bytes sent, GNUNET_SYSERR on error
490  */
491 ssize_t
492 GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Handle * desc,
493                               const void *message, size_t length,
494                               const struct sockaddr * dest_addr,
495                               socklen_t dest_len)
496 {
497   int ret;
498   int flags;
499   flags = 0;
500
501 #ifdef MSG_DONTWAIT
502   flags |= MSG_DONTWAIT;
503 #endif
504 #ifdef MSG_NOSIGNAL
505   flags |= MSG_NOSIGNAL;
506 #endif
507   ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);
508 #ifdef MINGW
509   if (SOCKET_ERROR == ret)
510     SetErrnoFromWinsockError (WSAGetLastError ());
511 #endif
512   return ret;
513 }
514
515
516 /**
517  * Set socket option
518  * @param fd socket
519  * @param level protocol level of the option
520  * @param option_name option identifier
521  * @param option_value value to set
522  * @param option_len size of option_value
523  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
524  */
525 int
526 GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Handle *fd,
527                                   int level, int option_name,
528                                   const void *option_value,
529                                   socklen_t option_len)
530 {
531   int ret;
532
533   ret = setsockopt (fd->fd, level, option_name, option_value, option_len);
534 #ifdef MINGW
535   if (SOCKET_ERROR == ret)
536     SetErrnoFromWinsockError (WSAGetLastError ());
537 #endif
538   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
539 }
540
541
542 /**
543  * Create a new socket.  Configure it for non-blocking IO and
544  * mark it as non-inheritable to child processes (set the
545  * close-on-exec flag).
546  *
547  * @param domain domain of the socket
548  * @param type socket type
549  * @param protocol network protocol
550  * @return new socket, NULL on error
551  */
552 struct GNUNET_NETWORK_Handle *
553 GNUNET_NETWORK_socket_create (int domain, int type, int protocol)
554 {
555   struct GNUNET_NETWORK_Handle *ret;
556   ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Handle));
557   ret->fd = socket (domain, type, protocol);
558   if (INVALID_SOCKET == ret->fd)
559     {
560 #ifdef MINGW
561       SetErrnoFromWinsockError (WSAGetLastError ());
562 #endif
563       GNUNET_free (ret);
564       return NULL;
565     }
566
567 #ifndef MINGW
568   if (ret->fd >= FD_SETSIZE)
569     {
570       GNUNET_break (0 == close (ret->fd));
571       GNUNET_free (ret);
572       errno = EMFILE;
573       return NULL;
574     }
575
576 #endif
577   if (GNUNET_SYSERR == socket_set_blocking (ret, GNUNET_NO))
578     {
579       /* we might want to treat this one as fatal... */
580       GNUNET_break (0);
581       GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (ret));
582       return NULL;
583     }
584
585 #ifndef MINGW
586   if (GNUNET_OK != socket_set_inheritable (ret))
587     GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR | GNUNET_ERROR_TYPE_BULK,
588                          "socket_set_inheritable");
589 #endif
590 #ifdef DARWIN
591   socket_set_nosigpipe (ret);
592 #endif
593   if (type == SOCK_STREAM)
594     socket_set_nodelay (ret);
595   return ret;
596 }
597
598
599 /**
600  * Shut down socket operations
601  * @param desc socket
602  * @param how type of shutdown
603  * @return GNUNET_OK on success, GNUNET_SYSERR otherwise
604  */
605 int
606 GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Handle *desc, int how)
607 {
608   int ret;
609
610   ret = shutdown (desc->fd, how);
611 #ifdef MINGW
612   if (ret != 0)
613     SetErrnoFromWinsockError (WSAGetLastError ());
614 #endif
615   return ret == 0 ? GNUNET_OK : GNUNET_SYSERR;
616 }
617
618
619 /**
620  * Reset FD set
621  * @param fds fd set
622  */
623 void
624 GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)
625 {
626   FD_ZERO (&fds->sds);
627   fds->nsds = 0;
628 #ifdef MINGW
629   GNUNET_CONTAINER_slist_clear (fds->handles);
630 #endif
631 }
632
633 /**
634  * Add a socket to the FD set
635  * @param fds fd set
636  * @param desc socket to add
637  */
638 void
639 GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,
640                           const struct GNUNET_NETWORK_Handle *desc)
641 {
642   FD_SET (desc->fd, &fds->sds);
643   if (desc->fd + 1 > fds->nsds)
644     fds->nsds = desc->fd + 1;
645 }
646
647
648 /**
649  * Check whether a socket is part of the fd set
650  * @param fds fd set
651  * @param desc socket
652  * @return 0 if the FD is not set
653  */
654 int
655 GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,
656                             const struct GNUNET_NETWORK_Handle *desc)
657 {
658   return FD_ISSET (desc->fd, &fds->sds);
659 }
660
661
662 /**
663  * Add one fd set to another
664  * @param dst the fd set to add to
665  * @param src the fd set to add from
666  */
667 void
668 GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,
669                           const struct GNUNET_NETWORK_FDSet *src)
670 {
671   int nfds;
672   for (nfds = src->nsds; nfds > 0; nfds--)
673     if (FD_ISSET (nfds, &src->sds))
674
675       {
676         FD_SET (nfds, &dst->sds);
677         if (nfds + 1 > dst->nsds)
678           dst->nsds = nfds + 1;
679       }
680 #ifdef MINGW
681   GNUNET_CONTAINER_slist_append (dst->handles, src->handles);
682 #endif
683 }
684
685
686 /**
687  * Copy one fd set to another
688  *
689  * @param to destination
690  * @param from source
691  */
692 void
693 GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,
694                            const struct GNUNET_NETWORK_FDSet *from)
695 {
696   FD_COPY (&from->sds, &to->sds);
697   to->nsds = from->nsds;
698
699 #ifdef MINGW
700   GNUNET_CONTAINER_slist_clear (to->handles);
701   GNUNET_CONTAINER_slist_append (to->handles, from->handles);
702 #endif
703 }
704
705 int
706 GNUNET_NETWORK_get_fd (struct GNUNET_NETWORK_Handle *desc)
707 {
708   return desc->fd;
709 }
710
711 /**
712  * Copy a native fd set
713  *
714  * @param to destination
715  * @param from native source set
716  * @param nfds the biggest socket number in from + 1
717  */
718 void
719 GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,
720                                   const fd_set * from, int nfds)
721 {
722   FD_COPY (from, &to->sds);
723   to->nsds = nfds;
724 }
725
726 /**
727  * Add a file handle to the fd set
728  * @param fds fd set
729  * @param h the file handle to add
730  */
731 void
732 GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,
733                                  const struct GNUNET_DISK_FileHandle *h)
734 {
735
736 #ifdef MINGW
737   HANDLE hw;
738   GNUNET_DISK_internal_file_handle_ (h, &hw, sizeof (HANDLE));
739   GNUNET_CONTAINER_slist_add (fds->handles,
740                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
741                               &hw, sizeof (HANDLE));
742
743 #else
744   int fd;
745   GNUNET_DISK_internal_file_handle_ (h, &fd, sizeof (int));
746   FD_SET (fd, &fds->sds);
747   if (fd + 1 > fds->nsds)
748     fds->nsds = fd + 1;
749
750 #endif
751 }
752
753
754 /**
755  * Check if a file handle is part of an fd set
756  * @param fds fd set
757  * @param h file handle
758  * @return GNUNET_YES if the file handle is part of the set
759  */
760 int
761 GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,
762                                    const struct GNUNET_DISK_FileHandle *h)
763 {
764
765 #ifdef MINGW
766   return GNUNET_CONTAINER_slist_contains (fds->handles, &h->h,
767                                           sizeof (HANDLE));
768 #else
769   return FD_ISSET (h->fd, &fds->sds);
770 #endif
771 }
772
773
774 /**
775  * Checks if two fd sets overlap
776  * @param fds1 first fd set
777  * @param fds2 second fd set
778  * @return GNUNET_YES if they do overlap, GNUNET_NO otherwise
779  */
780 int
781 GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,
782                               const struct GNUNET_NETWORK_FDSet *fds2)
783 {
784   int nfds;
785   nfds = fds1->nsds;
786   if (nfds < fds2->nsds)
787     nfds = fds2->nsds;
788   for (; nfds >= 0; nfds--)
789     if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))
790       return GNUNET_YES;
791 #ifdef MINGW
792   {
793     struct GNUNET_CONTAINER_SList_Iterator *it;
794
795     for (it = GNUNET_CONTAINER_slist_begin (fds1->handles);
796          GNUNET_CONTAINER_slist_end (it) != GNUNET_YES;
797          GNUNET_CONTAINER_slist_next (it))
798       {
799         HANDLE *h;
800
801         h = GNUNET_CONTAINER_slist_get (it, NULL);
802         if (GNUNET_CONTAINER_slist_contains
803             (fds2->handles, h, sizeof (HANDLE)))
804           {
805             GNUNET_CONTAINER_slist_iter_destroy (it);
806             return GNUNET_YES;
807           }
808       }
809     GNUNET_CONTAINER_slist_iter_destroy (it);
810   }
811 #endif
812   return GNUNET_NO;
813 }
814
815
816 /**
817  * Creates an fd set
818  * @return a new fd set
819  */
820 struct GNUNET_NETWORK_FDSet *
821 GNUNET_NETWORK_fdset_create ()
822 {
823   struct GNUNET_NETWORK_FDSet *fds;
824   fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));
825 #ifdef MINGW
826   fds->handles = GNUNET_CONTAINER_slist_create ();
827 #endif
828   GNUNET_NETWORK_fdset_zero (fds);
829   return fds;
830 }
831
832
833 /**
834  * Releases the associated memory of an fd set
835  * @param fds fd set
836  */
837 void
838 GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)
839 {
840 #ifdef MINGW
841   GNUNET_CONTAINER_slist_destroy (fds->handles);
842 #endif
843   GNUNET_free (fds);
844 }
845
846 /**
847  * Check if sockets meet certain conditions
848  * @param rfds set of sockets to be checked for readability
849  * @param wfds set of sockets to be checked for writability
850  * @param efds set of sockets to be checked for exceptions
851  * @param timeout relative value when to return
852  * @return number of selected sockets, GNUNET_SYSERR on error
853  */
854 int
855 GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,
856                               struct GNUNET_NETWORK_FDSet *wfds,
857                               struct GNUNET_NETWORK_FDSet *efds,
858                               const struct GNUNET_TIME_Relative timeout)
859 {
860   int nfds;
861 #ifdef MINGW
862   int handles;
863 #endif
864   nfds = 0;
865 #ifdef MINGW
866   handles = 0;
867 #endif
868   if (NULL != rfds)
869     {
870       nfds = rfds->nsds;
871 #ifdef MINGW
872       handles = GNUNET_CONTAINER_slist_count (rfds->handles);
873 #endif
874     }
875   if (NULL != wfds)
876     {
877       nfds = GNUNET_MAX (nfds, wfds->nsds);
878 #ifdef MINGW
879       handles += GNUNET_CONTAINER_slist_count (wfds->handles);
880 #endif
881     }
882   if (NULL != efds)
883     {
884       nfds = GNUNET_MAX (nfds, efds->nsds);
885 #ifdef MINGW
886       handles += GNUNET_CONTAINER_slist_count (efds->handles);
887 #endif
888     }
889
890   struct timeval tv;
891   tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value;
892   tv.tv_usec =
893     1000 * (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value));
894   if ((nfds == 0) && (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
895 #ifdef MINGW
896       && handles == 0
897 #endif
898     )
899     {
900       GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
901                   _
902                   ("Fatal internal logic error, process hangs in `%s' (abort with CTRL-C)!\n"),
903                   "select");
904       GNUNET_break (0);
905     }
906 #ifndef MINGW
907   return select (nfds + 1,
908                  (rfds != NULL) ? &rfds->sds : NULL,
909                  (wfds != NULL) ? &wfds->sds : NULL,
910                  (efds != NULL) ? &efds->sds : NULL,
911                  (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
912                  ? NULL : &tv);
913
914 #else
915   DWORD limit;
916   fd_set sock_read, sock_write, sock_except;
917   fd_set aread, awrite, aexcept;
918   struct GNUNET_CONTAINER_SList *handles_read, *handles_write,
919     *handles_except;
920
921   int i;
922   struct timeval tvslice;
923   int retcode;
924   DWORD ms_total;
925
926 #define SAFE_FD_ISSET(fd, set)  (set != NULL && FD_ISSET(fd, set))
927
928   /* calculate how long we need to wait in milliseconds */
929   if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)
930     ms_total = INFINITE;
931
932   else
933     ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value;
934
935   /* select() may be used as a portable way to sleep */
936   if (!(rfds || wfds || efds))
937
938     {
939       Sleep (ms_total);
940       return 0;
941     }
942
943   handles_read = GNUNET_CONTAINER_slist_create ();
944   handles_write = GNUNET_CONTAINER_slist_create ();
945   handles_except = GNUNET_CONTAINER_slist_create ();
946
947   if (rfds)
948     sock_read = rfds->sds;
949   else
950     FD_ZERO (&sock_read);
951   if (wfds)
952     sock_write = wfds->sds;
953   else
954     FD_ZERO (&sock_write);
955   if (efds)
956     sock_except = efds->sds;
957   else
958     FD_ZERO (&sock_except);
959
960   /* multiplex between winsock select() and waiting on the handles */
961   FD_ZERO (&aread);
962   FD_ZERO (&awrite);
963   FD_ZERO (&aexcept);
964   limit = GetTickCount () + ms_total;
965
966   do
967     {
968       retcode = 0;
969       if (nfds > 0)
970
971         {
972
973           /* overwrite the zero'd sets here; the select call
974            * will clear those that are not active */
975           FD_COPY (&sock_read, &aread);
976           FD_COPY (&sock_write, &awrite);
977           FD_COPY (&sock_except, &aexcept);
978           tvslice.tv_sec = 0;
979           tvslice.tv_usec = 100000;
980           if ((retcode =
981                select (nfds + 1, &aread, &awrite, &aexcept,
982                        &tvslice)) == SOCKET_ERROR)
983
984             {
985               SetErrnoFromWinsockError (WSAGetLastError ());
986               if (errno == ENOTSOCK)
987                 errno = EBADF;
988
989 #if DEBUG_NETWORK
990               GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");
991
992 #endif
993               goto select_loop_end;
994             }
995         }
996
997       /* Poll read pipes */
998       if (rfds)
999
1000         {
1001           struct GNUNET_CONTAINER_SList_Iterator *i;
1002           for (i = GNUNET_CONTAINER_slist_begin (rfds->handles);
1003                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1004                GNUNET_CONTAINER_slist_next (i))
1005
1006             {
1007               HANDLE h;
1008               DWORD dwBytes;
1009               h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL);
1010               if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL))
1011                 {
1012                   retcode = -1;
1013                   SetErrnoFromWinError (GetLastError ());
1014
1015 #if DEBUG_NETWORK
1016                   GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
1017                                        "PeekNamedPipe");
1018
1019 #endif
1020                   goto select_loop_end;
1021                 }
1022               else if (dwBytes)
1023
1024                 {
1025                   GNUNET_CONTAINER_slist_add (handles_read,
1026                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1027                                               &h, sizeof (HANDLE));
1028                   retcode++;
1029                 }
1030             }
1031           GNUNET_CONTAINER_slist_iter_destroy (i);
1032         }
1033
1034       /* Poll for faulty pipes */
1035       if (efds)
1036
1037         {
1038           struct GNUNET_CONTAINER_SList_Iterator *i;
1039           for (i = GNUNET_CONTAINER_slist_begin (efds->handles);
1040                GNUNET_CONTAINER_slist_end (i) != GNUNET_YES;
1041                GNUNET_CONTAINER_slist_next (i))
1042
1043             {
1044               HANDLE h;
1045               DWORD dwBytes;
1046               h = *(HANDLE *) GNUNET_CONTAINER_slist_get (i, NULL);
1047               if (!PeekNamedPipe (h, NULL, 0, NULL, &dwBytes, NULL))
1048
1049                 {
1050                   GNUNET_CONTAINER_slist_add (handles_except,
1051                                               GNUNET_CONTAINER_SLIST_DISPOSITION_TRANSIENT,
1052                                               &h, sizeof (HANDLE));
1053                   retcode++;
1054                 }
1055             }
1056           GNUNET_CONTAINER_slist_iter_destroy (i);
1057         }
1058
1059       if (wfds)
1060         {
1061           GNUNET_CONTAINER_slist_append (handles_write, wfds->handles);
1062           retcode += GNUNET_CONTAINER_slist_count (wfds->handles);
1063         }
1064
1065       /* Check for closed sockets */
1066       for (i = 0; i < nfds; i++)
1067
1068         {
1069           if (SAFE_FD_ISSET (i, &sock_read))
1070
1071             {
1072               struct sockaddr addr;
1073               int len;
1074               if (getpeername (i, &addr, &len) == SOCKET_ERROR)
1075
1076                 {
1077                   int err, len;
1078                   len = sizeof (err);
1079                   if (getsockopt
1080                       (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0
1081                       && err == WSAENOTCONN)
1082
1083                     {
1084                       if (!SAFE_FD_ISSET (i, &aread))
1085
1086                         {
1087                           FD_SET (i, &aread);
1088                           retcode++;
1089                         }
1090                     }
1091                 }
1092             }
1093         }
1094     select_loop_end:
1095       if (retcode == 0 && nfds == 0)
1096         Sleep (GNUNET_MIN (100, limit - GetTickCount ()));
1097     }
1098   while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));
1099
1100   if (retcode != -1)
1101
1102     {
1103       if (rfds)
1104
1105         {
1106           GNUNET_NETWORK_fdset_zero (rfds);
1107           GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);
1108           GNUNET_CONTAINER_slist_clear (rfds->handles);
1109           GNUNET_CONTAINER_slist_append (rfds->handles, handles_read);
1110
1111         }
1112       if (wfds)
1113
1114         {
1115           GNUNET_NETWORK_fdset_zero (wfds);
1116           GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);
1117           GNUNET_CONTAINER_slist_clear (wfds->handles);
1118           GNUNET_CONTAINER_slist_append (wfds->handles, handles_write);
1119         }
1120       if (efds)
1121
1122         {
1123           GNUNET_NETWORK_fdset_zero (efds);
1124           GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);
1125           GNUNET_CONTAINER_slist_clear (efds->handles);
1126           GNUNET_CONTAINER_slist_append (efds->handles, handles_except);
1127         }
1128     }
1129
1130   GNUNET_CONTAINER_slist_destroy (handles_read);
1131   GNUNET_CONTAINER_slist_destroy (handles_write);
1132   GNUNET_CONTAINER_slist_destroy (handles_except);
1133
1134   return retcode;
1135 #endif
1136 }
1137
1138
1139 /* end of network.c */