From 3b635c35004c228d542c529be2d9ce261558ce4d Mon Sep 17 00:00:00 2001 From: iProgramInCpp Date: Wed, 29 May 2024 10:57:04 +0300 Subject: [PATCH] * Improve websocket connection failure condition handling. --- src/discord/Frontend.hpp | 2 +- src/discord/WebsocketClient.cpp | 23 ++++++++++++++++++++--- src/windows/Frontend_Win32.cpp | 24 ++++++++++++++++++++---- src/windows/Frontend_Win32.hpp | 2 +- src/windows/Main.cpp | 1 + src/windows/WindowMessages.hpp | 1 + 6 files changed, 44 insertions(+), 9 deletions(-) diff --git a/src/discord/Frontend.hpp b/src/discord/Frontend.hpp index a7a0751..73069f9 100644 --- a/src/discord/Frontend.hpp +++ b/src/discord/Frontend.hpp @@ -66,7 +66,7 @@ class Frontend // Called by WebSocketClient, dispatches to relevant places including DiscordInstance virtual void OnWebsocketMessage(int gatewayID, const std::string& payload) = 0; virtual void OnWebsocketClose(int gatewayID, int errorCode, const std::string& message) = 0; - virtual void OnWebsocketFail(int gatewayID, int errorCode, const std::string& message, bool isTLSError) = 0; + virtual void OnWebsocketFail(int gatewayID, int errorCode, const std::string& message, bool isTLSError, bool mayRetry) = 0; // Heartbeat interval virtual void SetHeartbeatInterval(int timeMs) = 0; diff --git a/src/discord/WebsocketClient.cpp b/src/discord/WebsocketClient.cpp index d9bba4d..da01871 100644 --- a/src/discord/WebsocketClient.cpp +++ b/src/discord/WebsocketClient.cpp @@ -44,18 +44,35 @@ void WSConnectionMetadata::OnFail(WSClient* c, websocketpp::connection_hdl hdl) guiMessage += " (transport error " + xportEc.message() + ")"; namespace SocketErrors = websocketpp::transport::asio::socket::error; + using WebsocketErrors = websocketpp::error::value; + bool isTLSError = false; switch (pConn->get_ec().value()) { case SocketErrors::missing_tls_init_handler: case SocketErrors::tls_failed_sni_hostname: - case SocketErrors::tls_handshake_timeout: - case SocketErrors::tls_handshake_failed: case SocketErrors::invalid_tls_context: case SocketErrors::security: + //case SocketErrors::tls_handshake_timeout: + //case SocketErrors::tls_handshake_failed: isTLSError = true; } - GetFrontend()->OnWebsocketFail(m_id, pConn->get_ec().value(), guiMessage, isTLSError); + bool mayRetry = false; + switch (pConn->get_ec().value()) { + case WSAHOST_NOT_FOUND: + case WSATRY_AGAIN: + case WSAEDISCON: + case WSAETIMEDOUT: + case SocketErrors::tls_handshake_timeout: + case SocketErrors::tls_handshake_failed: + case WebsocketErrors::bad_connection: + case WebsocketErrors::open_handshake_timeout: + case WebsocketErrors::close_handshake_timeout: + case WebsocketErrors::extension_neg_failed: + mayRetry = true; + } + + GetFrontend()->OnWebsocketFail(m_id, pConn->get_ec().value(), guiMessage, isTLSError, mayRetry); } void WSConnectionMetadata::OnClose(WSClient* c, websocketpp::connection_hdl hdl) diff --git a/src/windows/Frontend_Win32.cpp b/src/windows/Frontend_Win32.cpp index 8107e52..547fce1 100644 --- a/src/windows/Frontend_Win32.cpp +++ b/src/windows/Frontend_Win32.cpp @@ -326,7 +326,7 @@ void Frontend_Win32::OnWebsocketClose(int gatewayID, int errorCode, const std::s #include -void Frontend_Win32::OnWebsocketFail(int gatewayID, int errorCode, const std::string& message, bool isTLSError) +void Frontend_Win32::OnWebsocketFail(int gatewayID, int errorCode, const std::string& message, bool isTLSError, bool mayRetry) { static TCHAR buffer[8192]; LPTSTR msg = ConvertCppStringToTString(message); @@ -337,6 +337,7 @@ void Frontend_Win32::OnWebsocketFail(int gatewayID, int errorCode, const std::st errorCode, msg ); + free(msg); if (isTLSError) { _tcscat( @@ -357,10 +358,25 @@ void Frontend_Win32::OnWebsocketFail(int gatewayID, int errorCode, const std::st ); } - free(msg); + if (mayRetry) { + _tcscat(buffer, TEXT("\n\nClick Retry to try connecting again, or Cancel to quit.")); + } + + int flags = (mayRetry ? MB_RETRYCANCEL : MB_OK) | (isTLSError ? MB_ICONWARNING : MB_ICONERROR); + int result = MessageBox(g_Hwnd, buffer, TmGetTString(IDS_PROGRAM_NAME), flags); - MessageBox(g_Hwnd, buffer, TmGetTString(IDS_PROGRAM_NAME), (isTLSError ? MB_ICONWARNING : MB_ICONERROR) | MB_OK); - SendMessage(g_Hwnd, WM_CONNECTERROR, 0, 0); + if (mayRetry) { + if (result == IDRETRY) { + SendMessage(g_Hwnd, WM_CONNECTERROR, 0, 0); + } + else { + SendMessage(g_Hwnd, WM_DESTROY, 0, 0); + RequestQuit(); + } + } + else { + SendMessage(g_Hwnd, WM_CONNECTERROR2, 0, 0); + } } void Frontend_Win32::RequestQuit() diff --git a/src/windows/Frontend_Win32.hpp b/src/windows/Frontend_Win32.hpp index d711f77..f0ca58e 100644 --- a/src/windows/Frontend_Win32.hpp +++ b/src/windows/Frontend_Win32.hpp @@ -47,7 +47,7 @@ class Frontend_Win32 : public Frontend void JumpToMessage(Snowflake messageInCurrentChannel) override; void OnWebsocketMessage(int gatewayID, const std::string& payload) override; void OnWebsocketClose(int gatewayID, int errorCode, const std::string& message) override; - void OnWebsocketFail(int gatewayID, int errorCode, const std::string& message, bool isTLSError) override; + void OnWebsocketFail(int gatewayID, int errorCode, const std::string& message, bool isTLSError, bool mayRetry) override; void SetHeartbeatInterval(int timeMs) override; void LaunchURL(const std::string& url) override; void RegisterIcon(Snowflake sf, const std::string& avatarlnk) override; diff --git a/src/windows/Main.cpp b/src/windows/Main.cpp index ba8b26f..7c29409 100644 --- a/src/windows/Main.cpp +++ b/src/windows/Main.cpp @@ -1033,6 +1033,7 @@ LRESULT CALLBACK WindowProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) if (g_tryAgainTimerElapse > 10000) g_tryAgainTimerElapse = 10000; break; + case WM_CONNECTERROR2: case WM_CONNECTED: ResetTryAgainInTime(); if (g_tryAgainTimer) { diff --git a/src/windows/WindowMessages.hpp b/src/windows/WindowMessages.hpp index 024a979..3c25c68 100644 --- a/src/windows/WindowMessages.hpp +++ b/src/windows/WindowMessages.hpp @@ -57,4 +57,5 @@ enum eWmUserMsgs WM_UPDATEUSER, // Snowflake[1] WM_UPDATEEMOJI, // Snowflake[1] WM_TOGGLECHANNELS, + WM_CONNECTERROR2, };