AC_C_INLINE
if test "x$GCC" = "xyes" ; then
- CFLAGS="$CFLAGS -std=gnu99 -ggdb3 -Wall -W -Wpointer-arith -Wformat-security -Wcast-align -Wundef -Wcast-align -Wstrict-prototypes -Wmissing-declarations -Wmissing-format-attribute -Wredundant-decls -Wnested-externs -Wunused-parameter -Wwrite-strings"
+ CFLAGS="$CFLAGS -std=gnu99 -ggdb3 -Wall -W -Wpointer-arith -Wformat-security -Wcast-align -Wundef -Wcast-align -Wstrict-prototypes -Wmissing-declarations -Wmissing-format-attribute -Wredundant-decls -Wnested-externs -Wunused-parameter -Wwrite-strings -Wvariadic-macros -Waggregate-return -Wvla -Winline -Wfloat-equal"
dnl figure out gcc version
AC_MSG_CHECKING([gcc version])
}
}
+char *
+tr_net_strerror( char * buf, size_t buflen, int err )
+{
+ *buf = '\0';
+#ifdef WIN32
+ FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, e, 0, buf, buflen, NULL );
+#else
+ tr_strlcpy( buf, tr_strerror( err ), buflen );
+#endif
+ return buf;
+}
+
const char *
tr_ntop( const tr_address * src, char * dst, int size )
{
void tr_netInit( void );
+/**
+ * @brief get a human-representable string representing the network error.
+ * @param err an errno on Unix/Linux and an WSAError on win32)
+ */
+char* tr_net_strerror( char * buf, size_t buflen, int err );
+
const unsigned char *tr_globalIPv6( void );
#if defined( WIN32) && !defined(QT_DLL)
#define MAGIC_NUMBER 206745
+#ifdef WIN32
+ #define EAGAIN WSAEWOULDBLOCK
+ #define EINTR WSAEINTR
+ #define EINPROGRESS WSAEINPROGRESS
+ #define EPIPE WSAECONNRESET
+#endif
+
static size_t
guessPacketOverhead( size_t d )
{
return;
}
- errno = 0;
+ EVUTIL_SET_SOCKET_ERROR( 0 );
res = evbuffer_read( io->inbuf, fd, howmuch );
- e = errno;
+ e = EVUTIL_SOCKET_ERROR( );
if( res > 0 )
{
}
else
{
+ char errstr[512];
short what = EVBUFFER_READ;
if( res == 0 ) /* EOF */
what |= EVBUFFER_ERROR;
}
- dbgmsg( io, "event_read_cb got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, strerror( e ) );
+ tr_net_strerror( errstr, sizeof( errstr ), e );
+ dbgmsg( io, "event_read_cb got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, errstr );
if( io->gotError != NULL )
io->gotError( io, what, io->userData );
{
int e;
int n;
+ char errstr[256];
struct evbuffer * buffer = io->outbuf;
howmuch = MIN( EVBUFFER_LENGTH( buffer ), howmuch );
- errno = 0;
+ EVUTIL_SET_SOCKET_ERROR( 0 );
#ifdef WIN32
n = (int) send(fd, buffer->buffer, howmuch, 0 );
#else
n = (int) write(fd, buffer->buffer, howmuch );
#endif
- e = errno;
- dbgmsg( io, "wrote %d to peer (%s)", n, (n==-1?strerror(e):"") );
+ e = EVUTIL_SOCKET_ERROR( );
+ dbgmsg( io, "wrote %d to peer (%s)", n, (n==-1?tr_net_strerror(errstr,sizeof(errstr),e):"") );
if( n > 0 )
evbuffer_drain( buffer, n );
return;
}
- errno = 0;
+ EVUTIL_SET_SOCKET_ERROR( 0 );
res = tr_evbuffer_write( io, fd, howmuch );
- e = errno;
+ e = EVUTIL_SOCKET_ERROR( );
if (res == -1) {
-#ifndef WIN32
-/*todo. evbuffer uses WriteFile when WIN32 is set. WIN32 system calls do not
- * *set errno. thus this error checking is not portable*/
if (e == EAGAIN || e == EINTR || e == EINPROGRESS)
goto reschedule;
/* error case */
what |= EVBUFFER_ERROR;
-
-#else
- goto reschedule;
-#endif
-
} else if (res == 0) {
/* eof case */
what |= EVBUFFER_EOF;
if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_DOWN, howmuch )))
{
int e;
- errno = 0;
+
+ EVUTIL_SET_SOCKET_ERROR( 0 );
res = evbuffer_read( io->inbuf, io->socket, howmuch );
- e = errno;
+ e = EVUTIL_SOCKET_ERROR( );
dbgmsg( io, "read %d from peer (%s)", res, (res==-1?strerror(e):"") );
if( ( res <= 0 ) && ( io->gotError ) && ( e != EAGAIN ) && ( e != EINTR ) && ( e != EINPROGRESS ) )
{
+ char errstr[512];
short what = EVBUFFER_READ | EVBUFFER_ERROR;
if( res == 0 )
what |= EVBUFFER_EOF;
- dbgmsg( io, "tr_peerIoTryRead got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, strerror( e ) );
+ tr_net_strerror( errstr, sizeof( errstr ), e );
+ dbgmsg( io, "tr_peerIoTryRead got an error. res is %d, what is %hd, errno is %d (%s)", res, what, e, errstr );
io->gotError( io, what, io->userData );
}
}
if(( howmuch = tr_bandwidthClamp( &io->bandwidth, TR_UP, howmuch )))
{
int e;
- errno = 0;
+ EVUTIL_SET_SOCKET_ERROR( 0 );
n = tr_evbuffer_write( io, io->socket, howmuch );
- e = errno;
+ e = EVUTIL_SOCKET_ERROR( );
if( n > 0 )
didWriteWrapper( io, n );
if( ( n < 0 ) && ( io->gotError ) && ( e != EPIPE ) && ( e != EAGAIN ) && ( e != EINTR ) && ( e != EINPROGRESS ) )
{
+ char errstr[512];
const short what = EVBUFFER_WRITE | EVBUFFER_ERROR;
- dbgmsg( io, "tr_peerIoTryWrite got an error. res is %d, what is %hd, errno is %d (%s)", n, what, e, strerror( e ) );
+
+ tr_net_strerror( errstr, sizeof( errstr ), e );
+ dbgmsg( io, "tr_peerIoTryWrite got an error. res is %d, what is %hd, errno is %d (%s)", n, what, e, errstr );
if( io->gotError != NULL )
io->gotError( io, what, io->userData );
}
static void
-nap( int roughly )
+nap( int roughly_sec )
{
- struct timeval tv;
- tv.tv_sec = roughly / 2 + tr_cryptoWeakRandInt( roughly );
- tv.tv_usec = tr_cryptoWeakRandInt( 1000000 );
- select( 0, NULL, NULL, NULL, &tv );
+ const int roughly_msec = roughly_sec * 1000;
+ const int msec = roughly_msec/2 + tr_cryptoWeakRandInt(roughly_msec);
+ tr_wait_msec( msec );
}
static int
#include <stdio.h>
/* posix */
-#include <netinet/in.h> /* sockaddr_in */
#include <signal.h> /* sig_atomic_t */
#include <sys/time.h>
-#include <sys/types.h>
-#include <sys/socket.h> /* socket(), bind() */
#include <unistd.h> /* close() */
#include <fcntl.h> /* fcntl(), O_NONBLOCK */
#include <ctype.h> /* toupper() */
+#ifdef WIN32
+ #include <w32api.h>
+ #define WINDOWS WindowsXP /* freeaddrinfo(),getaddrinfo(),getnameinfo() */
+ #include <inttypes.h>
+ #include <ws2tcpip.h>
+ typedef uint16_t in_port_t; /* all missing */
+ extern int fcntl (int fd, int cmd, ...);
+ #define O_NONBLOCK 04000
+#else
+ #include <sys/types.h>
+ #include <sys/socket.h> /* socket(), bind() */
+ #include <netinet/in.h> /* sockaddr_in */
+#endif
/* third party */
#include <event.h>
* @brief Configures additional capabilities for a socket */
static inline int lpd_configureSocket( int sock, int add )
{
+#ifdef WIN32
+ unsigned long flags = 1;
+
+ if (add != O_NONBLOCK)
+ return -1; /* not supported */
+ if (ioctlsocket(sock, FIONBIO, &flags) == SOCKET_ERROR)
+ return -1;
+#else
/* read-modify-write socket flags */
int flags = fcntl( sock, F_GETFL );
if( fcntl( sock, F_SETFL, add | flags ) == -1 )
return -1;
+#endif
return add;
}
piperead( int s, char *buf, int len )
{
int ret = recv(s, buf, len, 0);
- int werror = 0;
if (ret < 0) {
- werror= WSAGetLastError();
+ const int werror= WSAGetLastError();
switch(werror) {
/* simplified error mapping (not valid for connect) */
case WSAEWOULDBLOCK:
}
}
+/**
+ * Portability wrapper for select().
+ *
+ * http://msdn.microsoft.com/en-us/library/ms740141%28VS.85%29.aspx
+ * On win32, any two of the parameters, readfds, writefds, or exceptfds,
+ * can be given as null. At least one must be non-null, and any non-null
+ * descriptor set must contain at least one handle to a socket.
+ */
+static void
+tr_select( int nfds,
+ fd_set * r_fd_set, fd_set * w_fd_set, fd_set * c_fd_set,
+ struct timeval * t )
+{
+#ifdef WIN32
+ if( !r_fd_set->fd_count && !w_fd_set->fd_count && !c_fd_set->fd_count )
+ {
+ tr_wait_msec( msec );
+ }
+ else if( select( 0, r_fd_set->fd_count ? r_fd_set : NULL,
+ w_fd_set->fd_count ? w_fd_set : NULL,
+ c_fd_set->fd_count ? c_fd_set : NULL, t ) < 0 )
+ {
+ char errstr[512];
+ const int e = EVUTIL_SOCKET_ERROR( );
+ tr_net_strerror( errstr, sizeof( errstr ), e );
+ dbgmsg( "Error: select (%d) %s", e, errstr );
+ }
+#else
+ select( nfds, r_fd_set, w_fd_set, c_fd_set, t );
+#endif
+}
+
static void
tr_webThreadFunc( void * vsession )
{
t.tv_sec = usec / 1000000;
t.tv_usec = usec % 1000000;
-#ifdef WIN32
- /* see ticket #3311, comments 16-18 */
- if( !r_fd_set.fd_count && !w_fd_set.fd_count && !c_fd_set.fd_count )
- tr_wait_msec( msec );
- else
- select( 0, r_fd_set.fd_count ? &r_fd_set : NULL,
- w_fd_set.fd_count ? &w_fd_set : NULL,
- c_fd_set.fd_count ? &c_fd_set : NULL, &t );
-#else
- select( max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t );
-#endif
+ tr_select( max_fd+1, &r_fd_set, &w_fd_set, &c_fd_set, &t );
}
/* call curl_multi_perform() */
#include <unistd.h>
#include <fcntl.h>
#include <sys/time.h>
+#ifndef WIN32
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
+#else
+#include <w32api.h>
+#define WINVER WindowsXP /* freeaddrinfo(),getaddrinfo(),getnameinfo() */
+#include <ws2tcpip.h>
+#define random rand /* int rand() since no long random() */
+extern const char *inet_ntop(int, const void *, char *, socklen_t); /* from libtransmission (utils.c) */
+#define EAFNOSUPPORT WSAEAFNOSUPPORT
+#endif
#include "dht.h"
dht_init(int s, int s6, const unsigned char *id, const unsigned char *v)
{
int rc;
+#ifdef WIN32
+ unsigned long flags = 1;
+#endif
+
if(dht_socket >= 0 || dht_socket6 >= 0 || buckets || buckets6) {
errno = EBUSY;
return -1;
buckets->af = AF_INET;
+#ifndef WIN32
rc = fcntl(s, F_GETFL, 0);
if(rc < 0)
goto fail;
rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
+#else
+ rc = ioctlsocket(s, FIONBIO, &flags);
+#endif
if(rc < 0)
goto fail;
}
return -1;
buckets6->af = AF_INET6;
+#ifndef WIN32
rc = fcntl(s6, F_GETFL, 0);
if(rc < 0)
goto fail;
rc = fcntl(s6, F_SETFL, (rc | O_NONBLOCK));
+#else
+ rc = ioctlsocket(s6, FIONBIO, &flags);
+#endif
if(rc < 0)
goto fail;
}
#include <winsock2.h>
#include <ws2tcpip.h>
#include <io.h>
-#include <IPHlpApi.h>
+#include <iphlpapi.h>
#define snprintf _snprintf
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
#define strncasecmp _memicmp