diff options
author | B Stack <bgstack15@gmail.com> | 2018-10-17 02:11:26 +0000 |
---|---|---|
committer | B Stack <bgstack15@gmail.com> | 2018-10-17 02:11:26 +0000 |
commit | f70f8f961ef8f4d909266f71310e3515f25928e6 (patch) | |
tree | 89b2a018482c164bdd8ecac5c76b19a08f420dec /zen/socket.h | |
parent | Merge branch '10.4' into 'master' (diff) | |
parent | 10.5 (diff) | |
download | FreeFileSync-f70f8f961ef8f4d909266f71310e3515f25928e6.tar.gz FreeFileSync-f70f8f961ef8f4d909266f71310e3515f25928e6.tar.bz2 FreeFileSync-f70f8f961ef8f4d909266f71310e3515f25928e6.zip |
Merge branch '10.5' into 'master'10.5
10.5
See merge request opensource-tracking/FreeFileSync!2
Diffstat (limited to 'zen/socket.h')
-rwxr-xr-x | zen/socket.h | 74 |
1 files changed, 70 insertions, 4 deletions
diff --git a/zen/socket.h b/zen/socket.h index e551a5ba..33ac2e50 100755 --- a/zen/socket.h +++ b/zen/socket.h @@ -20,6 +20,12 @@ namespace zen do { const ErrorCode ecInternal = getLastError(); throw SysError(formatSystemError(functionName, ecInternal)); } while (false) +//patch up socket portability: +using SocketType = int; +const SocketType invalidSocket = -1; +inline void closeSocket(SocketType s) { ::close(s); } + + //Winsock needs to be initialized before calling any of these functions! (WSAStartup/WSACleanup) class Socket //throw SysError @@ -67,18 +73,78 @@ public: ~Socket() { closeSocket(socket_); } - using SocketType = int; SocketType get() const { return socket_; } private: Socket (const Socket&) = delete; Socket& operator=(const Socket&) = delete; - static const SocketType invalidSocket = -1; - static void closeSocket(SocketType s) { ::close(s); } - SocketType socket_ = invalidSocket; }; + + +//more socket helper functions: +namespace +{ +size_t tryReadSocket(SocketType socket, void* buffer, size_t bytesToRead) //throw SysError; may return short, only 0 means EOF! +{ + if (bytesToRead == 0) //"read() with a count of 0 returns zero" => indistinguishable from end of file! => check! + throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__)); + + int bytesReceived = 0; + for (;;) + { + bytesReceived = ::recv(socket, //_In_ SOCKET s, + static_cast<char*>(buffer), //_Out_ char *buf, + static_cast<int>(bytesToRead), //_In_ int len, + 0); //_In_ int flags + if (bytesReceived >= 0 || errno != EINTR) + break; + } + if (bytesReceived < 0) + THROW_LAST_SYS_ERROR_WSA(L"recv"); + + if (static_cast<size_t>(bytesReceived) > bytesToRead) //better safe than sorry + throw SysError(L"HttpInputStream::tryRead: buffer overflow."); + + return bytesReceived; //"zero indicates end of file" +} + + +size_t tryWriteSocket(SocketType socket, const void* buffer, size_t bytesToWrite) //throw SysError; may return short! CONTRACT: bytesToWrite > 0 +{ + if (bytesToWrite == 0) + throw std::logic_error("Contract violation! " + std::string(__FILE__) + ":" + numberTo<std::string>(__LINE__)); + + int bytesWritten = 0; + for (;;) + { + bytesWritten = ::send(socket, //_In_ SOCKET s, + static_cast<const char*>(buffer), //_In_ const char *buf, + static_cast<int>(bytesToWrite), //_In_ int len, + 0); //_In_ int flags + if (bytesWritten >= 0 || errno != EINTR) + break; + } + if (bytesWritten < 0) + THROW_LAST_SYS_ERROR_WSA(L"send"); + if (bytesWritten > static_cast<int>(bytesToWrite)) + throw SysError(L"send: buffer overflow."); + if (bytesWritten == 0) + throw SysError(L"send: zero bytes processed"); + + return bytesWritten; +} +} + + +inline +void shutdownSocketSend(SocketType socket) //throw SysError +{ + if (::shutdown(socket, SHUT_WR) != 0) + THROW_LAST_SYS_ERROR_WSA(L"shutdown"); +} + } #endif //SOCKET_H_23498325972583947678456437 |