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