From: Christian Grothoff Date: Sat, 29 Aug 2009 19:46:39 +0000 (+0000) Subject: more fixes X-Git-Tag: initial-import-from-subversion-38251~23570 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=ab3a3be75688c71b23570406816dbd12c67529ec;p=oweals%2Fgnunet.git more fixes --- diff --git a/src/include/gnunet_container_lib.h b/src/include/gnunet_container_lib.h index 1adae17b1..087324174 100644 --- a/src/include/gnunet_container_lib.h +++ b/src/include/gnunet_container_lib.h @@ -52,10 +52,13 @@ struct GNUNET_CONTAINER_BloomFilter; /** * 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. @@ -170,14 +173,14 @@ int GNUNET_CONTAINER_bloomfilter_or (struct GNUNET_CONTAINER_BloomFilter *bf, * * @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 ******************* */ @@ -276,14 +279,14 @@ void GNUNET_CONTAINER_meta_data_add_publication_date (struct * 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. diff --git a/src/include/gnunet_disk_lib.h b/src/include/gnunet_disk_lib.h index f4fd6f36b..cb88fd3d0 100644 --- a/src/include/gnunet_disk_lib.h +++ b/src/include/gnunet_disk_lib.h @@ -22,18 +22,27 @@ * @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 +#include "gnunet_configuration_lib.h" +#include "gnunet_scheduler_lib.h" #ifdef __cplusplus extern "C" @@ -43,6 +52,7 @@ extern "C" #endif #endif + /* Open the file for reading */ #define GNUNET_DISK_OPEN_READ 1 /* Open the file for writing */ @@ -79,10 +89,6 @@ enum GNUNET_DISK_Seek 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). diff --git a/src/include/gnunet_network_lib.h b/src/include/gnunet_network_lib.h index 5828456ca..726114758 100644 --- a/src/include/gnunet_network_lib.h +++ b/src/include/gnunet_network_lib.h @@ -35,8 +35,6 @@ extern "C" #endif #endif -#include "gnunet_disk_lib.h" -#include "gnunet_time_lib.h" /** @@ -50,9 +48,14 @@ struct GNUNET_NETWORK_Descriptor; 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 diff --git a/src/include/gnunet_scheduler_lib.h b/src/include/gnunet_scheduler_lib.h index 86f709ed6..0ace207ec 100644 --- a/src/include/gnunet_scheduler_lib.h +++ b/src/include/gnunet_scheduler_lib.h @@ -36,9 +36,6 @@ extern "C" #endif -#include "gnunet_time_lib.h" -#include "gnunet_network_lib.h" - /** * Opaque handle for the scheduling service. */ @@ -151,6 +148,9 @@ enum GNUNET_SCHEDULER_Priority GNUNET_SCHEDULER_PRIORITY_COUNT = 7 }; +#include "gnunet_time_lib.h" +#include "gnunet_network_lib.h" + /** * Context information passed to each scheduler task. diff --git a/src/util/container_bloomfilter.c b/src/util/container_bloomfilter.c index 9efc2647c..5cc947bd6 100644 --- a/src/util/container_bloomfilter.c +++ b/src/util/container_bloomfilter.c @@ -277,12 +277,13 @@ makeEmptyFile (const struct GNUNET_DISK_FileHandle *fh, unsigned int size) * 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 @@ -309,9 +310,10 @@ iterateBits (struct GNUNET_CONTAINER_BloomFilter *bf, { 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) @@ -330,13 +332,14 @@ iterateBits (struct GNUNET_CONTAINER_BloomFilter *bf, /** * 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); } @@ -344,13 +347,14 @@ incrementBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf, /** * 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); } @@ -358,13 +362,13 @@ decrementBitCallback (struct GNUNET_CONTAINER_BloomFilter *bf, /** * 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)) @@ -674,7 +678,7 @@ GNUNET_CONTAINER_bloomfilter_resize (struct GNUNET_CONTAINER_BloomFilter *bf, 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); } diff --git a/src/util/network.c b/src/util/network.c new file mode 100644 index 000000000..9c50d6fcd --- /dev/null +++ b/src/util/network.c @@ -0,0 +1,678 @@ +/* + This file is part of GNUnet. + (C) 2009 Christian Grothoff (and other contributing authors) + + GNUnet is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation; either version 2, or (at your + option) any later version. + + GNUnet is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with GNUnet; see the file COPYING. If not, write to the + Free Software Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. +*/ + +/** + * @file util/sock.c + * @brief basic, low-level networking interface + * @author Nils Durner + */ + +#include "platform.h" +#include "gnunet_disk_lib.h" +#include "disk.h" +#include "gnunet_container_lib.h" + +#define DEBUG_SOCK GNUNET_NO + +struct GNUNET_NETWORK_Descriptor +{ + int fd; +}; + +struct GNUNET_NETWORK_FDSet +{ + /* socket descriptors */ + int nsds; + fd_set sds; +#ifdef WINDOWS + /* handles */ + struct GNUNET_CONTAINER_Vector *handles; +#endif +}; + +#ifndef FD_COPY +#define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) +#endif + +struct GNUNET_NETWORK_Descriptor * +GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc, + struct sockaddr *address, + socklen_t * address_len) +{ + struct GNUNET_NETWORK_Descriptor *ret; + + ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor)); + ret->fd = accept (desc->fd, address, address_len); +#ifdef MINGW + if (INVALID_SOCKET == ret->fd) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + return ret; +} + +int +GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Descriptor *desc, + const struct sockaddr *address, + socklen_t address_len) +{ + int ret; + + ret = bind (desc->fd, address, address_len); +#ifdef MINGW + if (SOCKET_ERROR == ret) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + return ret; +} + +/** + * Set if a socket should use blocking or non-blocking IO. + * + * @return GNUNET_OK on success, GNUNET_SYSERR on error + */ +int +GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Descriptor *fd, + int doBlock) +{ +#if MINGW + u_long mode; + mode = !doBlock; + if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR) + { + SetErrnoFromWinsockError (WSAGetLastError ()); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket"); + return GNUNET_SYSERR; + } + return GNUNET_OK; + +#else + /* not MINGW */ + int flags = fcntl (fd->fd, F_GETFL); + if (flags == -1) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl"); + return GNUNET_SYSERR; + } + if (doBlock) + flags &= ~O_NONBLOCK; + else + flags |= O_NONBLOCK; + if (0 != fcntl (fd->fd, F_SETFL, flags)) + { + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl"); + return GNUNET_SYSERR; + } + return GNUNET_OK; +#endif +} + +int +GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Descriptor *desc) +{ + int ret; +#ifdef MINGW + ret = closesocket (desc->fd); + if (SOCKET_ERROR != ret) + GNUNET_free (desc); + else + SetErrnoFromWinsockError (WSAGetLastError ()); +#else + ret = close (desc->fd); + if (-1 == ret) + { + GNUNET_free (desc); + } +#endif + + return ret; +} + +int +GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Descriptor *desc, + const struct sockaddr *address, + socklen_t address_len) +{ + int ret; + + ret = connect (desc->fd, address, address_len); +#ifdef MINGW + if (SOCKET_ERROR == ret) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + return ret; +} + +int +GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Descriptor *desc, + int level, int optname, void *optval, + socklen_t * optlen) +{ + int ret; + + ret = getsockopt (desc->fd, level, optname, optval, optlen); +#ifdef MINGW + if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR) + *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval)); + else if (SOCKET_ERROR == ret) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + return ret; +} + +int +GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Descriptor *desc, + int backlog) +{ + int ret; + + ret = listen (desc->fd, backlog); +#ifdef MINGW + if (SOCKET_ERROR == ret) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + + return ret; +} + +ssize_t +GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Descriptor * desc, + void *buffer, size_t length, int flags) +{ + int ret; + + ret = recv (desc->fd, buffer, length, flags); +#ifdef MINGW + if (SOCKET_ERROR == ret) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + + return ret; +} + +ssize_t +GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Descriptor * desc, + const void *buffer, size_t length, int flags) +{ + int ret; + + ret = send (desc->fd, buffer, length, flags); +#ifdef MINGW + if (SOCKET_ERROR == ret) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + + return ret; +} + +ssize_t +GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Descriptor * desc, + const void *message, size_t length, int flags, + const struct sockaddr * dest_addr, + socklen_t dest_len) +{ + int ret; + + ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len); +#ifdef MINGW + if (SOCKET_ERROR == ret) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + + return ret; +} + +int +GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Descriptor *fd, + int level, int option_name, + const void *option_value, + socklen_t option_len) +{ + int ret; + + ret = setsockopt (fd->fd, level, option_name, option_value, option_len); +#ifdef MINGW + if (SOCKET_ERROR == ret) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + + return ret; +} + +struct GNUNET_NETWORK_Descriptor * +GNUNET_NETWORK_socket_socket (int domain, int type, int protocol) +{ + struct GNUNET_NETWORK_Descriptor *ret; + + ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor)); + ret->fd = socket (domain, type, protocol); +#ifdef MINGW + if (INVALID_SOCKET == ret->fd) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + + if (ret->fd < 0) + { + GNUNET_free (ret); + ret = NULL; + } + + return ret; +} + +int +GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Descriptor *desc, + int how) +{ + int ret; + + ret = shutdown (desc->fd, how); +#ifdef MINGW + if (ret != 0) + SetErrnoFromWinsockError (WSAGetLastError ()); +#endif + + return ret; +} + +int +GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor + *desc) +{ +#ifdef MINGW + errno = ENOSYS; + return GNUNET_SYSERR; +#else + return fcntl (desc->fd, F_SETFD, + fcntl (desc->fd, + F_GETFD) | FD_CLOEXEC) == + 0 ? GNUNET_OK : GNUNET_SYSERR; +#endif +} + +void +GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds) +{ + FD_ZERO (&fds->sds); + fds->nsds = 0; +#ifdef MINGW + if (fds->handles) + GNUNET_CONTAINER_vector_destroy (fds->handles); + fds->handles = GNUNET_CONTAINER_vector_create (2); +#endif +} + +void +GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds, + const struct GNUNET_NETWORK_Descriptor *desc) +{ + FD_SET (desc->fd, &fds->sds); + + if (desc->fd + 1 > fds->nsds) + fds->nsds = desc->fd + 1; +} + +int +GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds, + const struct GNUNET_NETWORK_Descriptor *desc) +{ + return FD_ISSET (desc->fd, &fds->sds); +} + +void +GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, + const struct GNUNET_NETWORK_FDSet *src) +{ + int nfds; + + for (nfds = src->nsds; nfds > 0; nfds--) + if (FD_ISSET (nfds, &src->sds)) + { + FD_SET (nfds, &dst->sds); + if (nfds + 1 > dst->nsds) + dst->nsds = nfds + 1; + } +} + +void +GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, + const struct GNUNET_NETWORK_FDSet *from) +{ + FD_COPY (&from->sds, &to->sds); + to->nsds = from->nsds; +#ifdef MINGW + void *obj; + + if (to->handles) + GNUNET_CONTAINER_vector_destroy (to->handles); + to->handles = GNUNET_CONTAINER_vector_create (2); + for (obj = GNUNET_CONTAINER_vector_get_first (from->handles); obj != NULL; + obj = GNUNET_CONTAINER_vector_get_next (from->handles)) + { + GNUNET_CONTAINER_vector_insert_last (to->handles, obj); + } +#endif +} + +void +GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to, + const fd_set * from, int nfds) +{ + FD_COPY (from, &to->sds); + to->nsds = nfds; +} + +void +GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds, + const struct GNUNET_DISK_FileHandle *h) +{ +#ifdef MINGW + HANDLE hw; + + GNUNET_internal_disk_file_handle (h, &hw, sizeof (HANDLE)); + GNUNET_CONTAINER_vector_insert_last (fds->handles, h); +#else + int fd; + + GNUNET_internal_disk_file_handle (h, &fd, sizeof (int)); + FD_SET (fd, &fds->sds); + if (fd + 1 > fds->nsds) + fds->nsds = fd + 1; +#endif +} + +int +GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds, + const struct GNUNET_DISK_FileHandle *h) +{ +#ifdef MINGW + return GNUNET_CONTAINER_vector_index_of (fds->handles, h->h) != + (unsigned int) -1; +#else + return FD_ISSET (h->fd, &fds->sds); +#endif +} + +int +GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, + const struct GNUNET_NETWORK_FDSet *fds2) +{ + int nfds; + + nfds = fds1->nsds; + if (nfds < fds2->nsds) + nfds = fds2->nsds; + + for (; nfds >= 0; nfds--) + if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds)) + return GNUNET_YES; + + return GNUNET_NO; +} + +struct GNUNET_NETWORK_FDSet * +GNUNET_NETWORK_fdset_create () +{ + struct GNUNET_NETWORK_FDSet *fds; + + fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet)); +#ifdef MINGW + fds->handles = NULL; +#endif + GNUNET_NETWORK_fdset_zero (fds); + + return fds; +} + +void +GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds) +{ +#ifdef MINGW + GNUNET_CONTAINER_vector_destroy (fds->handles); +#endif + GNUNET_free (fds); +} + +int +GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, + struct GNUNET_NETWORK_FDSet *wfds, + struct GNUNET_NETWORK_FDSet *efds, + const struct GNUNET_TIME_Relative timeout) +{ + int nfds; + + nfds = 0; + + if (rfds) + nfds = rfds->nsds; + if (wfds && wfds->nsds > nfds) + nfds = wfds->nsds; + if (efds && efds->nsds > nfds) + nfds = efds->nsds; + +#ifndef MINGW + struct timeval tv; + + tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value; + tv.tv_usec = (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value)) + / GNUNET_TIME_UNIT_MILLISECONDS.value; + + return select (nfds + 1, rfds ? &rfds->sds : NULL, wfds ? &wfds->sds : NULL, + efds ? &efds->sds : NULL, timeout.value + == GNUNET_TIME_UNIT_FOREVER_REL.value ? NULL : &tv); +#else + DWORD limit; + fd_set sock_read, sock_write, sock_except; + fd_set aread, awrite, aexcept; + int i; + struct timeval tvslice; + int retcode; + DWORD ms_total; + +#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) + + /* calculate how long we need to wait in milliseconds */ + if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value) + ms_total = INFINITE; + else + ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value; + + /* select() may be used as a portable way to sleep */ + if (!(rfds || wfds || efds)) + { + Sleep (ms_total); + + return 0; + } + + if (rfds) + sock_read = rfds->sds; + else + FD_ZERO(&sock_read); + + if (wfds) + sock_write = wfds->sds; + else + FD_ZERO(&sock_write); + + if (efds) + sock_except = efds->sds; + else + FD_ZERO(&sock_except); + + /* + if (rfds) + FD_COPY (&rfds->sds, &sock_read); + else + FD_ZERO(&sock_read); + + if (wfds) + FD_COPY (&wfds->sds, &sock_write); + else + FD_ZERO(&sock_write); + + if (efds) + FD_COPY (&efds->sds, &sock_except); + else + FD_ZERO(&sock_except); +*/ + + /* multiplex between winsock select() and waiting on the handles */ + + FD_ZERO (&aread); + FD_ZERO (&awrite); + FD_ZERO (&aexcept); + + limit = GetTickCount () + ms_total; + do + { + retcode = 0; + + if (nfds > 0) + { + /* overwrite the zero'd sets here; the select call + * will clear those that are not active */ + + FD_COPY (&sock_read, &aread); + FD_COPY (&sock_write, &awrite); + FD_COPY (&sock_except, &aexcept); + + tvslice.tv_sec = 0; + tvslice.tv_usec = 100000; + + if ((retcode = + select (nfds + 1, &aread, &awrite, &aexcept, + &tvslice)) == SOCKET_ERROR) + { + SetErrnoFromWinsockError (WSAGetLastError ()); + if (errno == ENOTSOCK) + errno = EBADF; + +#if DEBUG_SOCK + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select"); +#endif + + goto select_loop_end; + } + } + + /* Poll read pipes */ + if (rfds) + for (i = GNUNET_CONTAINER_vector_size (rfds->handles) - 1; i >= 0; i--) + { + DWORD dwBytes; + + if (!PeekNamedPipe + (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0, + NULL, &dwBytes, NULL)) + { + GNUNET_CONTAINER_vector_remove_at (rfds->handles, i); + + retcode = -1; + SetErrnoFromWinError (GetLastError ()); +#if DEBUG_SOCK + GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "PeekNamedPipe"); +#endif + goto select_loop_end; + } + else if (dwBytes) + { + retcode++; + } + else + GNUNET_CONTAINER_vector_remove_at (rfds->handles, i); + } + + /* Poll for faulty pipes */ + if (efds) + for (i = GNUNET_CONTAINER_vector_size (efds->handles); i >= 0; i--) + { + DWORD dwBytes; + + if (PeekNamedPipe + (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0, + NULL, &dwBytes, NULL)) + { + GNUNET_CONTAINER_vector_remove_at (efds->handles, i); + + retcode++; + } + } + + /* FIXME */ + if (wfds) + GNUNET_assert (GNUNET_CONTAINER_vector_size (wfds->handles) == 0); + + /* Check for closed sockets */ + for (i = 0; i < nfds; i++) + { + if (SAFE_FD_ISSET (i, &sock_read)) + { + struct sockaddr addr; + int len; + + if (getpeername (i, &addr, &len) == SOCKET_ERROR) + { + int err, len; + + len = sizeof (err); + if (getsockopt + (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0 + && err == WSAENOTCONN) + { + if (!SAFE_FD_ISSET (i, &aread)) + { + FD_SET (i, &aread); + retcode++; + } + } + } + } + } + + select_loop_end:; + } + while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit)); + + if (retcode != -1) + { + if (rfds) + { + GNUNET_NETWORK_fdset_zero (rfds); + GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode); + } + + if (wfds) + { + GNUNET_NETWORK_fdset_zero (wfds); + GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode); + } + + if (efds) + { + GNUNET_NETWORK_fdset_zero (efds); + GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode); + } + } + + return retcode; +#endif +} + +/* end of network_socket.c */ diff --git a/src/util/network_socket.c b/src/util/network_socket.c deleted file mode 100644 index 9c50d6fcd..000000000 --- a/src/util/network_socket.c +++ /dev/null @@ -1,678 +0,0 @@ -/* - This file is part of GNUnet. - (C) 2009 Christian Grothoff (and other contributing authors) - - GNUnet is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation; either version 2, or (at your - option) any later version. - - GNUnet is distributed in the hope that it will be useful, but - WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - General Public License for more details. - - You should have received a copy of the GNU General Public License - along with GNUnet; see the file COPYING. If not, write to the - Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. -*/ - -/** - * @file util/sock.c - * @brief basic, low-level networking interface - * @author Nils Durner - */ - -#include "platform.h" -#include "gnunet_disk_lib.h" -#include "disk.h" -#include "gnunet_container_lib.h" - -#define DEBUG_SOCK GNUNET_NO - -struct GNUNET_NETWORK_Descriptor -{ - int fd; -}; - -struct GNUNET_NETWORK_FDSet -{ - /* socket descriptors */ - int nsds; - fd_set sds; -#ifdef WINDOWS - /* handles */ - struct GNUNET_CONTAINER_Vector *handles; -#endif -}; - -#ifndef FD_COPY -#define FD_COPY(s, d) (memcpy ((d), (s), sizeof (fd_set))) -#endif - -struct GNUNET_NETWORK_Descriptor * -GNUNET_NETWORK_socket_accept (const struct GNUNET_NETWORK_Descriptor *desc, - struct sockaddr *address, - socklen_t * address_len) -{ - struct GNUNET_NETWORK_Descriptor *ret; - - ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor)); - ret->fd = accept (desc->fd, address, address_len); -#ifdef MINGW - if (INVALID_SOCKET == ret->fd) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - return ret; -} - -int -GNUNET_NETWORK_socket_bind (struct GNUNET_NETWORK_Descriptor *desc, - const struct sockaddr *address, - socklen_t address_len) -{ - int ret; - - ret = bind (desc->fd, address, address_len); -#ifdef MINGW - if (SOCKET_ERROR == ret) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - return ret; -} - -/** - * Set if a socket should use blocking or non-blocking IO. - * - * @return GNUNET_OK on success, GNUNET_SYSERR on error - */ -int -GNUNET_NETWORK_socket_set_blocking (struct GNUNET_NETWORK_Descriptor *fd, - int doBlock) -{ -#if MINGW - u_long mode; - mode = !doBlock; - if (ioctlsocket (fd->fd, FIONBIO, &mode) == SOCKET_ERROR) - { - SetErrnoFromWinsockError (WSAGetLastError ()); - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "ioctlsocket"); - return GNUNET_SYSERR; - } - return GNUNET_OK; - -#else - /* not MINGW */ - int flags = fcntl (fd->fd, F_GETFL); - if (flags == -1) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl"); - return GNUNET_SYSERR; - } - if (doBlock) - flags &= ~O_NONBLOCK; - else - flags |= O_NONBLOCK; - if (0 != fcntl (fd->fd, F_SETFL, flags)) - { - GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, "fcntl"); - return GNUNET_SYSERR; - } - return GNUNET_OK; -#endif -} - -int -GNUNET_NETWORK_socket_close (struct GNUNET_NETWORK_Descriptor *desc) -{ - int ret; -#ifdef MINGW - ret = closesocket (desc->fd); - if (SOCKET_ERROR != ret) - GNUNET_free (desc); - else - SetErrnoFromWinsockError (WSAGetLastError ()); -#else - ret = close (desc->fd); - if (-1 == ret) - { - GNUNET_free (desc); - } -#endif - - return ret; -} - -int -GNUNET_NETWORK_socket_connect (const struct GNUNET_NETWORK_Descriptor *desc, - const struct sockaddr *address, - socklen_t address_len) -{ - int ret; - - ret = connect (desc->fd, address, address_len); -#ifdef MINGW - if (SOCKET_ERROR == ret) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - return ret; -} - -int -GNUNET_NETWORK_socket_getsockopt (const struct GNUNET_NETWORK_Descriptor *desc, - int level, int optname, void *optval, - socklen_t * optlen) -{ - int ret; - - ret = getsockopt (desc->fd, level, optname, optval, optlen); -#ifdef MINGW - if (ret == 0 && level == SOL_SOCKET && optname == SO_ERROR) - *((int *) optval) = GetErrnoFromWinsockError (*((int *) optval)); - else if (SOCKET_ERROR == ret) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - return ret; -} - -int -GNUNET_NETWORK_socket_listen (const struct GNUNET_NETWORK_Descriptor *desc, - int backlog) -{ - int ret; - - ret = listen (desc->fd, backlog); -#ifdef MINGW - if (SOCKET_ERROR == ret) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - - return ret; -} - -ssize_t -GNUNET_NETWORK_socket_recv (const struct GNUNET_NETWORK_Descriptor * desc, - void *buffer, size_t length, int flags) -{ - int ret; - - ret = recv (desc->fd, buffer, length, flags); -#ifdef MINGW - if (SOCKET_ERROR == ret) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - - return ret; -} - -ssize_t -GNUNET_NETWORK_socket_send (const struct GNUNET_NETWORK_Descriptor * desc, - const void *buffer, size_t length, int flags) -{ - int ret; - - ret = send (desc->fd, buffer, length, flags); -#ifdef MINGW - if (SOCKET_ERROR == ret) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - - return ret; -} - -ssize_t -GNUNET_NETWORK_socket_sendto (const struct GNUNET_NETWORK_Descriptor * desc, - const void *message, size_t length, int flags, - const struct sockaddr * dest_addr, - socklen_t dest_len) -{ - int ret; - - ret = sendto (desc->fd, message, length, flags, dest_addr, dest_len); -#ifdef MINGW - if (SOCKET_ERROR == ret) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - - return ret; -} - -int -GNUNET_NETWORK_socket_setsockopt (struct GNUNET_NETWORK_Descriptor *fd, - int level, int option_name, - const void *option_value, - socklen_t option_len) -{ - int ret; - - ret = setsockopt (fd->fd, level, option_name, option_value, option_len); -#ifdef MINGW - if (SOCKET_ERROR == ret) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - - return ret; -} - -struct GNUNET_NETWORK_Descriptor * -GNUNET_NETWORK_socket_socket (int domain, int type, int protocol) -{ - struct GNUNET_NETWORK_Descriptor *ret; - - ret = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_Descriptor)); - ret->fd = socket (domain, type, protocol); -#ifdef MINGW - if (INVALID_SOCKET == ret->fd) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - - if (ret->fd < 0) - { - GNUNET_free (ret); - ret = NULL; - } - - return ret; -} - -int -GNUNET_NETWORK_socket_shutdown (struct GNUNET_NETWORK_Descriptor *desc, - int how) -{ - int ret; - - ret = shutdown (desc->fd, how); -#ifdef MINGW - if (ret != 0) - SetErrnoFromWinsockError (WSAGetLastError ()); -#endif - - return ret; -} - -int -GNUNET_NETWORK_socket_set_inheritable (const struct GNUNET_NETWORK_Descriptor - *desc) -{ -#ifdef MINGW - errno = ENOSYS; - return GNUNET_SYSERR; -#else - return fcntl (desc->fd, F_SETFD, - fcntl (desc->fd, - F_GETFD) | FD_CLOEXEC) == - 0 ? GNUNET_OK : GNUNET_SYSERR; -#endif -} - -void -GNUNET_NETWORK_fdset_zero (struct GNUNET_NETWORK_FDSet *fds) -{ - FD_ZERO (&fds->sds); - fds->nsds = 0; -#ifdef MINGW - if (fds->handles) - GNUNET_CONTAINER_vector_destroy (fds->handles); - fds->handles = GNUNET_CONTAINER_vector_create (2); -#endif -} - -void -GNUNET_NETWORK_fdset_set (struct GNUNET_NETWORK_FDSet *fds, - const struct GNUNET_NETWORK_Descriptor *desc) -{ - FD_SET (desc->fd, &fds->sds); - - if (desc->fd + 1 > fds->nsds) - fds->nsds = desc->fd + 1; -} - -int -GNUNET_NETWORK_fdset_isset (const struct GNUNET_NETWORK_FDSet *fds, - const struct GNUNET_NETWORK_Descriptor *desc) -{ - return FD_ISSET (desc->fd, &fds->sds); -} - -void -GNUNET_NETWORK_fdset_add (struct GNUNET_NETWORK_FDSet *dst, - const struct GNUNET_NETWORK_FDSet *src) -{ - int nfds; - - for (nfds = src->nsds; nfds > 0; nfds--) - if (FD_ISSET (nfds, &src->sds)) - { - FD_SET (nfds, &dst->sds); - if (nfds + 1 > dst->nsds) - dst->nsds = nfds + 1; - } -} - -void -GNUNET_NETWORK_fdset_copy (struct GNUNET_NETWORK_FDSet *to, - const struct GNUNET_NETWORK_FDSet *from) -{ - FD_COPY (&from->sds, &to->sds); - to->nsds = from->nsds; -#ifdef MINGW - void *obj; - - if (to->handles) - GNUNET_CONTAINER_vector_destroy (to->handles); - to->handles = GNUNET_CONTAINER_vector_create (2); - for (obj = GNUNET_CONTAINER_vector_get_first (from->handles); obj != NULL; - obj = GNUNET_CONTAINER_vector_get_next (from->handles)) - { - GNUNET_CONTAINER_vector_insert_last (to->handles, obj); - } -#endif -} - -void -GNUNET_NETWORK_fdset_copy_native (struct GNUNET_NETWORK_FDSet *to, - const fd_set * from, int nfds) -{ - FD_COPY (from, &to->sds); - to->nsds = nfds; -} - -void -GNUNET_NETWORK_fdset_handle_set (struct GNUNET_NETWORK_FDSet *fds, - const struct GNUNET_DISK_FileHandle *h) -{ -#ifdef MINGW - HANDLE hw; - - GNUNET_internal_disk_file_handle (h, &hw, sizeof (HANDLE)); - GNUNET_CONTAINER_vector_insert_last (fds->handles, h); -#else - int fd; - - GNUNET_internal_disk_file_handle (h, &fd, sizeof (int)); - FD_SET (fd, &fds->sds); - if (fd + 1 > fds->nsds) - fds->nsds = fd + 1; -#endif -} - -int -GNUNET_NETWORK_fdset_handle_isset (const struct GNUNET_NETWORK_FDSet *fds, - const struct GNUNET_DISK_FileHandle *h) -{ -#ifdef MINGW - return GNUNET_CONTAINER_vector_index_of (fds->handles, h->h) != - (unsigned int) -1; -#else - return FD_ISSET (h->fd, &fds->sds); -#endif -} - -int -GNUNET_NETWORK_fdset_overlap (const struct GNUNET_NETWORK_FDSet *fds1, - const struct GNUNET_NETWORK_FDSet *fds2) -{ - int nfds; - - nfds = fds1->nsds; - if (nfds < fds2->nsds) - nfds = fds2->nsds; - - for (; nfds >= 0; nfds--) - if (FD_ISSET (nfds, &fds1->sds) && FD_ISSET (nfds, &fds2->sds)) - return GNUNET_YES; - - return GNUNET_NO; -} - -struct GNUNET_NETWORK_FDSet * -GNUNET_NETWORK_fdset_create () -{ - struct GNUNET_NETWORK_FDSet *fds; - - fds = GNUNET_malloc (sizeof (struct GNUNET_NETWORK_FDSet)); -#ifdef MINGW - fds->handles = NULL; -#endif - GNUNET_NETWORK_fdset_zero (fds); - - return fds; -} - -void -GNUNET_NETWORK_fdset_destroy (struct GNUNET_NETWORK_FDSet *fds) -{ -#ifdef MINGW - GNUNET_CONTAINER_vector_destroy (fds->handles); -#endif - GNUNET_free (fds); -} - -int -GNUNET_NETWORK_socket_select (struct GNUNET_NETWORK_FDSet *rfds, - struct GNUNET_NETWORK_FDSet *wfds, - struct GNUNET_NETWORK_FDSet *efds, - const struct GNUNET_TIME_Relative timeout) -{ - int nfds; - - nfds = 0; - - if (rfds) - nfds = rfds->nsds; - if (wfds && wfds->nsds > nfds) - nfds = wfds->nsds; - if (efds && efds->nsds > nfds) - nfds = efds->nsds; - -#ifndef MINGW - struct timeval tv; - - tv.tv_sec = timeout.value / GNUNET_TIME_UNIT_SECONDS.value; - tv.tv_usec = (timeout.value - (tv.tv_sec * GNUNET_TIME_UNIT_SECONDS.value)) - / GNUNET_TIME_UNIT_MILLISECONDS.value; - - return select (nfds + 1, rfds ? &rfds->sds : NULL, wfds ? &wfds->sds : NULL, - efds ? &efds->sds : NULL, timeout.value - == GNUNET_TIME_UNIT_FOREVER_REL.value ? NULL : &tv); -#else - DWORD limit; - fd_set sock_read, sock_write, sock_except; - fd_set aread, awrite, aexcept; - int i; - struct timeval tvslice; - int retcode; - DWORD ms_total; - -#define SAFE_FD_ISSET(fd, set) (set != NULL && FD_ISSET(fd, set)) - - /* calculate how long we need to wait in milliseconds */ - if (timeout.value == GNUNET_TIME_UNIT_FOREVER_REL.value) - ms_total = INFINITE; - else - ms_total = timeout.value / GNUNET_TIME_UNIT_MILLISECONDS.value; - - /* select() may be used as a portable way to sleep */ - if (!(rfds || wfds || efds)) - { - Sleep (ms_total); - - return 0; - } - - if (rfds) - sock_read = rfds->sds; - else - FD_ZERO(&sock_read); - - if (wfds) - sock_write = wfds->sds; - else - FD_ZERO(&sock_write); - - if (efds) - sock_except = efds->sds; - else - FD_ZERO(&sock_except); - - /* - if (rfds) - FD_COPY (&rfds->sds, &sock_read); - else - FD_ZERO(&sock_read); - - if (wfds) - FD_COPY (&wfds->sds, &sock_write); - else - FD_ZERO(&sock_write); - - if (efds) - FD_COPY (&efds->sds, &sock_except); - else - FD_ZERO(&sock_except); -*/ - - /* multiplex between winsock select() and waiting on the handles */ - - FD_ZERO (&aread); - FD_ZERO (&awrite); - FD_ZERO (&aexcept); - - limit = GetTickCount () + ms_total; - do - { - retcode = 0; - - if (nfds > 0) - { - /* overwrite the zero'd sets here; the select call - * will clear those that are not active */ - - FD_COPY (&sock_read, &aread); - FD_COPY (&sock_write, &awrite); - FD_COPY (&sock_except, &aexcept); - - tvslice.tv_sec = 0; - tvslice.tv_usec = 100000; - - if ((retcode = - select (nfds + 1, &aread, &awrite, &aexcept, - &tvslice)) == SOCKET_ERROR) - { - SetErrnoFromWinsockError (WSAGetLastError ()); - if (errno == ENOTSOCK) - errno = EBADF; - -#if DEBUG_SOCK - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "select"); -#endif - - goto select_loop_end; - } - } - - /* Poll read pipes */ - if (rfds) - for (i = GNUNET_CONTAINER_vector_size (rfds->handles) - 1; i >= 0; i--) - { - DWORD dwBytes; - - if (!PeekNamedPipe - (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0, - NULL, &dwBytes, NULL)) - { - GNUNET_CONTAINER_vector_remove_at (rfds->handles, i); - - retcode = -1; - SetErrnoFromWinError (GetLastError ()); -#if DEBUG_SOCK - GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "PeekNamedPipe"); -#endif - goto select_loop_end; - } - else if (dwBytes) - { - retcode++; - } - else - GNUNET_CONTAINER_vector_remove_at (rfds->handles, i); - } - - /* Poll for faulty pipes */ - if (efds) - for (i = GNUNET_CONTAINER_vector_size (efds->handles); i >= 0; i--) - { - DWORD dwBytes; - - if (PeekNamedPipe - (GNUNET_CONTAINER_vector_get_at (rfds->handles, i), NULL, 0, - NULL, &dwBytes, NULL)) - { - GNUNET_CONTAINER_vector_remove_at (efds->handles, i); - - retcode++; - } - } - - /* FIXME */ - if (wfds) - GNUNET_assert (GNUNET_CONTAINER_vector_size (wfds->handles) == 0); - - /* Check for closed sockets */ - for (i = 0; i < nfds; i++) - { - if (SAFE_FD_ISSET (i, &sock_read)) - { - struct sockaddr addr; - int len; - - if (getpeername (i, &addr, &len) == SOCKET_ERROR) - { - int err, len; - - len = sizeof (err); - if (getsockopt - (i, SOL_SOCKET, SO_ERROR, (char *) &err, &len) == 0 - && err == WSAENOTCONN) - { - if (!SAFE_FD_ISSET (i, &aread)) - { - FD_SET (i, &aread); - retcode++; - } - } - } - } - } - - select_loop_end:; - } - while (retcode == 0 && (ms_total == INFINITE || GetTickCount () < limit)); - - if (retcode != -1) - { - if (rfds) - { - GNUNET_NETWORK_fdset_zero (rfds); - GNUNET_NETWORK_fdset_copy_native (rfds, &aread, retcode); - } - - if (wfds) - { - GNUNET_NETWORK_fdset_zero (wfds); - GNUNET_NETWORK_fdset_copy_native (wfds, &awrite, retcode); - } - - if (efds) - { - GNUNET_NETWORK_fdset_zero (efds); - GNUNET_NETWORK_fdset_copy_native (efds, &aexcept, retcode); - } - } - - return retcode; -#endif -} - -/* end of network_socket.c */