/**
* Iterator over HashCodes.
*
+ * @param cls closure
+ * @param next set to the next hash code
* @return GNUNET_YES if next was updated
* GNUNET_NO if there are no more entries
*/
-typedef int (*GNUNET_HashCodeIterator) (GNUNET_HashCode * next, void *arg);
+typedef int (*GNUNET_HashCodeIterator) (void *cls,
+ GNUNET_HashCode * next);
/**
* Load a bloom-filter from a file.
*
* @param bf the filter
* @param iterator an iterator over all elements stored in the BF
- * @param iterator_arg argument to the iterator function
+ * @param iterator_cls closure for iterator
* @param size the new size for the filter
* @param k the new number of GNUNET_CRYPTO_hash-function to apply per element
*/
void GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter
*bf,
GNUNET_HashCodeIterator iterator,
- void *iterator_arg,
+ void *iterator_cls,
unsigned int size, unsigned int k);
/* ****************** metadata ******************* */
* Iterate over MD entries, excluding thumbnails.
*
* @param md metadata to inspect
- * @param iterator function to call on each entry
- * @param closure closure for iterator
+ * @param iter function to call on each entry
+ * @param iter_cls closure for iterator
* @return number of entries
*/
int GNUNET_CONTAINER_meta_data_get_contents (const struct
GNUNET_CONTAINER_MetaData *md,
GNUNET_CONTAINER_MetaDataProcessor
- iterator, void *closure);
+ iter, void *iter_cls);
/**
* Get the first MD entry of the given type.
* @file include/gnunet_disk_lib.h
* @brief disk IO apis
*/
-
#ifndef GNUNET_DISK_LIB_H
#define GNUNET_DISK_LIB_H
-#include "gnunet_configuration_lib.h"
-#include "gnunet_scheduler_lib.h"
+/**
+ * Opaque handle used to access files.
+ */
+struct GNUNET_DISK_FileHandle;
+
+/**
+ * Opaque handle used to manage a pipe.
+ */
+struct GNUNET_DISK_PipeHandle;
+
/* we need size_t, and since it can be both unsigned int
or unsigned long long, this IS platform dependent;
but "stdlib.h" should be portable 'enough' to be
unconditionally available... */
#include <stdlib.h>
+#include "gnunet_configuration_lib.h"
+#include "gnunet_scheduler_lib.h"
#ifdef __cplusplus
extern "C"
#endif
#endif
+
/* Open the file for reading */
#define GNUNET_DISK_OPEN_READ 1
/* Open the file for writing */
GNUNET_DISK_SEEK_END
};
-struct GNUNET_DISK_FileHandle;
-
-struct GNUNET_DISK_PipeHandle;
-
/**
* Get the number of blocks that are left on the partition that
* contains the given file (for normal users).
#endif
#endif
-#include "gnunet_disk_lib.h"
-#include "gnunet_time_lib.h"
/**
struct GNUNET_NETWORK_FDSet;
-struct GNUNET_NETWORK_Descriptor *GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc,
- struct sockaddr *address,
- socklen_t *address_len);
+#include "gnunet_disk_lib.h"
+#include "gnunet_time_lib.h"
+
+
+struct GNUNET_NETWORK_Descriptor *
+GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc,
+ struct sockaddr *address,
+ socklen_t *address_len);
int
GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor
#endif
-#include "gnunet_time_lib.h"
-#include "gnunet_network_lib.h"
-
/**
* Opaque handle for the scheduling service.
*/
GNUNET_SCHEDULER_PRIORITY_COUNT = 7
};
+#include "gnunet_time_lib.h"
+#include "gnunet_network_lib.h"
+
/**
* Context information passed to each scheduler task.
* bloomfilter iterator on each bit that is to be
* set or tested for the key.
*
+ * @param cls closure
* @param bf the filter to manipulate
* @param bit the current bit
- * @param additional context specific argument
*/
-typedef void (*BitIterator) (struct GNUNET_CONTAINER_BloomFilter * bf,
- unsigned int bit, void *arg);
+typedef void (*BitIterator) (void *cls,
+ struct GNUNET_CONTAINER_BloomFilter * bf,
+ unsigned int bit);
/**
* Call an iterator for each bit that the bloomfilter
{
while (slot < (sizeof (GNUNET_HashCode) / sizeof (unsigned int)))
{
- callback (bf,
+ callback (arg,
+ bf,
(((unsigned int *) &tmp[round & 1])[slot]) &
- ((bf->bitArraySize * 8) - 1), arg);
+ ((bf->bitArraySize * 8) - 1));
slot++;
bitCount--;
if (bitCount == 0)
/**
* Callback: increment bit
*
+ * @param cls not used
* @param bf the filter to manipulate
* @param bit the bit to increment
- * @param arg not used
*/
static void
-incrementBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf,
- unsigned int bit, void *arg)
+incrementBitCallback (void *cls,
+ struct GNUNET_CONTAINER_BloomFilter *bf,
+ unsigned int bit)
{
incrementBit (bf->bitArray, bit, bf->fh);
}
/**
* Callback: decrement bit
*
+ * @param cls not used
* @param bf the filter to manipulate
* @param bit the bit to decrement
- * @param arg not used
*/
static void
-decrementBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf,
- unsigned int bit, void *arg)
+decrementBitCallback (void *cls,
+ struct GNUNET_CONTAINER_BloomFilter *bf,
+ unsigned int bit)
{
decrementBit (bf->bitArray, bit, bf->fh);
}
/**
* Callback: test if all bits are set
*
+ * @param cls pointer set to GNUNET_NO if bit is not set
* @param bf the filter
* @param bit the bit to test
- * @param arg pointer set to GNUNET_NO if bit is not set
*/
static void
-testBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit,
- void *cls)
+testBitCallback (void *cls,
+ struct GNUNET_CONTAINER_BloomFilter *bf, unsigned int bit)
{
int *arg = cls;
if (GNUNET_NO == testBit (bf->bitArray, bit))
memset (bf->bitArray, 0, bf->bitArraySize);
if (bf->filename != NULL)
makeEmptyFile (bf->fh, bf->bitArraySize * 4);
- while (GNUNET_YES == iterator (&hc, iterator_arg))
+ while (GNUNET_YES == iterator (iterator_arg, &hc))
GNUNET_CONTAINER_bloomfilter_add (bf, &hc);
}
--- /dev/null
+/*\r
+ This file is part of GNUnet.\r
+ (C) 2009 Christian Grothoff (and other contributing authors)\r
+\r
+ GNUnet is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published\r
+ by the Free Software Foundation; either version 2, or (at your\r
+ option) any later version.\r
+\r
+ GNUnet is distributed in the hope that it will be useful, but\r
+ WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
+ General Public License for more details.\r
+\r
+ You should have received a copy of the GNU General Public License\r
+ along with GNUnet; see the file COPYING. If not, write to the\r
+ Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
+ Boston, MA 02111-1307, USA.\r
+*/\r
+\r
+/**\r
+ * @file util/sock.c\r
+ * @brief basic, low-level networking interface\r
+ * @author Nils Durner\r
+ */\r
+\r
+#include "platform.h"\r
+#include "gnunet_disk_lib.h"\r
+#include "disk.h"\r
+#include "gnunet_container_lib.h"\r
+\r
+#define DEBUG_SOCK GNUNET_NO\r
+\r
+struct GNUNET_NETWORK_Descriptor\r
+{\r
+ int fd;\r
+};\r
+\r
+struct GNUNET_NETWORK_FDSet\r
+{\r
+ /* socket descriptors */\r
+ int nsds;\r
+ fd_set sds;\r
+#ifdef WINDOWS\r
+ /* handles */\r
+ struct GNUNET_CONTAINER_Vector *handles;\r
+#endif\r
+};\r
+\r
+#ifndef FD_COPY\r
+#define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))\r
+#endif\r
+\r
+struct GNUNET_NETWORK_Descriptor *\r
+GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc,\r
+ struct sockaddr *address,\r
+ socklen_t * address_len)\r
+{\r
+ struct GNUNET_NETWORK_Descriptor *ret;\r
+\r
+ ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor));\r
+ ret->fd = accept (desc->fd, address, address_len);\r
+#ifdef MINGW\r
+ if (INVALID_SOCKET == ret->fd)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+ return ret;\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Descriptor *desc,\r
+ const struct sockaddr *address,\r
+ socklen_t address_len)\r
+{\r
+ int ret;\r
+\r
+ ret = bind (desc->fd, address, address_len);\r
+#ifdef MINGW\r
+ if (SOCKET_ERROR == ret)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+ return ret;\r
+}\r
+\r
+/**\r
+ * Set if a socket should use blocking or non-blocking IO.\r
+ *\r
+ * @return GNUNET_OK on success, GNUNET_SYSERR on error\r
+ */\r
+int\r
+GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Descriptor *fd,\r
+ int doBlock)\r
+{\r
+#if MINGW\r
+ u_long mode;\r
+ mode = !doBlock;\r
+ if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)\r
+ {\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");\r
+ return GNUNET_SYSERR;\r
+ }\r
+ return GNUNET_OK;\r
+\r
+#else\r
+ /* not MINGW */\r
+ int flags = fcntl (fd->fd, F_GETFL);\r
+ if (flags == -1)\r
+ {\r
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");\r
+ return GNUNET_SYSERR;\r
+ }\r
+ if (doBlock)\r
+ flags &= ~O_NONBLOCK;\r
+ else\r
+ flags |= O_NONBLOCK;\r
+ if (0 != fcntl (fd->fd, F_SETFL, flags))\r
+ {\r
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");\r
+ return GNUNET_SYSERR;\r
+ }\r
+ return GNUNET_OK;\r
+#endif\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Descriptor *desc)\r
+{\r
+ int ret;\r
+#ifdef MINGW\r
+ ret = closesocket (desc->fd);\r
+ if (SOCKET_ERROR != ret)\r
+ GNUNET_free (desc);\r
+ else\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#else\r
+ ret = close (desc->fd);\r
+ if (-1 == ret)\r
+ {\r
+ GNUNET_free (desc);\r
+ }\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Descriptor *desc,\r
+ const struct sockaddr *address,\r
+ socklen_t address_len)\r
+{\r
+ int ret;\r
+\r
+ ret = connect (desc->fd, address, address_len);\r
+#ifdef MINGW\r
+ if (SOCKET_ERROR == ret)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+ return ret;\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Descriptor *desc,\r
+ int level, int optname, void *optval,\r
+ socklen_t * optlen)\r
+{\r
+ int ret;\r
+\r
+ ret = getsockopt (desc->fd, level, optname, optval, optlen);\r
+#ifdef MINGW\r
+ if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)\r
+ *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));\r
+ else if (SOCKET_ERROR == ret)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+ return ret;\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Descriptor *desc,\r
+ int backlog)\r
+{\r
+ int ret;\r
+\r
+ ret = listen (desc->fd, backlog);\r
+#ifdef MINGW\r
+ if (SOCKET_ERROR == ret)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+ssize_t\r
+GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Descriptor * desc,\r
+ void *buffer, size_t length, int flags)\r
+{\r
+ int ret;\r
+\r
+ ret = recv (desc->fd, buffer, length, flags);\r
+#ifdef MINGW\r
+ if (SOCKET_ERROR == ret)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+ssize_t\r
+GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Descriptor * desc,\r
+ const void *buffer, size_t length, int flags)\r
+{\r
+ int ret;\r
+\r
+ ret = send (desc->fd, buffer, length, flags);\r
+#ifdef MINGW\r
+ if (SOCKET_ERROR == ret)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+ssize_t\r
+GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Descriptor * desc,\r
+ const void *message, size_t length, int flags,\r
+ const struct sockaddr * dest_addr,\r
+ socklen_t dest_len)\r
+{\r
+ int ret;\r
+\r
+ ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);\r
+#ifdef MINGW\r
+ if (SOCKET_ERROR == ret)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Descriptor *fd,\r
+ int level, int option_name,\r
+ const void *option_value,\r
+ socklen_t option_len)\r
+{\r
+ int ret;\r
+\r
+ ret = setsockopt (fd->fd, level, option_name, option_value, option_len);\r
+#ifdef MINGW\r
+ if (SOCKET_ERROR == ret)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+struct GNUNET_NETWORK_Descriptor *\r
+GNUNET_NETWORK_socket_socket (int domain, int type, int protocol)\r
+{\r
+ struct GNUNET_NETWORK_Descriptor *ret;\r
+\r
+ ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor));\r
+ ret->fd = socket (domain, type, protocol);\r
+#ifdef MINGW\r
+ if (INVALID_SOCKET == ret->fd)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+\r
+ if (ret->fd < 0)\r
+ {\r
+ GNUNET_free (ret);\r
+ ret = NULL;\r
+ }\r
+\r
+ return ret;\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Descriptor *desc,\r
+ int how)\r
+{\r
+ int ret;\r
+\r
+ ret = shutdown (desc->fd, how);\r
+#ifdef MINGW\r
+ if (ret != 0)\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+#endif\r
+\r
+ return ret;\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor\r
+ *desc)\r
+{\r
+#ifdef MINGW\r
+ errno = ENOSYS;\r
+ return GNUNET_SYSERR;\r
+#else\r
+ return fcntl (desc->fd, F_SETFD,\r
+ fcntl (desc->fd,\r
+ F_GETFD) | FD_CLOEXEC) ==\r
+ 0 ? GNUNET_OK : GNUNET_SYSERR;\r
+#endif\r
+}\r
+\r
+void\r
+GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)\r
+{\r
+ FD_ZERO (&fds->sds);\r
+ fds->nsds = 0;\r
+#ifdef MINGW\r
+ if (fds->handles)\r
+ GNUNET_CONTAINER_vector_destroy (fds->handles);\r
+ fds->handles = GNUNET_CONTAINER_vector_create (2);\r
+#endif\r
+}\r
+\r
+void\r
+GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,\r
+ const struct GNUNET_NETWORK_Descriptor *desc)\r
+{\r
+ FD_SET (desc->fd, &fds->sds);\r
+\r
+ if (desc->fd + 1 > fds->nsds)\r
+ fds->nsds = desc->fd + 1;\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,\r
+ const struct GNUNET_NETWORK_Descriptor *desc)\r
+{\r
+ return FD_ISSET (desc->fd, &fds->sds);\r
+}\r
+\r
+void\r
+GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,\r
+ const struct GNUNET_NETWORK_FDSet *src)\r
+{\r
+ int nfds;\r
+\r
+ for (nfds = src->nsds; nfds > 0; nfds--)\r
+ if (FD_ISSET (nfds, &src->sds))\r
+ {\r
+ FD_SET (nfds, &dst->sds);\r
+ if (nfds + 1 > dst->nsds)\r
+ dst->nsds = nfds + 1;\r
+ }\r
+}\r
+\r
+void\r
+GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,\r
+ const struct GNUNET_NETWORK_FDSet *from)\r
+{\r
+ FD_COPY (&from->sds, &to->sds);\r
+ to->nsds = from->nsds;\r
+#ifdef MINGW\r
+ void *obj;\r
+\r
+ if (to->handles)\r
+ GNUNET_CONTAINER_vector_destroy (to->handles);\r
+ to->handles = GNUNET_CONTAINER_vector_create (2);\r
+ for (obj = GNUNET_CONTAINER_vector_get_first (from->handles); obj != NULL;\r
+ obj = GNUNET_CONTAINER_vector_get_next (from->handles))\r
+ {\r
+ GNUNET_CONTAINER_vector_insert_last (to->handles, obj);\r
+ }\r
+#endif\r
+}\r
+\r
+void\r
+GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,\r
+ const fd_set * from, int nfds)\r
+{\r
+ FD_COPY (from, &to->sds);\r
+ to->nsds = nfds;\r
+}\r
+\r
+void\r
+GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,\r
+ const struct GNUNET_DISK_FileHandle *h)\r
+{\r
+#ifdef MINGW\r
+ HANDLE hw;\r
+\r
+ GNUNET_internal_disk_file_handle (h, &hw, sizeof (HANDLE));\r
+ GNUNET_CONTAINER_vector_insert_last (fds->handles, h);\r
+#else\r
+ int fd;\r
+\r
+ GNUNET_internal_disk_file_handle (h, &fd, sizeof (int));\r
+ FD_SET (fd, &fds->sds);\r
+ if (fd + 1 > fds->nsds)\r
+ fds->nsds = fd + 1;\r
+#endif\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,\r
+ const struct GNUNET_DISK_FileHandle *h)\r
+{\r
+#ifdef MINGW\r
+ return GNUNET_CONTAINER_vector_index_of (fds->handles, h->h) !=\r
+ (unsigned int) -1;\r
+#else\r
+ return FD_ISSET (h->fd, &fds->sds);\r
+#endif\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,\r
+ const struct GNUNET_NETWORK_FDSet *fds2)\r
+{\r
+ int nfds;\r
+\r
+ nfds = fds1->nsds;\r
+ if (nfds < fds2->nsds)\r
+ nfds = fds2->nsds;\r
+\r
+ for (; nfds >= 0; nfds--)\r
+ if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))\r
+ return GNUNET_YES;\r
+\r
+ return GNUNET_NO;\r
+}\r
+\r
+struct GNUNET_NETWORK_FDSet *\r
+GNUNET_NETWORK_fdset_create ()\r
+{\r
+ struct GNUNET_NETWORK_FDSet *fds;\r
+\r
+ fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));\r
+#ifdef MINGW\r
+ fds->handles = NULL;\r
+#endif\r
+ GNUNET_NETWORK_fdset_zero (fds);\r
+\r
+ return fds;\r
+}\r
+\r
+void\r
+GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)\r
+{\r
+#ifdef MINGW\r
+ GNUNET_CONTAINER_vector_destroy (fds->handles);\r
+#endif\r
+ GNUNET_free (fds);\r
+}\r
+\r
+int\r
+GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,\r
+ struct GNUNET_NETWORK_FDSet *wfds,\r
+ struct GNUNET_NETWORK_FDSet *efds,\r
+ const struct GNUNET_TIME_Relative timeout)\r
+{\r
+ int nfds;\r
+\r
+ nfds = 0;\r
+\r
+ if (rfds)\r
+ nfds = rfds->nsds;\r
+ if (wfds && wfds->nsds > nfds)\r
+ nfds = wfds->nsds;\r
+ if (efds && efds->nsds > nfds)\r
+ nfds = efds->nsds;\r
+\r
+#ifndef MINGW\r
+ struct timeval tv;\r
+\r
+ tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value;\r
+ tv.tv_usec = (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value))\r
+ / GNUNET_TIME_UNIT_MILLISECONDS.value;\r
+\r
+ return select (nfds + 1, rfds ? &rfds->sds : NULL, wfds ? &wfds->sds : NULL,\r
+ efds ? &efds->sds : NULL, timeout.value\r
+ == GNUNET_TIME_UNIT_FOREVER_REL.value ? NULL : &tv);\r
+#else\r
+ DWORD limit;\r
+ fd_set sock_read, sock_write, sock_except;\r
+ fd_set aread, awrite, aexcept;\r
+ int i;\r
+ struct timeval tvslice;\r
+ int retcode;\r
+ DWORD ms_total;\r
+\r
+#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))\r
+\r
+ /* calculate how long we need to wait in milliseconds */\r
+ if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)\r
+ ms_total = INFINITE;\r
+ else\r
+ ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value;\r
+\r
+ /* select() may be used as a portable way to sleep */\r
+ if (!(rfds || wfds || efds))\r
+ {\r
+ Sleep (ms_total);\r
+\r
+ return 0;\r
+ }\r
+\r
+ if (rfds)\r
+ sock_read = rfds->sds;\r
+ else\r
+ FD_ZERO(&sock_read);\r
+\r
+ if (wfds)\r
+ sock_write = wfds->sds;\r
+ else\r
+ FD_ZERO(&sock_write);\r
+\r
+ if (efds)\r
+ sock_except = efds->sds;\r
+ else\r
+ FD_ZERO(&sock_except);\r
+\r
+ /*\r
+ if (rfds)\r
+ FD_COPY (&rfds->sds, &sock_read);\r
+ else\r
+ FD_ZERO(&sock_read);\r
+\r
+ if (wfds)\r
+ FD_COPY (&wfds->sds, &sock_write);\r
+ else\r
+ FD_ZERO(&sock_write);\r
+\r
+ if (efds)\r
+ FD_COPY (&efds->sds, &sock_except);\r
+ else\r
+ FD_ZERO(&sock_except);\r
+*/\r
+\r
+ /* multiplex between winsock select() and waiting on the handles */\r
+\r
+ FD_ZERO (&aread);\r
+ FD_ZERO (&awrite);\r
+ FD_ZERO (&aexcept);\r
+\r
+ limit = GetTickCount () + ms_total;\r
+ do\r
+ {\r
+ retcode = 0;\r
+\r
+ if (nfds > 0)\r
+ {\r
+ /* overwrite the zero'd sets here; the select call\r
+ * will clear those that are not active */\r
+\r
+ FD_COPY (&sock_read, &aread);\r
+ FD_COPY (&sock_write, &awrite);\r
+ FD_COPY (&sock_except, &aexcept);\r
+\r
+ tvslice.tv_sec = 0;\r
+ tvslice.tv_usec = 100000;\r
+\r
+ if ((retcode =\r
+ select (nfds + 1, &aread, &awrite, &aexcept,\r
+ &tvslice)) == SOCKET_ERROR)\r
+ {\r
+ SetErrnoFromWinsockError (WSAGetLastError ());\r
+ if (errno == ENOTSOCK)\r
+ errno = EBADF;\r
+\r
+#if DEBUG_SOCK\r
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");\r
+#endif\r
+\r
+ goto select_loop_end;\r
+ }\r
+ }\r
+\r
+ /* Poll read pipes */\r
+ if (rfds)\r
+ for (i = GNUNET_CONTAINER_vector_size (rfds->handles) - 1; i >= 0; i--)\r
+ {\r
+ DWORD dwBytes;\r
+\r
+ if (!PeekNamedPipe\r
+ (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0,\r
+ NULL, &dwBytes, NULL))\r
+ {\r
+ GNUNET_CONTAINER_vector_remove_at (rfds->handles, i);\r
+\r
+ retcode = -1;\r
+ SetErrnoFromWinError (GetLastError ());\r
+#if DEBUG_SOCK\r
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "PeekNamedPipe");\r
+#endif\r
+ goto select_loop_end;\r
+ }\r
+ else if (dwBytes)\r
+ {\r
+ retcode++;\r
+ }\r
+ else\r
+ GNUNET_CONTAINER_vector_remove_at (rfds->handles, i);\r
+ }\r
+\r
+ /* Poll for faulty pipes */\r
+ if (efds)\r
+ for (i = GNUNET_CONTAINER_vector_size (efds->handles); i >= 0; i--)\r
+ {\r
+ DWORD dwBytes;\r
+\r
+ if (PeekNamedPipe\r
+ (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0,\r
+ NULL, &dwBytes, NULL))\r
+ {\r
+ GNUNET_CONTAINER_vector_remove_at (efds->handles, i);\r
+\r
+ retcode++;\r
+ }\r
+ }\r
+\r
+ /* FIXME */\r
+ if (wfds)\r
+ GNUNET_assert (GNUNET_CONTAINER_vector_size (wfds->handles) == 0);\r
+\r
+ /* Check for closed sockets */\r
+ for (i = 0; i < nfds; i++)\r
+ {\r
+ if (SAFE_FD_ISSET (i, &sock_read))\r
+ {\r
+ struct sockaddr addr;\r
+ int len;\r
+\r
+ if (getpeername (i, &addr, &len) == SOCKET_ERROR)\r
+ {\r
+ int err, len;\r
+\r
+ len = sizeof (err);\r
+ if (getsockopt\r
+ (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0\r
+ && err == WSAENOTCONN)\r
+ {\r
+ if (!SAFE_FD_ISSET (i, &aread))\r
+ {\r
+ FD_SET (i, &aread);\r
+ retcode++;\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ select_loop_end:;\r
+ }\r
+ while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));\r
+\r
+ if (retcode != -1)\r
+ {\r
+ if (rfds)\r
+ {\r
+ GNUNET_NETWORK_fdset_zero (rfds);\r
+ GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);\r
+ }\r
+\r
+ if (wfds)\r
+ {\r
+ GNUNET_NETWORK_fdset_zero (wfds);\r
+ GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);\r
+ }\r
+\r
+ if (efds)\r
+ {\r
+ GNUNET_NETWORK_fdset_zero (efds);\r
+ GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);\r
+ }\r
+ }\r
+\r
+ return retcode;\r
+#endif\r
+}\r
+\r
+/* end of network_socket.c */\r
+++ /dev/null
-/*\r
- This file is part of GNUnet.\r
- (C) 2009 Christian Grothoff (and other contributing authors)\r
-\r
- GNUnet is free software; you can redistribute it and/or modify\r
- it under the terms of the GNU General Public License as published\r
- by the Free Software Foundation; either version 2, or (at your\r
- option) any later version.\r
-\r
- GNUnet is distributed in the hope that it will be useful, but\r
- WITHOUT ANY WARRANTY; without even the implied warranty of\r
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU\r
- General Public License for more details.\r
-\r
- You should have received a copy of the GNU General Public License\r
- along with GNUnet; see the file COPYING. If not, write to the\r
- Free Software Foundation, Inc., 59 Temple Place - Suite 330,\r
- Boston, MA 02111-1307, USA.\r
-*/\r
-\r
-/**\r
- * @file util/sock.c\r
- * @brief basic, low-level networking interface\r
- * @author Nils Durner\r
- */\r
-\r
-#include "platform.h"\r
-#include "gnunet_disk_lib.h"\r
-#include "disk.h"\r
-#include "gnunet_container_lib.h"\r
-\r
-#define DEBUG_SOCK GNUNET_NO\r
-\r
-struct GNUNET_NETWORK_Descriptor\r
-{\r
- int fd;\r
-};\r
-\r
-struct GNUNET_NETWORK_FDSet\r
-{\r
- /* socket descriptors */\r
- int nsds;\r
- fd_set sds;\r
-#ifdef WINDOWS\r
- /* handles */\r
- struct GNUNET_CONTAINER_Vector *handles;\r
-#endif\r
-};\r
-\r
-#ifndef FD_COPY\r
-#define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set)))\r
-#endif\r
-\r
-struct GNUNET_NETWORK_Descriptor *\r
-GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc,\r
- struct sockaddr *address,\r
- socklen_t * address_len)\r
-{\r
- struct GNUNET_NETWORK_Descriptor *ret;\r
-\r
- ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor));\r
- ret->fd = accept (desc->fd, address, address_len);\r
-#ifdef MINGW\r
- if (INVALID_SOCKET == ret->fd)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
- return ret;\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Descriptor *desc,\r
- const struct sockaddr *address,\r
- socklen_t address_len)\r
-{\r
- int ret;\r
-\r
- ret = bind (desc->fd, address, address_len);\r
-#ifdef MINGW\r
- if (SOCKET_ERROR == ret)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
- return ret;\r
-}\r
-\r
-/**\r
- * Set if a socket should use blocking or non-blocking IO.\r
- *\r
- * @return GNUNET_OK on success, GNUNET_SYSERR on error\r
- */\r
-int\r
-GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Descriptor *fd,\r
- int doBlock)\r
-{\r
-#if MINGW\r
- u_long mode;\r
- mode = !doBlock;\r
- if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR)\r
- {\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket");\r
- return GNUNET_SYSERR;\r
- }\r
- return GNUNET_OK;\r
-\r
-#else\r
- /* not MINGW */\r
- int flags = fcntl (fd->fd, F_GETFL);\r
- if (flags == -1)\r
- {\r
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");\r
- return GNUNET_SYSERR;\r
- }\r
- if (doBlock)\r
- flags &= ~O_NONBLOCK;\r
- else\r
- flags |= O_NONBLOCK;\r
- if (0 != fcntl (fd->fd, F_SETFL, flags))\r
- {\r
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl");\r
- return GNUNET_SYSERR;\r
- }\r
- return GNUNET_OK;\r
-#endif\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Descriptor *desc)\r
-{\r
- int ret;\r
-#ifdef MINGW\r
- ret = closesocket (desc->fd);\r
- if (SOCKET_ERROR != ret)\r
- GNUNET_free (desc);\r
- else\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#else\r
- ret = close (desc->fd);\r
- if (-1 == ret)\r
- {\r
- GNUNET_free (desc);\r
- }\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Descriptor *desc,\r
- const struct sockaddr *address,\r
- socklen_t address_len)\r
-{\r
- int ret;\r
-\r
- ret = connect (desc->fd, address, address_len);\r
-#ifdef MINGW\r
- if (SOCKET_ERROR == ret)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
- return ret;\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Descriptor *desc,\r
- int level, int optname, void *optval,\r
- socklen_t * optlen)\r
-{\r
- int ret;\r
-\r
- ret = getsockopt (desc->fd, level, optname, optval, optlen);\r
-#ifdef MINGW\r
- if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR)\r
- *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval));\r
- else if (SOCKET_ERROR == ret)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
- return ret;\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Descriptor *desc,\r
- int backlog)\r
-{\r
- int ret;\r
-\r
- ret = listen (desc->fd, backlog);\r
-#ifdef MINGW\r
- if (SOCKET_ERROR == ret)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-ssize_t\r
-GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Descriptor * desc,\r
- void *buffer, size_t length, int flags)\r
-{\r
- int ret;\r
-\r
- ret = recv (desc->fd, buffer, length, flags);\r
-#ifdef MINGW\r
- if (SOCKET_ERROR == ret)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-ssize_t\r
-GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Descriptor * desc,\r
- const void *buffer, size_t length, int flags)\r
-{\r
- int ret;\r
-\r
- ret = send (desc->fd, buffer, length, flags);\r
-#ifdef MINGW\r
- if (SOCKET_ERROR == ret)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-ssize_t\r
-GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Descriptor * desc,\r
- const void *message, size_t length, int flags,\r
- const struct sockaddr * dest_addr,\r
- socklen_t dest_len)\r
-{\r
- int ret;\r
-\r
- ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len);\r
-#ifdef MINGW\r
- if (SOCKET_ERROR == ret)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Descriptor *fd,\r
- int level, int option_name,\r
- const void *option_value,\r
- socklen_t option_len)\r
-{\r
- int ret;\r
-\r
- ret = setsockopt (fd->fd, level, option_name, option_value, option_len);\r
-#ifdef MINGW\r
- if (SOCKET_ERROR == ret)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-struct GNUNET_NETWORK_Descriptor *\r
-GNUNET_NETWORK_socket_socket (int domain, int type, int protocol)\r
-{\r
- struct GNUNET_NETWORK_Descriptor *ret;\r
-\r
- ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor));\r
- ret->fd = socket (domain, type, protocol);\r
-#ifdef MINGW\r
- if (INVALID_SOCKET == ret->fd)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
-\r
- if (ret->fd < 0)\r
- {\r
- GNUNET_free (ret);\r
- ret = NULL;\r
- }\r
-\r
- return ret;\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Descriptor *desc,\r
- int how)\r
-{\r
- int ret;\r
-\r
- ret = shutdown (desc->fd, how);\r
-#ifdef MINGW\r
- if (ret != 0)\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
-#endif\r
-\r
- return ret;\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor\r
- *desc)\r
-{\r
-#ifdef MINGW\r
- errno = ENOSYS;\r
- return GNUNET_SYSERR;\r
-#else\r
- return fcntl (desc->fd, F_SETFD,\r
- fcntl (desc->fd,\r
- F_GETFD) | FD_CLOEXEC) ==\r
- 0 ? GNUNET_OK : GNUNET_SYSERR;\r
-#endif\r
-}\r
-\r
-void\r
-GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds)\r
-{\r
- FD_ZERO (&fds->sds);\r
- fds->nsds = 0;\r
-#ifdef MINGW\r
- if (fds->handles)\r
- GNUNET_CONTAINER_vector_destroy (fds->handles);\r
- fds->handles = GNUNET_CONTAINER_vector_create (2);\r
-#endif\r
-}\r
-\r
-void\r
-GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds,\r
- const struct GNUNET_NETWORK_Descriptor *desc)\r
-{\r
- FD_SET (desc->fd, &fds->sds);\r
-\r
- if (desc->fd + 1 > fds->nsds)\r
- fds->nsds = desc->fd + 1;\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds,\r
- const struct GNUNET_NETWORK_Descriptor *desc)\r
-{\r
- return FD_ISSET (desc->fd, &fds->sds);\r
-}\r
-\r
-void\r
-GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst,\r
- const struct GNUNET_NETWORK_FDSet *src)\r
-{\r
- int nfds;\r
-\r
- for (nfds = src->nsds; nfds > 0; nfds--)\r
- if (FD_ISSET (nfds, &src->sds))\r
- {\r
- FD_SET (nfds, &dst->sds);\r
- if (nfds + 1 > dst->nsds)\r
- dst->nsds = nfds + 1;\r
- }\r
-}\r
-\r
-void\r
-GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to,\r
- const struct GNUNET_NETWORK_FDSet *from)\r
-{\r
- FD_COPY (&from->sds, &to->sds);\r
- to->nsds = from->nsds;\r
-#ifdef MINGW\r
- void *obj;\r
-\r
- if (to->handles)\r
- GNUNET_CONTAINER_vector_destroy (to->handles);\r
- to->handles = GNUNET_CONTAINER_vector_create (2);\r
- for (obj = GNUNET_CONTAINER_vector_get_first (from->handles); obj != NULL;\r
- obj = GNUNET_CONTAINER_vector_get_next (from->handles))\r
- {\r
- GNUNET_CONTAINER_vector_insert_last (to->handles, obj);\r
- }\r
-#endif\r
-}\r
-\r
-void\r
-GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to,\r
- const fd_set * from, int nfds)\r
-{\r
- FD_COPY (from, &to->sds);\r
- to->nsds = nfds;\r
-}\r
-\r
-void\r
-GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds,\r
- const struct GNUNET_DISK_FileHandle *h)\r
-{\r
-#ifdef MINGW\r
- HANDLE hw;\r
-\r
- GNUNET_internal_disk_file_handle (h, &hw, sizeof (HANDLE));\r
- GNUNET_CONTAINER_vector_insert_last (fds->handles, h);\r
-#else\r
- int fd;\r
-\r
- GNUNET_internal_disk_file_handle (h, &fd, sizeof (int));\r
- FD_SET (fd, &fds->sds);\r
- if (fd + 1 > fds->nsds)\r
- fds->nsds = fd + 1;\r
-#endif\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds,\r
- const struct GNUNET_DISK_FileHandle *h)\r
-{\r
-#ifdef MINGW\r
- return GNUNET_CONTAINER_vector_index_of (fds->handles, h->h) !=\r
- (unsigned int) -1;\r
-#else\r
- return FD_ISSET (h->fd, &fds->sds);\r
-#endif\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1,\r
- const struct GNUNET_NETWORK_FDSet *fds2)\r
-{\r
- int nfds;\r
-\r
- nfds = fds1->nsds;\r
- if (nfds < fds2->nsds)\r
- nfds = fds2->nsds;\r
-\r
- for (; nfds >= 0; nfds--)\r
- if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds))\r
- return GNUNET_YES;\r
-\r
- return GNUNET_NO;\r
-}\r
-\r
-struct GNUNET_NETWORK_FDSet *\r
-GNUNET_NETWORK_fdset_create ()\r
-{\r
- struct GNUNET_NETWORK_FDSet *fds;\r
-\r
- fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet));\r
-#ifdef MINGW\r
- fds->handles = NULL;\r
-#endif\r
- GNUNET_NETWORK_fdset_zero (fds);\r
-\r
- return fds;\r
-}\r
-\r
-void\r
-GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds)\r
-{\r
-#ifdef MINGW\r
- GNUNET_CONTAINER_vector_destroy (fds->handles);\r
-#endif\r
- GNUNET_free (fds);\r
-}\r
-\r
-int\r
-GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds,\r
- struct GNUNET_NETWORK_FDSet *wfds,\r
- struct GNUNET_NETWORK_FDSet *efds,\r
- const struct GNUNET_TIME_Relative timeout)\r
-{\r
- int nfds;\r
-\r
- nfds = 0;\r
-\r
- if (rfds)\r
- nfds = rfds->nsds;\r
- if (wfds && wfds->nsds > nfds)\r
- nfds = wfds->nsds;\r
- if (efds && efds->nsds > nfds)\r
- nfds = efds->nsds;\r
-\r
-#ifndef MINGW\r
- struct timeval tv;\r
-\r
- tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value;\r
- tv.tv_usec = (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value))\r
- / GNUNET_TIME_UNIT_MILLISECONDS.value;\r
-\r
- return select (nfds + 1, rfds ? &rfds->sds : NULL, wfds ? &wfds->sds : NULL,\r
- efds ? &efds->sds : NULL, timeout.value\r
- == GNUNET_TIME_UNIT_FOREVER_REL.value ? NULL : &tv);\r
-#else\r
- DWORD limit;\r
- fd_set sock_read, sock_write, sock_except;\r
- fd_set aread, awrite, aexcept;\r
- int i;\r
- struct timeval tvslice;\r
- int retcode;\r
- DWORD ms_total;\r
-\r
-#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set))\r
-\r
- /* calculate how long we need to wait in milliseconds */\r
- if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value)\r
- ms_total = INFINITE;\r
- else\r
- ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value;\r
-\r
- /* select() may be used as a portable way to sleep */\r
- if (!(rfds || wfds || efds))\r
- {\r
- Sleep (ms_total);\r
-\r
- return 0;\r
- }\r
-\r
- if (rfds)\r
- sock_read = rfds->sds;\r
- else\r
- FD_ZERO(&sock_read);\r
-\r
- if (wfds)\r
- sock_write = wfds->sds;\r
- else\r
- FD_ZERO(&sock_write);\r
-\r
- if (efds)\r
- sock_except = efds->sds;\r
- else\r
- FD_ZERO(&sock_except);\r
-\r
- /*\r
- if (rfds)\r
- FD_COPY (&rfds->sds, &sock_read);\r
- else\r
- FD_ZERO(&sock_read);\r
-\r
- if (wfds)\r
- FD_COPY (&wfds->sds, &sock_write);\r
- else\r
- FD_ZERO(&sock_write);\r
-\r
- if (efds)\r
- FD_COPY (&efds->sds, &sock_except);\r
- else\r
- FD_ZERO(&sock_except);\r
-*/\r
-\r
- /* multiplex between winsock select() and waiting on the handles */\r
-\r
- FD_ZERO (&aread);\r
- FD_ZERO (&awrite);\r
- FD_ZERO (&aexcept);\r
-\r
- limit = GetTickCount () + ms_total;\r
- do\r
- {\r
- retcode = 0;\r
-\r
- if (nfds > 0)\r
- {\r
- /* overwrite the zero'd sets here; the select call\r
- * will clear those that are not active */\r
-\r
- FD_COPY (&sock_read, &aread);\r
- FD_COPY (&sock_write, &awrite);\r
- FD_COPY (&sock_except, &aexcept);\r
-\r
- tvslice.tv_sec = 0;\r
- tvslice.tv_usec = 100000;\r
-\r
- if ((retcode =\r
- select (nfds + 1, &aread, &awrite, &aexcept,\r
- &tvslice)) == SOCKET_ERROR)\r
- {\r
- SetErrnoFromWinsockError (WSAGetLastError ());\r
- if (errno == ENOTSOCK)\r
- errno = EBADF;\r
-\r
-#if DEBUG_SOCK\r
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select");\r
-#endif\r
-\r
- goto select_loop_end;\r
- }\r
- }\r
-\r
- /* Poll read pipes */\r
- if (rfds)\r
- for (i = GNUNET_CONTAINER_vector_size (rfds->handles) - 1; i >= 0; i--)\r
- {\r
- DWORD dwBytes;\r
-\r
- if (!PeekNamedPipe\r
- (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0,\r
- NULL, &dwBytes, NULL))\r
- {\r
- GNUNET_CONTAINER_vector_remove_at (rfds->handles, i);\r
-\r
- retcode = -1;\r
- SetErrnoFromWinError (GetLastError ());\r
-#if DEBUG_SOCK\r
- GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "PeekNamedPipe");\r
-#endif\r
- goto select_loop_end;\r
- }\r
- else if (dwBytes)\r
- {\r
- retcode++;\r
- }\r
- else\r
- GNUNET_CONTAINER_vector_remove_at (rfds->handles, i);\r
- }\r
-\r
- /* Poll for faulty pipes */\r
- if (efds)\r
- for (i = GNUNET_CONTAINER_vector_size (efds->handles); i >= 0; i--)\r
- {\r
- DWORD dwBytes;\r
-\r
- if (PeekNamedPipe\r
- (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0,\r
- NULL, &dwBytes, NULL))\r
- {\r
- GNUNET_CONTAINER_vector_remove_at (efds->handles, i);\r
-\r
- retcode++;\r
- }\r
- }\r
-\r
- /* FIXME */\r
- if (wfds)\r
- GNUNET_assert (GNUNET_CONTAINER_vector_size (wfds->handles) == 0);\r
-\r
- /* Check for closed sockets */\r
- for (i = 0; i < nfds; i++)\r
- {\r
- if (SAFE_FD_ISSET (i, &sock_read))\r
- {\r
- struct sockaddr addr;\r
- int len;\r
-\r
- if (getpeername (i, &addr, &len) == SOCKET_ERROR)\r
- {\r
- int err, len;\r
-\r
- len = sizeof (err);\r
- if (getsockopt\r
- (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0\r
- && err == WSAENOTCONN)\r
- {\r
- if (!SAFE_FD_ISSET (i, &aread))\r
- {\r
- FD_SET (i, &aread);\r
- retcode++;\r
- }\r
- }\r
- }\r
- }\r
- }\r
-\r
- select_loop_end:;\r
- }\r
- while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit));\r
-\r
- if (retcode != -1)\r
- {\r
- if (rfds)\r
- {\r
- GNUNET_NETWORK_fdset_zero (rfds);\r
- GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode);\r
- }\r
-\r
- if (wfds)\r
- {\r
- GNUNET_NETWORK_fdset_zero (wfds);\r
- GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode);\r
- }\r
-\r
- if (efds)\r
- {\r
- GNUNET_NETWORK_fdset_zero (efds);\r
- GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode);\r
- }\r
- }\r
-\r
- return retcode;\r
-#endif\r
-}\r
-\r
-/* end of network_socket.c */\r