X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fplatform%2Fwindows%2Fos-socket.h;h=0c3855558ddeb7b164d151cb3e1e50ca0fa1cdee;hb=2b44051cbfa70deafc30d9767323214debbc1a75;hp=9b0656fb5bdb90c2b421f90f2f9c5aa477a67138;hpb=71194cf4f11d94bc92594c263d2a4eeafcea72b3;p=deb_libcec.git diff --git a/src/lib/platform/windows/os-socket.h b/src/lib/platform/windows/os-socket.h index 9b0656f..0c38555 100644 --- a/src/lib/platform/windows/os-socket.h +++ b/src/lib/platform/windows/os-socket.h @@ -2,7 +2,7 @@ /* * This file is part of the libCEC(R) library. * - * libCEC(R) is Copyright (C) 2011 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. * libCEC(R) is an original work, containing original code. * * libCEC(R) is a trademark of Pulse-Eight Limited. @@ -31,10 +31,9 @@ * http://www.pulse-eight.net/ */ -#include "../os.h" -#include "../util/timeutils.h" +#include "lib/platform/os.h" +#include "lib/platform/util/timeutils.h" -#pragma comment(lib, "Ws2_32.lib") #include #include #include @@ -64,101 +63,239 @@ namespace PLATFORM } } - inline void SocketClose(socket_t socket) + // Serial port + //@{ + inline void SerialSocketClose(serial_socket_t socket) { - if (socket != SOCKET_ERROR && socket != INVALID_SOCKET) - closesocket(socket); + if (socket != INVALID_HANDLE_VALUE) + CloseHandle(socket); } - inline void SocketSetBlocking(socket_t socket, bool bSetTo) + inline ssize_t SerialSocketWrite(serial_socket_t socket, int *iError, void* data, size_t len) { - u_long nVal = bSetTo ? 1 : 0; - ioctlsocket(socket, FIONBIO, &nVal); - } + if (len != (DWORD)len) + { + *iError = EINVAL; + return -1; + } - inline int64_t SocketWrite(socket_t socket, int *iError, uint8_t* data, uint32_t len) - { - int64_t iReturn(-1); - if (socket != SOCKET_ERROR && socket != INVALID_SOCKET) + DWORD iBytesWritten(0); + if (socket != INVALID_HANDLE_VALUE) { - iReturn = send(socket, (char*)data, len, 0); - if (iReturn <= 0) - *iError = GetSocketError(); + if (!WriteFile(socket, data, (DWORD)len, &iBytesWritten, NULL)) + { + *iError = GetLastError(); + return -1; + } + return (ssize_t)iBytesWritten; } - return iReturn; + + return -1; } - inline int SocketReadFixed(socket_t socket, char *buf, int iLength, int iFlags) + inline ssize_t SerialSocketRead(serial_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) { - int iReadResult(1), iBytesRead(0); - - if ((iFlags & MSG_WAITALL) == 0) - return recv(socket, buf, iLength, iFlags); + if (len != (DWORD)len) + { + *iError = EINVAL; + return -1; + } - iFlags &= ~MSG_WAITALL; - while(iBytesRead < iLength && iReadResult > 0) + DWORD iBytesRead(0); + if (socket != INVALID_HANDLE_VALUE) { - if ((iReadResult = recv(socket, buf + iBytesRead, iLength - iBytesRead, iFlags)) < 0) - return iReadResult; + if(!ReadFile(socket, data, (DWORD)len, &iBytesRead, NULL) != 0) + { + *iError = GetLastError(); + return -1; + } + return (ssize_t)iBytesRead; } - return iLength - iBytesRead; + return -1; } + //@} - inline int32_t SocketRead(socket_t socket, void *buf, uint32_t nLen) + // TCP + //@{ + inline void TcpSocketSetBlocking(tcp_socket_t socket, bool bSetTo) { - int iReadResult = SocketReadFixed(socket, (char *)buf, nLen, MSG_WAITALL); + u_long iSetTo = bSetTo ? 0 : 1; + ioctlsocket(socket, FIONBIO, &iSetTo); + } - if (iReadResult == -1) - return GetSocketError(); - if (iReadResult < (int)nLen) - return ECONNRESET; + inline void TcpSocketClose(tcp_socket_t socket) + { + closesocket(socket); + } - return 0; + inline void TcpSocketShutdown(tcp_socket_t socket) + { + if (socket != INVALID_SOCKET && + socket != SOCKET_ERROR) + shutdown(socket, SHUT_RDWR); } - inline int32_t SocketRead(socket_t socket, int *iError, uint8_t* data, uint32_t iLength, uint64_t iTimeoutMs) + inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len) { - int iReadResult(0); - uint32_t iBytesRead(0); - fd_set fd_read; - struct timeval tv; + if (socket == INVALID_SOCKET || + socket == SOCKET_ERROR || + len != (int)len) + { + *iError = EINVAL; + return -1; + } - if (iTimeoutMs <= 0) - return EINVAL; + ssize_t iReturn = send(socket, (char*)data, (int)len, 0); + if (iReturn < (ssize_t)len) + *iError = GetSocketError(); + return iReturn; + } - uint64_t iNow = GetTimeMs(); - uint64_t iTarget = iNow + iTimeoutMs; + inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) + { + int64_t iNow(0), iTarget(0); + ssize_t iBytesRead(0); + *iError = 0; - while(iNow < iTarget && iBytesRead < iLength) + if (socket == INVALID_SOCKET || + socket == SOCKET_ERROR || + len != (int)len) { - tv.tv_sec = (long)(iTarget - iNow / 1000); - tv.tv_usec = (long)(1000 * (iTarget - iNow % 1000)); + *iError = EINVAL; + return -1; + } - FD_ZERO(&fd_read); - FD_SET(socket, &fd_read); + if (iTimeoutMs > 0) + { + iNow = GetTimeMs(); + iTarget = iNow + (int64_t) iTimeoutMs; + } - if ((iReadResult = select(socket + 1, &fd_read, NULL, NULL, &tv)) == 0) - return ETIMEDOUT; + fd_set fd_read; + struct timeval tv; + while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow)) + { + if (iTimeoutMs > 0) + { + tv.tv_sec = (long)(iTimeoutMs / 1000); + tv.tv_usec = 1000 * (long)(iTimeoutMs % 1000); - SocketSetBlocking(socket, false); + FD_ZERO(&fd_read); + #pragma warning(disable:4127) /* disable 'conditional expression is constant' */ + FD_SET(socket, &fd_read); + #pragma warning(default:4127) - iReadResult = SocketReadFixed(socket, (char *)data + iBytesRead, iLength - iBytesRead, 0); + if (select((int)socket + 1, &fd_read, NULL, NULL, &tv) == 0) + { + *iError = ETIMEDOUT; + return ETIMEDOUT; + } + TcpSocketSetBlocking(socket, false); + } - SocketSetBlocking(socket, true); + ssize_t iReadResult = (iTimeoutMs > 0) ? + recv(socket, (char*)data + iBytesRead, (int)(len - iBytesRead), 0) : + recv(socket, (char*)data, (int)len, MSG_WAITALL); + *iError = GetSocketError(); - if (iReadResult == -1) + if (iTimeoutMs > 0) { - int iError = GetSocketError(); - if (iError == EAGAIN) + TcpSocketSetBlocking(socket, true); + iNow = GetTimeMs(); + } + + if (iReadResult < 0) + { + if (*iError == EAGAIN && iTimeoutMs > 0) continue; - return iError; + return -1; + } + else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0)) + { + *iError = ECONNRESET; + return -1; } - else if (iReadResult == 0) - return ECONNRESET; iBytesRead += iReadResult; } - return iBytesRead == iLength ? 0 : ECONNRESET; + if (iBytesRead < (ssize_t)len && *iError == 0) + *iError = ETIMEDOUT; + + return iBytesRead; + } + + inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info) + { + struct addrinfo hints; + char service[33]; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + sprintf(service, "%d", iPort); + + *iError = getaddrinfo(strHost, service, &hints, info); + return !(*iError); + } + + inline int TcpGetSocketError(tcp_socket_t socket) + { + int iReturn(0); + socklen_t optLen = sizeof(tcp_socket_t); + getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)&iReturn, &optLen); + return iReturn; + } + + inline bool TcpSetNoDelay(tcp_socket_t socket) + { + int iSetTo(1); + setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&iSetTo, sizeof(iSetTo)); + return true; + } + + inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0) + { + TcpSocketSetBlocking(socket, false); + + *iError = 0; + int iConnectResult = connect(socket, addr->ai_addr, (int)addr->ai_addrlen); + if (iConnectResult == -1) + { + if (GetSocketError() == EINPROGRESS || + GetSocketError() == EAGAIN) + { + fd_set fd_write, fd_except; + struct timeval tv; + tv.tv_sec = (long)(iTimeout / 1000); + tv.tv_usec = 1000 * (long)(iTimeout % 1000); + + FD_ZERO(&fd_write); + FD_ZERO(&fd_except); + #pragma warning(disable:4127) /* disable 'conditional expression is constant' */ + FD_SET(socket, &fd_write); + FD_SET(socket, &fd_except); + #pragma warning(default:4127) + + int iPollResult = select(sizeof(socket)*8, NULL, &fd_write, &fd_except, &tv); + if (iPollResult == 0) + *iError = ETIMEDOUT; + else if (iPollResult == -1) + *iError = GetSocketError(); + else + { + socklen_t errlen = sizeof(int); + getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)iError, &errlen); + } + } + else + { + *iError = GetSocketError(); + } + } + + TcpSocketSetBlocking(socket, true); + + return *iError == 0; } }