diff --git a/src/util/sock.cpp b/src/util/sock.cpp index 36493ec241..e13c52a16a 100644 --- a/src/util/sock.cpp +++ b/src/util/sock.cpp @@ -250,6 +250,31 @@ std::string Sock::RecvUntilTerminator(uint8_t terminator, } } +bool Sock::IsConnected(std::string& errmsg) const +{ + if (m_socket == INVALID_SOCKET) { + errmsg = "not connected"; + return false; + } + + char c; + switch (Recv(&c, sizeof(c), MSG_PEEK)) { + case -1: { + const int err = WSAGetLastError(); + if (IOErrorIsPermanent(err)) { + errmsg = NetworkErrorString(err); + return false; + } + return true; + } + case 0: + errmsg = "closed"; + return false; + default: + return true; + } +} + #ifdef WIN32 std::string NetworkErrorString(int err) { diff --git a/src/util/sock.h b/src/util/sock.h index 209d30def4..ecebb84205 100644 --- a/src/util/sock.h +++ b/src/util/sock.h @@ -143,6 +143,13 @@ public: std::chrono::milliseconds timeout, CThreadInterrupt& interrupt) const; + /** + * Check if still connected. + * @param[out] err The error string, if the socket has been disconnected. + * @return true if connected + */ + virtual bool IsConnected(std::string& errmsg) const; + private: /** * Contained socket. `INVALID_SOCKET` designates the object is empty.