diff --git a/NEWS b/NEWS index 6f5e676e5..36ddce6fe 100644 --- a/NEWS +++ b/NEWS @@ -3,6 +3,8 @@ ver 0.23 (not yet released) - new command "getvol" ver 0.22.5 (not yet released) +* output + - httpd: error handling on Windows improved ver 0.22.4 (2021/01/21) * protocol diff --git a/src/event/BufferedSocket.cxx b/src/event/BufferedSocket.cxx index 268f055f0..53877da5f 100644 --- a/src/event/BufferedSocket.cxx +++ b/src/event/BufferedSocket.cxx @@ -36,7 +36,7 @@ BufferedSocket::DirectRead(void *data, size_t length) noexcept } const auto code = GetSocketError(); - if (IsSocketErrorAgain(code)) + if (IsSocketErrorReceiveWouldBlock(code)) return 0; if (IsSocketErrorClosed(code)) diff --git a/src/event/FullyBufferedSocket.cxx b/src/event/FullyBufferedSocket.cxx index 93e2efb07..b8bfdf5f9 100644 --- a/src/event/FullyBufferedSocket.cxx +++ b/src/event/FullyBufferedSocket.cxx @@ -31,7 +31,7 @@ FullyBufferedSocket::DirectWrite(const void *data, size_t length) noexcept const auto nbytes = GetSocket().Write((const char *)data, length); if (gcc_unlikely(nbytes < 0)) { const auto code = GetSocketError(); - if (IsSocketErrorAgain(code)) + if (IsSocketErrorSendWouldBlock(code)) return 0; idle_event.Cancel(); diff --git a/src/net/SocketError.hxx b/src/net/SocketError.hxx index 8e8db1ddf..44989c52f 100644 --- a/src/net/SocketError.hxx +++ b/src/net/SocketError.hxx @@ -52,14 +52,79 @@ GetSocketError() noexcept #endif } -gcc_const -static inline bool -IsSocketErrorAgain(socket_error_t code) noexcept +constexpr bool +IsSocketErrorInProgress(socket_error_t code) noexcept { #ifdef _WIN32 return code == WSAEINPROGRESS; #else - return code == EAGAIN; + return code == EINPROGRESS; +#endif +} + +constexpr bool +IsSocketErrorWouldBlock(socket_error_t code) noexcept +{ +#ifdef _WIN32 + return code == WSAEWOULDBLOCK; +#else + return code == EWOULDBLOCK; +#endif +} + +constexpr bool +IsSocketErrorConnectWouldBlock(socket_error_t code) noexcept +{ +#if defined(_WIN32) || defined(__linux__) + /* on Windows, WSAEINPROGRESS is for blocking sockets and + WSAEWOULDBLOCK for non-blocking sockets */ + /* on Linux, EAGAIN==EWOULDBLOCK is for local sockets and + EINPROGRESS is for all other sockets */ + return IsSocketErrorInProgress(code) || IsSocketErrorWouldBlock(code); +#else + /* on all other operating systems, there's just EINPROGRESS */ + return IsSocketErrorInProgress(code); +#endif +} + +constexpr bool +IsSocketErrorSendWouldBlock(socket_error_t code) noexcept +{ +#ifdef _WIN32 + /* on Windows, WSAEINPROGRESS is for blocking sockets and + WSAEWOULDBLOCK for non-blocking sockets */ + return IsSocketErrorInProgress(code) || IsSocketErrorWouldBlock(code); +#else + /* on all other operating systems, there's just EAGAIN==EWOULDBLOCK */ + return IsSocketErrorWouldBlock(code); +#endif +} + +constexpr bool +IsSocketErrorReceiveWouldBlock(socket_error_t code) noexcept +{ +#ifdef _WIN32 + /* on Windows, WSAEINPROGRESS is for blocking sockets and + WSAEWOULDBLOCK for non-blocking sockets */ + return IsSocketErrorInProgress(code) || IsSocketErrorWouldBlock(code); +#else + /* on all other operating systems, there's just + EAGAIN==EWOULDBLOCK */ + return IsSocketErrorWouldBlock(code); +#endif +} + +constexpr bool +IsSocketErrorAcceptWouldBlock(socket_error_t code) noexcept +{ +#ifdef _WIN32 + /* on Windows, WSAEINPROGRESS is for blocking sockets and + WSAEWOULDBLOCK for non-blocking sockets */ + return IsSocketErrorInProgress(code) || IsSocketErrorWouldBlock(code); +#else + /* on all other operating systems, there's just + EAGAIN==EWOULDBLOCK */ + return IsSocketErrorWouldBlock(code); #endif } diff --git a/src/output/plugins/httpd/HttpdClient.cxx b/src/output/plugins/httpd/HttpdClient.cxx index 6345f8f9f..e16389db0 100644 --- a/src/output/plugins/httpd/HttpdClient.cxx +++ b/src/output/plugins/httpd/HttpdClient.cxx @@ -278,7 +278,7 @@ HttpdClient::TryWrite() noexcept metadata_current_position); if (nbytes < 0) { auto e = GetSocketError(); - if (IsSocketErrorAgain(e)) + if (IsSocketErrorSendWouldBlock(e)) return true; if (!IsSocketErrorClosed(e)) { @@ -305,7 +305,7 @@ HttpdClient::TryWrite() noexcept ssize_t nbytes = GetSocket().Write(&empty_data, 1); if (nbytes < 0) { auto e = GetSocketError(); - if (IsSocketErrorAgain(e)) + if (IsSocketErrorSendWouldBlock(e)) return true; if (!IsSocketErrorClosed(e)) { @@ -328,7 +328,7 @@ HttpdClient::TryWrite() noexcept bytes_to_write); if (nbytes < 0) { auto e = GetSocketError(); - if (IsSocketErrorAgain(e)) + if (IsSocketErrorSendWouldBlock(e)) return true; if (!IsSocketErrorClosed(e)) {