From 7904aa9ba74e79c36b5aba83dbee4710d05e58ec Mon Sep 17 00:00:00 2001 From: Jkorf Date: Thu, 9 Jan 2025 16:18:13 +0100 Subject: [PATCH] Fixed websocket connection getting stuck after a ping frame timeout, removed unnecessary type restraints on RestApiClient.SendAsync methods --- CryptoExchange.Net/Clients/RestApiClient.cs | 4 ++-- ...ryptoExchangeWebSocketClientLoggingExtension.cs | 14 +++++++++++++- .../Sockets/CryptoExchangeWebSocketClient.cs | 12 +++++++++++- 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/CryptoExchange.Net/Clients/RestApiClient.cs b/CryptoExchange.Net/Clients/RestApiClient.cs index 6b6b813..2770226 100644 --- a/CryptoExchange.Net/Clients/RestApiClient.cs +++ b/CryptoExchange.Net/Clients/RestApiClient.cs @@ -163,7 +163,7 @@ namespace CryptoExchange.Net.Clients CancellationToken cancellationToken, Dictionary? additionalHeaders = null, int? weight = null, - int? weightSingleLimiter = null) where T : class + int? weightSingleLimiter = null) { var parameterPosition = definition.ParameterPosition ?? ParameterPositions[definition.Method]; return SendAsync( @@ -198,7 +198,7 @@ namespace CryptoExchange.Net.Clients CancellationToken cancellationToken, Dictionary? additionalHeaders = null, int? weight = null, - int? weightSingleLimiter = null) where T : class + int? weightSingleLimiter = null) { string? cacheKey = null; if (ShouldCache(definition)) diff --git a/CryptoExchange.Net/Logging/Extensions/CryptoExchangeWebSocketClientLoggingExtension.cs b/CryptoExchange.Net/Logging/Extensions/CryptoExchangeWebSocketClientLoggingExtension.cs index dfb943f..79b4f23 100644 --- a/CryptoExchange.Net/Logging/Extensions/CryptoExchangeWebSocketClientLoggingExtension.cs +++ b/CryptoExchange.Net/Logging/Extensions/CryptoExchangeWebSocketClientLoggingExtension.cs @@ -35,6 +35,7 @@ namespace CryptoExchange.Net.Logging.Extensions private static readonly Action _startingTaskForNoDataReceivedCheck; private static readonly Action _noDataReceiveTimoutReconnect; private static readonly Action _socketProcessingStateChanged; + private static readonly Action _socketPingTimeout; static CryptoExchangeWebSocketClientLoggingExtension() { @@ -180,9 +181,14 @@ namespace CryptoExchange.Net.Logging.Extensions _socketProcessingStateChanged = LoggerMessage.Define( LogLevel.Trace, - new EventId(1028, "SocketProcessingStateChanged"), + new EventId(1029, "SocketProcessingStateChanged"), "[Sckt {Id}] processing state change: {PreviousState} -> {NewState}"); + _socketPingTimeout = LoggerMessage.Define( + LogLevel.Warning, + new EventId(1030, "SocketPingTimeout"), + "[Sckt {Id}] ping frame timeout; reconnecting socket"); + } public static void SocketConnecting( @@ -358,5 +364,11 @@ namespace CryptoExchange.Net.Logging.Extensions { _socketProcessingStateChanged(logger, socketId, prevState, newState, null); } + + public static void SocketPingTimeout( + this ILogger logger, int socketId) + { + _socketPingTimeout(logger, socketId, null); + } } } diff --git a/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs b/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs index 2d8ef04..f6bc0e7 100644 --- a/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs +++ b/CryptoExchange.Net/Sockets/CryptoExchangeWebSocketClient.cs @@ -587,8 +587,18 @@ namespace CryptoExchange.Net.Sockets lock (_receivedMessagesLock) _receivedMessages.Add(new ReceiveItem(DateTime.UtcNow, receiveResult.Count)); } - catch (OperationCanceledException) + catch (OperationCanceledException ex) { + if (ex.InnerException?.InnerException?.Message.Equals("The WebSocket didn't recieve a Pong frame in response to a Ping frame within the configured KeepAliveTimeout.") == true) + { + // Spefic case that the websocket connection got closed because of a ping frame timeout + // Unfortunately doesn't seem to be a nicer way to catch + _logger.SocketPingTimeout(Id); + } + + if (_closeTask?.IsCompleted != false) + _closeTask = CloseInternalAsync(); + // canceled break; }