X-Git-Url: https://git.piment-noir.org/?a=blobdiff_plain;f=src%2Flib%2Fplatform%2Fwindows%2Fos-socket.h;h=1ce8912475a7645bbfe7cf01aa5e853565f2bdbb;hb=d9de2aae6b2f47b8e1faacc69adba7406b9d85f0;hp=0b11c590420e566f00e8c886a76d79a646715d8f;hpb=1d9111bd750766146b0ab268a497e7707dfb5f5b;p=deb_libcec.git diff --git a/src/lib/platform/windows/os-socket.h b/src/lib/platform/windows/os-socket.h index 0b11c59..1ce8912 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-2013 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,104 +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*/) { - char* org = buf; - int nRes = 1; - - if ((iFlags & MSG_WAITALL) == 0) - return recv(socket, buf, iLength, iFlags); - - iFlags &= ~MSG_WAITALL; - while(iLength > 0 && nRes > 0) + if (len != (DWORD)len) { - nRes = recv(socket, buf, iLength, iFlags); - if (nRes < 0) - return nRes; + *iError = EINVAL; + return -1; + } - buf += nRes; - iLength -= nRes; + DWORD iBytesRead(0); + if (socket != INVALID_HANDLE_VALUE) + { + if(!ReadFile(socket, data, (DWORD)len, &iBytesRead, NULL) != 0) + { + *iError = GetLastError(); + return -1; + } + return (ssize_t)iBytesRead; } - return buf - org; + 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 x = SocketReadFixed(socket, (char *)buf, nLen, MSG_WAITALL); + u_long iSetTo = bSetTo ? 0 : 1; + ioctlsocket(socket, FIONBIO, &iSetTo); + } - if (x == -1) - return GetSocketError(); - if (x != (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 x, tot = 0, nErr; - fd_set fd_read; - struct timeval tv; + if (socket == INVALID_SOCKET || + socket == SOCKET_ERROR || + len != (int)len) + { + *iError = EINVAL; + return -1; + } + + ssize_t iReturn = send(socket, (char*)data, (int)len, 0); + if (iReturn < (ssize_t)len) + *iError = GetSocketError(); + return iReturn; + } - if (iTimeoutMs <= 0) - return EINVAL; + 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(tot != (int)iLength) + if (socket == INVALID_SOCKET || + socket == SOCKET_ERROR || + len != (int)len) { - tv.tv_sec = (long)(iTimeoutMs / 1000); - tv.tv_usec = (long)(1000 * (iTimeoutMs % 1000)); + *iError = EINVAL; + return -1; + } - FD_ZERO(&fd_read); - FD_SET(socket, &fd_read); + if (iTimeoutMs > 0) + { + iNow = GetTimeMs(); + iTarget = iNow + (int64_t) iTimeoutMs; + } - x = select(socket + 1, &fd_read, NULL, NULL, &tv); + 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); - if (x == 0) - return ETIMEDOUT; + FD_ZERO(&fd_read); + #pragma warning(disable:4127) /* disable 'conditional expression is constant' */ + FD_SET(socket, &fd_read); + #pragma warning(default:4127) - SocketSetBlocking(socket, false); + if (select((int)socket + 1, &fd_read, NULL, NULL, &tv) == 0) + { + *iError = ETIMEDOUT; + return ETIMEDOUT; + } + TcpSocketSetBlocking(socket, false); + } - x = SocketReadFixed(socket, (char *)data + tot, iLength - tot, 0); - nErr = GetSocketError(); + ssize_t iReadResult = (iTimeoutMs > 0) ? + recv(socket, (char*)data + iBytesRead, (int)(len - iBytesRead), 0) : + recv(socket, (char*)data, (int)len, MSG_WAITALL); + *iError = GetSocketError(); - SocketSetBlocking(socket, true); + if (iTimeoutMs > 0) + { + TcpSocketSetBlocking(socket, true); + iNow = GetTimeMs(); + } - if (x == -1) + if (iReadResult < 0) { - if (nErr == EAGAIN) + if (*iError == EAGAIN && iTimeoutMs > 0) continue; - return nErr; + return -1; } + else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0)) + { + *iError = ECONNRESET; + return -1; + } + + iBytesRead += iReadResult; + } - if (x == 0) - return ECONNRESET; + if (iBytesRead < (ssize_t)len && *iError == 0) + *iError = ETIMEDOUT; - tot += x; + 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(); + } } - return 0; + + TcpSocketSetBlocking(socket, true); + + return *iError == 0; } }