--- linux/net_posix.c 2011-04-30 00:03:11.082316000 +0200 +++ windows/net_winsock.c 2011-04-30 00:08:43.142316001 +0200 @@ -1,6 +1,7 @@ /* - * Networking under POSIX + * Networking under WINDOWS * Copyright (C) 2007-2008 Andreas Ă–man + * Copyright (C) 2007-2008 Joakim Plate * Copyright (C) 2011 Team XBMC * * This program is free software; you can redistribute it and/or @@ -18,28 +19,56 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifdef __APPLE__ -/* Needed on Mac OS/X */ -#ifndef SOL_TCP -#define SOL_TCP IPPROTO_TCP -#endif -#include "OSXGNUReplacements.h" -#elif defined(__FreeBSD__) -#ifndef SOL_TCP -#define SOL_TCP IPPROTO_TCP -#endif -#else -#include -#endif #include -#include #include #include #include -#include #include "../os-dependent_socket.h" +#ifndef EINPROGRESS +#define EINPROGRESS WSAEINPROGRESS +#endif + +#ifndef ECONNRESET +#define ECONNRESET WSAECONNRESET +#endif + +#ifndef EAGAIN +#define EAGAIN WSAEWOULDBLOCK +#endif + +#ifndef EINVAL +#define EINVAL WSAEINVAL +#endif + +#ifndef MSG_WAITALL +#define MSG_WAITALL 0x8 +#endif + +static int recv_fixed (SOCKET fdSock, char * szBuf, int nLen, int nFlags) +{ + char* org = szBuf; + int nRes = 1; + + if ((nFlags & MSG_WAITALL) == 0) + return recv(fdSock, szBuf, nLen, nFlags); + + nFlags &= ~MSG_WAITALL; + while(nLen > 0 && nRes > 0) + { + nRes = recv(fdSock, szBuf, nLen, nFlags); + if (nRes < 0) + return nRes; + + szBuf += nRes; + nLen -= nRes; + } + return szBuf - org; +} + +#define recv(fdSock, szBuf, nLen, nFlags) recv_fixed(fdSock, szBuf, nLen, nFlags) + int tcp_connect_poll(struct addrinfo* addr, socket_t fdSock, char *szErrbuf, size_t nErrbufSize, int nTimeout) @@ -48,7 +77,8 @@ socklen_t errlen = sizeof(int); /* switch to non blocking */ - fcntl(fdSock, F_SETFL, fcntl(fdSock, F_GETFL) | O_NONBLOCK); + int nVal = 1; + ioctlsocket(fdSock, FIONBIO, &nVal); /* connect to the other side */ nRes = connect(fdSock, addr->ai_addr, addr->ai_addrlen); @@ -56,22 +86,29 @@ /* poll until a connection is established */ if (nRes == -1) { - if (errno == EINPROGRESS) + if (WSAGetLastError() == EINPROGRESS || + WSAGetLastError() == EAGAIN) { - struct pollfd pfd; - pfd.fd = fdSock; - pfd.events = POLLOUT; - pfd.revents = 0; + fd_set fd_write, fd_except; + struct timeval tv; + tv.tv_sec = nTimeout / 1000; + tv.tv_usec = 1000 * (nTimeout % 1000); + + FD_ZERO(&fd_write); + FD_ZERO(&fd_except); + FD_SET(fdSock, &fd_write); + FD_SET(fdSock, &fd_except); - nRes = poll(&pfd, 1, nTimeout); + nRes = select((int)fdSock+1, NULL, &fd_write, &fd_except, &tv); if (nRes == 0) { - snprintf(szErrbuf, nErrbufSize, "attempt timed out after %d milliseconds", nTimeout); + _snprintf(szErrbuf, nErrbufSize, "attempt timed out after %d milliseconds", nTimeout); return SOCKET_ERROR; } + else if (nRes == -1) { - snprintf(szErrbuf, nErrbufSize, "poll() error '%s'", strerror(errno)); + _snprintf(szErrbuf, nErrbufSize, "select() error: %s", strerror(WSAGetLastError())); return SOCKET_ERROR; } @@ -80,18 +117,18 @@ } else { - nErr = errno; + nErr = WSAGetLastError(); } } if (nErr != 0) { - snprintf(szErrbuf, nErrbufSize, "%s", strerror(nErr)); + _snprintf(szErrbuf, nErrbufSize, "%s", strerror(nErr)); return SOCKET_ERROR; } - /* switch back to blocking */ - fcntl(fdSock, F_SETFL, fcntl(fdSock, F_GETFL) & ~O_NONBLOCK); + nVal = 0; + ioctlsocket(fdSock, FIONBIO, &nVal); return 0; } @@ -107,20 +144,20 @@ fdSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); if (fdSock == -1) { - snprintf(szErrbuf, nErrbufSize, "Unable to create socket: %s", strerror(errno)); + _snprintf(szErrbuf, nErrbufSize, "Unable to create socket: %s", strerror(WSAGetLastError())); return SOCKET_ERROR; } /* connect to the socket */ if (tcp_connect_poll(addr, fdSock, szErrbuf, nErrbufSize, nTimeout) != 0) { - close(fdSock); + closesocket(fdSock); return SOCKET_ERROR; } /* set TCP_NODELAY socket option */ nVal = 1; - setsockopt(fdSock, SOL_TCP, TCP_NODELAY, &nVal, sizeof(nVal)); + setsockopt(fdSock, IPPROTO_TCP, TCP_NODELAY, (const char*)&nVal, sizeof(nVal)); return fdSock; } @@ -147,23 +184,23 @@ switch(nRes) { case EAI_NONAME: - snprintf(szErrbuf, nErrbufSize, "the specified host is unknown"); + _snprintf(szErrbuf, nErrbufSize, "the specified host is unknown"); break; case EAI_FAIL: - snprintf(szErrbuf, nErrbufSize, "a nonrecoverable failure in name resolution occurred"); + _snprintf(szErrbuf, nErrbufSize, "a nonrecoverable failure in name resolution occurred"); break; case EAI_MEMORY: - snprintf(szErrbuf, nErrbufSize, "a memory allocation failure occurred"); + _snprintf(szErrbuf, nErrbufSize, "a memory allocation failure occurred"); break; case EAI_AGAIN: - snprintf(szErrbuf, nErrbufSize, "a temporary error occurred on an authoritative name server"); + _snprintf(szErrbuf, nErrbufSize, "a temporary error occurred on an authoritative name server"); break; default: - snprintf(szErrbuf, nErrbufSize, "unknown error %d", nRes); + _snprintf(szErrbuf, nErrbufSize, "unknown error %d", nRes); break; } @@ -187,7 +224,7 @@ int x = recv(fdSock, buf, nLen, MSG_WAITALL); if (x == -1) - return errno; + return WSAGetLastError(); if (x != (int)nLen) return ECONNRESET; @@ -198,27 +235,40 @@ tcp_read_timeout(socket_t fdSock, void *buf, size_t nLen, int nTimeout) { int x, tot = 0; - struct pollfd fds; + int nVal, nErr; + fd_set fd_read; + struct timeval tv; if (nTimeout <= 0) return EINVAL; - fds.fd = fdSock; - fds.events = POLLIN; - fds.revents = 0; - while(tot != (int)nLen) { - x = poll(&fds, 1, nTimeout); + tv.tv_sec = nTimeout / 1000; + tv.tv_usec = 1000 * (nTimeout % 1000); + + FD_ZERO(&fd_read); + FD_SET(fdSock, &fd_read); + + x = select((int)fdSock+1, &fd_read, NULL, NULL, &tv); + if (x == 0) return ETIMEDOUT; - x = recv(fdSock, buf + tot, nLen - tot, MSG_DONTWAIT); + nVal = 1; + ioctlsocket(fdSock, FIONBIO, &nVal); + + x = recv(fdSock, (char *)buf + tot, nLen - tot, 0); + nErr = WSAGetLastError(); + + nVal = 0; + ioctlsocket(fdSock, FIONBIO, &nVal); + if (x == -1) { - if (errno == EAGAIN) + if (nErr == EAGAIN) continue; - return errno; + return nErr; } if (x == 0) @@ -233,5 +283,5 @@ tcp_close(socket_t fdSock) { if (fdSock != SOCKET_ERROR) - close(fdSock); + closesocket(fdSock); }