diff --git a/CryptoExchange.Net/Clients/RestApiClient.cs b/CryptoExchange.Net/Clients/RestApiClient.cs index 42ef7d8..ee584a3 100644 --- a/CryptoExchange.Net/Clients/RestApiClient.cs +++ b/CryptoExchange.Net/Clients/RestApiClient.cs @@ -114,12 +114,6 @@ namespace CryptoExchange.Net.Clients RequestFactory.Configure(options, httpClient); } - /// - /// Create a message accessor instance - /// - /// - protected abstract IStreamMessageAccessor CreateAccessor(); - /// /// Create a serializer instance /// diff --git a/CryptoExchange.Net/Clients/SocketApiClient.cs b/CryptoExchange.Net/Clients/SocketApiClient.cs index f3f95c9..1c4dbc2 100644 --- a/CryptoExchange.Net/Clients/SocketApiClient.cs +++ b/CryptoExchange.Net/Clients/SocketApiClient.cs @@ -99,11 +99,6 @@ namespace CryptoExchange.Net.Clients /// protected bool AllowTopicsOnTheSameConnection { get; set; } = true; - /// - /// Whether to continue processing and forward unparsable messages to handlers - /// - protected internal bool ProcessUnparsableMessages { get; set; } = false; - /// public double IncomingKbps { @@ -165,12 +160,6 @@ namespace CryptoExchange.Net.Clients { } - /// - /// Create a message accessor instance - /// - /// - protected internal abstract IByteMessageAccessor CreateAccessor(WebSocketMessageType messageType); - /// /// Create a serializer instance /// @@ -754,7 +743,6 @@ namespace CryptoExchange.Net.Clients // Create new socket connection var socketConnection = new SocketConnection(_logger, SocketFactory, GetWebSocketParameters(connectionAddress.Data!), this, address); - socketConnection.UnhandledMessage += HandleUnhandledMessage; socketConnection.ConnectRateLimitedAsync += HandleConnectRateLimitedAsync; if (dedicatedRequestConnection) { @@ -805,14 +793,6 @@ namespace CryptoExchange.Net.Clients return new CallResult>(socketConnection); } - /// - /// Process an unhandled message - /// - /// The message that wasn't processed - protected virtual void HandleUnhandledMessage(IMessageAccessor message) - { - } - /// /// Process an unhandled message /// @@ -873,7 +853,6 @@ namespace CryptoExchange.Net.Clients Proxy = ClientOptions.Proxy, Timeout = ApiOptions.SocketNoDataTimeout ?? ClientOptions.SocketNoDataTimeout, ReceiveBufferSize = ClientOptions.ReceiveBufferSize, - UseUpdatedDeserialization = ClientOptions.UseUpdatedDeserialization }; /// @@ -1066,7 +1045,6 @@ namespace CryptoExchange.Net.Clients sb.AppendLine($"\t\t\tId: {subState.Id}"); sb.AppendLine($"\t\t\tStatus: {subState.Status}"); sb.AppendLine($"\t\t\tInvocations: {subState.Invocations}"); - sb.AppendLine($"\t\t\tIdentifiers: [{subState.ListenMatcher.ToString()}]"); }); } }); @@ -1097,21 +1075,10 @@ namespace CryptoExchange.Net.Clients base.Dispose(); } - /// - /// Get the listener identifier for the message - /// - /// - /// - public abstract string? GetListenerIdentifier(IMessageAccessor messageAccessor); - /// /// Preprocess a stream message /// public virtual ReadOnlySpan PreprocessStreamMessage(SocketConnection connection, WebSocketMessageType type, ReadOnlySpan data) => data; - /// - /// Preprocess a stream message - /// - public virtual ReadOnlyMemory PreprocessStreamMessage(SocketConnection connection, WebSocketMessageType type, ReadOnlyMemory data) => data; /// /// Create a new message converter instance diff --git a/CryptoExchange.Net/Converters/MessageParsing/MessageNode.cs b/CryptoExchange.Net/Converters/MessageParsing/MessageNode.cs deleted file mode 100644 index b20eb1b..0000000 --- a/CryptoExchange.Net/Converters/MessageParsing/MessageNode.cs +++ /dev/null @@ -1,49 +0,0 @@ -namespace CryptoExchange.Net.Converters.MessageParsing -{ - /// - /// Node accessor - /// - public readonly struct NodeAccessor - { - /// - /// Index - /// - public int? Index { get; } - /// - /// Property name - /// - public string? Property { get; } - - /// - /// Type (0 = int, 1 = string, 2 = prop name) - /// - public int Type { get; } - - private NodeAccessor(int? index, string? property, int type) - { - Index = index; - Property = property; - Type = type; - } - - /// - /// Create an int node accessor - /// - /// - /// - public static NodeAccessor Int(int value) { return new NodeAccessor(value, null, 0); } - - /// - /// Create a string node accessor - /// - /// - /// - public static NodeAccessor String(string value) { return new NodeAccessor(null, value, 1); } - - /// - /// Create a property name node accessor - /// - /// - public static NodeAccessor PropertyName() { return new NodeAccessor(null, null, 2); } - } -} diff --git a/CryptoExchange.Net/Converters/MessageParsing/MessagePath.cs b/CryptoExchange.Net/Converters/MessageParsing/MessagePath.cs deleted file mode 100644 index 54588ed..0000000 --- a/CryptoExchange.Net/Converters/MessageParsing/MessagePath.cs +++ /dev/null @@ -1,50 +0,0 @@ -using System.Collections; -using System.Collections.Generic; - -namespace CryptoExchange.Net.Converters.MessageParsing -{ - /// - /// Message access definition - /// - public readonly struct MessagePath : IEnumerable - { - private readonly List _path; - - internal void Add(NodeAccessor node) - { - _path.Add(node); - } - - /// - /// ctor - /// - public MessagePath() - { - _path = new List(); - } - - /// - /// Create a new message path - /// - /// - public static MessagePath Get() - { - return new MessagePath(); - } - - /// - /// IEnumerable implementation - /// - /// - public IEnumerator GetEnumerator() - { - for (var i = 0; i < _path.Count; i++) - yield return _path[i]; - } - - IEnumerator IEnumerable.GetEnumerator() - { - return GetEnumerator(); - } - } -} diff --git a/CryptoExchange.Net/Converters/MessageParsing/MessagePathExtension.cs b/CryptoExchange.Net/Converters/MessageParsing/MessagePathExtension.cs deleted file mode 100644 index 2f5cde9..0000000 --- a/CryptoExchange.Net/Converters/MessageParsing/MessagePathExtension.cs +++ /dev/null @@ -1,43 +0,0 @@ -namespace CryptoExchange.Net.Converters.MessageParsing -{ - /// - /// Message path extension methods - /// - public static class MessagePathExtension - { - /// - /// Add a string node accessor - /// - /// - /// - /// - public static MessagePath Property(this MessagePath path, string propName) - { - path.Add(NodeAccessor.String(propName)); - return path; - } - - /// - /// Add a property name node accessor - /// - /// - /// - public static MessagePath PropertyName(this MessagePath path) - { - path.Add(NodeAccessor.PropertyName()); - return path; - } - - /// - /// Add a int node accessor - /// - /// - /// - /// - public static MessagePath Index(this MessagePath path, int index) - { - path.Add(NodeAccessor.Int(index)); - return path; - } - } -} diff --git a/CryptoExchange.Net/Converters/MessageParsing/NodeType.cs b/CryptoExchange.Net/Converters/MessageParsing/NodeType.cs deleted file mode 100644 index 21bccb8..0000000 --- a/CryptoExchange.Net/Converters/MessageParsing/NodeType.cs +++ /dev/null @@ -1,21 +0,0 @@ -namespace CryptoExchange.Net.Converters.MessageParsing -{ - /// - /// Message node type - /// - public enum NodeType - { - /// - /// Array node - /// - Array, - /// - /// Object node - /// - Object, - /// - /// Value node - /// - Value - } -} diff --git a/CryptoExchange.Net/Converters/SystemTextJson/SystemTextJsonMessageAccessor.cs b/CryptoExchange.Net/Converters/SystemTextJson/SystemTextJsonMessageAccessor.cs deleted file mode 100644 index 25e5d8a..0000000 --- a/CryptoExchange.Net/Converters/SystemTextJson/SystemTextJsonMessageAccessor.cs +++ /dev/null @@ -1,373 +0,0 @@ -using CryptoExchange.Net.Converters.MessageParsing; -using CryptoExchange.Net.Interfaces; -using CryptoExchange.Net.Objects; -using System; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Text; -using System.Text.Json; -using System.Threading.Tasks; - -namespace CryptoExchange.Net.Converters.SystemTextJson -{ - /// - /// System.Text.Json message accessor - /// - public abstract class SystemTextJsonMessageAccessor : IMessageAccessor - { - /// - /// The JsonDocument loaded - /// - protected JsonDocument? _document; - - private readonly JsonSerializerOptions? _customSerializerOptions; - - /// - public bool IsValid { get; set; } - - /// - public abstract bool OriginalDataAvailable { get; } - - /// - public object? Underlying => throw new NotImplementedException(); - - /// - /// ctor - /// - public SystemTextJsonMessageAccessor(JsonSerializerOptions options) - { - _customSerializerOptions = options; - } - - /// -#if NET5_0_OR_GREATER - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL3050:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] -#endif - public CallResult Deserialize(Type type, MessagePath? path = null) - { - if (!IsValid) - return new CallResult(GetOriginalString()); - - if (_document == null) - throw new InvalidOperationException("No json document loaded"); - - try - { - var result = _document.Deserialize(type, _customSerializerOptions); - return new CallResult(result!); - } - catch (JsonException ex) - { - var info = $"Json deserialization failed: {ex.Message}, Path: {ex.Path}, LineNumber: {ex.LineNumber}, LinePosition: {ex.BytePositionInLine}"; - return new CallResult(new DeserializeError(info, ex)); - } - catch (Exception ex) - { - return new CallResult(new DeserializeError($"Json deserialization failed: {ex.Message}", ex)); - } - } - - /// -#if NET5_0_OR_GREATER - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL3050:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] -#endif - public CallResult Deserialize(MessagePath? path = null) - { - if (_document == null) - throw new InvalidOperationException("No json document loaded"); - - try - { - var result = _document.Deserialize(_customSerializerOptions); - return new CallResult(result!); - } - catch (JsonException ex) - { - var info = $"Json deserialization failed: {ex.Message}, Path: {ex.Path}, LineNumber: {ex.LineNumber}, LinePosition: {ex.BytePositionInLine}"; - return new CallResult(new DeserializeError(info, ex)); - } - catch (Exception ex) - { - return new CallResult(new DeserializeError($"Json deserialization failed: {ex.Message}", ex)); - } - } - - /// - public NodeType? GetNodeType() - { - if (!IsValid) - throw new InvalidOperationException("Can't access json data on non-json message"); - - if (_document == null) - throw new InvalidOperationException("No json document loaded"); - - return _document.RootElement.ValueKind switch - { - JsonValueKind.Object => NodeType.Object, - JsonValueKind.Array => NodeType.Array, - _ => NodeType.Value - }; - } - - /// - public NodeType? GetNodeType(MessagePath path) - { - if (!IsValid) - throw new InvalidOperationException("Can't access json data on non-json message"); - - var node = GetPathNode(path); - if (!node.HasValue) - return null; - - return node.Value.ValueKind switch - { - JsonValueKind.Object => NodeType.Object, - JsonValueKind.Array => NodeType.Array, - _ => NodeType.Value - }; - } - - /// -#if NET5_0_OR_GREATER - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL3050:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] -#endif - public T? GetValue(MessagePath path) - { - if (!IsValid) - throw new InvalidOperationException("Can't access json data on non-json message"); - - var value = GetPathNode(path); - if (value == null) - return default; - - if (value.Value.ValueKind == JsonValueKind.Object || value.Value.ValueKind == JsonValueKind.Array) - { - try - { - return value.Value.Deserialize(_customSerializerOptions); - } - catch { } - - return default; - } - - if (typeof(T) == typeof(string)) - { - if (value.Value.ValueKind == JsonValueKind.Number) - return (T)(object)value.Value.GetInt64().ToString(); - } - - return value.Value.Deserialize(_customSerializerOptions); - } - - /// -#if NET5_0_OR_GREATER - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL3050:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] -#endif - public T?[]? GetValues(MessagePath path) - { - if (!IsValid) - throw new InvalidOperationException("Can't access json data on non-json message"); - - var value = GetPathNode(path); - if (value == null) - return default; - - if (value.Value.ValueKind != JsonValueKind.Array) - return default; - - return value.Value.Deserialize(_customSerializerOptions)!; - } - - private JsonElement? GetPathNode(MessagePath path) - { - if (!IsValid) - throw new InvalidOperationException("Can't access json data on non-json message"); - - if (_document == null) - throw new InvalidOperationException("No json document loaded"); - - JsonElement? currentToken = _document.RootElement; - foreach (var node in path) - { - if (node.Type == 0) - { - // Int value - var val = node.Index!.Value; - if (currentToken!.Value.ValueKind != JsonValueKind.Array || currentToken.Value.GetArrayLength() <= val) - return null; - - currentToken = currentToken.Value[val]; - } - else if (node.Type == 1) - { - // String value - if (currentToken!.Value.ValueKind != JsonValueKind.Object) - return null; - - if (!currentToken.Value.TryGetProperty(node.Property!, out var token)) - return null; - currentToken = token; - } - else - { - // Property name - if (currentToken!.Value.ValueKind != JsonValueKind.Object) - return null; - - throw new NotImplementedException(); - } - - if (currentToken == null) - return null; - } - - return currentToken; - } - - /// - public abstract string GetOriginalString(); - - /// - public abstract void Clear(); - } - - /// - /// System.Text.Json stream message accessor - /// - public class SystemTextJsonStreamMessageAccessor : SystemTextJsonMessageAccessor, IStreamMessageAccessor - { - private Stream? _stream; - - /// - public override bool OriginalDataAvailable => _stream?.CanSeek == true; - - /// - /// ctor - /// - public SystemTextJsonStreamMessageAccessor(JsonSerializerOptions options): base(options) - { - } - - /// - public async Task Read(Stream stream, bool bufferStream) - { - if (bufferStream && stream is not MemoryStream) - { - // We need to be buffer the stream, and it's not currently a seekable stream, so copy it to a new memory stream - _stream = new MemoryStream(); - stream.CopyTo(_stream); - _stream.Position = 0; - } - else if (bufferStream) - { - // We need to buffer the stream, and the current stream is seekable, store as is - _stream = stream; - } - else - { - // We don't need to buffer the stream, so don't bother keeping the reference - } - - try - { - _document = await JsonDocument.ParseAsync(_stream ?? stream).ConfigureAwait(false); - IsValid = true; - return CallResult.SuccessResult; - } - catch (Exception ex) - { - // Not a json message - IsValid = false; - return new CallResult(new DeserializeError($"Json deserialization failed: {ex.Message}", ex)); - } - } - - /// - public override string GetOriginalString() - { - if (_stream is null) - throw new NullReferenceException("Stream not initialized"); - - _stream.Position = 0; - using var textReader = new StreamReader(_stream, Encoding.UTF8, false, 1024, true); - return textReader.ReadToEnd(); - } - - /// - public override void Clear() - { - _stream?.Dispose(); - _stream = null; - _document?.Dispose(); - _document = null; - } - - } - - /// - /// System.Text.Json byte message accessor - /// - public class SystemTextJsonByteMessageAccessor : SystemTextJsonMessageAccessor, IByteMessageAccessor - { - private ReadOnlyMemory _bytes; - - /// - /// ctor - /// - public SystemTextJsonByteMessageAccessor(JsonSerializerOptions options) : base(options) - { - } - - /// - public CallResult Read(ReadOnlyMemory data) - { - _bytes = data; - - try - { - var firstByte = data.Span[0]; - if (firstByte != 0x7b && firstByte != 0x5b) - { - // Value doesn't start with `{` or `[`, prevent deserialization attempt as it's slow - IsValid = false; - return new CallResult(new DeserializeError("Not a json value")); - } - - _document = JsonDocument.Parse(data); - IsValid = true; - return CallResult.SuccessResult; - } - catch (Exception ex) - { - // Not a json message - IsValid = false; - return new CallResult(new DeserializeError($"Json deserialization failed: {ex.Message}", ex)); - } - } - - /// - public override string GetOriginalString() => - // NetStandard 2.0 doesn't support GetString from a ReadonlySpan, so use ToArray there instead -#if NETSTANDARD2_0 - Encoding.UTF8.GetString(_bytes.ToArray()); -#else - Encoding.UTF8.GetString(_bytes.Span); -#endif - - /// - public override bool OriginalDataAvailable => true; - - /// - public override void Clear() - { - _bytes = null; - _document?.Dispose(); - _document = null; - } - } -} \ No newline at end of file diff --git a/CryptoExchange.Net/ExtensionMethods.cs b/CryptoExchange.Net/ExtensionMethods.cs index 7dd272c..bbf562f 100644 --- a/CryptoExchange.Net/ExtensionMethods.cs +++ b/CryptoExchange.Net/ExtensionMethods.cs @@ -292,122 +292,6 @@ namespace CryptoExchange.Net return sb.ToString(); } - /// - /// Create a new uri with the provided parameters as query - /// - /// - /// - /// - /// - public static Uri SetParameters(this Uri baseUri, IDictionary parameters, ArrayParametersSerialization arraySerialization) - { - var uriBuilder = new UriBuilder(); - uriBuilder.Scheme = baseUri.Scheme; - uriBuilder.Host = baseUri.Host; - uriBuilder.Port = baseUri.Port; - uriBuilder.Path = baseUri.AbsolutePath; - var httpValueCollection = HttpUtility.ParseQueryString(string.Empty); - foreach (var parameter in parameters) - { - if (parameter.Value.GetType().IsArray) - { - if (arraySerialization == ArrayParametersSerialization.JsonArray) - { - httpValueCollection.Add(parameter.Key, $"[{string.Join(",", (object[])parameter.Value)}]"); - } - else - { - foreach (var item in (object[])parameter.Value) - { - if (arraySerialization == ArrayParametersSerialization.Array) - { - httpValueCollection.Add(parameter.Key + "[]", item.ToString()); - } - else - { - httpValueCollection.Add(parameter.Key, item.ToString()); - } - } - } - } - else - { - httpValueCollection.Add(parameter.Key, parameter.Value.ToString()); - } - } - - uriBuilder.Query = httpValueCollection.ToString(); - return uriBuilder.Uri; - } - - /// - /// Create a new uri with the provided parameters as query - /// - /// - /// - /// - /// - public static Uri SetParameters(this Uri baseUri, IOrderedEnumerable> parameters, ArrayParametersSerialization arraySerialization) - { - var uriBuilder = new UriBuilder(); - uriBuilder.Scheme = baseUri.Scheme; - uriBuilder.Host = baseUri.Host; - uriBuilder.Port = baseUri.Port; - uriBuilder.Path = baseUri.AbsolutePath; - var httpValueCollection = HttpUtility.ParseQueryString(string.Empty); - foreach (var parameter in parameters) - { - if (parameter.Value.GetType().IsArray) - { - if (arraySerialization == ArrayParametersSerialization.JsonArray) - { - httpValueCollection.Add(parameter.Key, $"[{string.Join(",", (object[])parameter.Value)}]"); - } - else - { - foreach (var item in (object[])parameter.Value) - { - if (arraySerialization == ArrayParametersSerialization.Array) - { - httpValueCollection.Add(parameter.Key + "[]", item.ToString()); - } - else - { - httpValueCollection.Add(parameter.Key, item.ToString()); - } - } - } - } - else - { - httpValueCollection.Add(parameter.Key, parameter.Value.ToString()); - } - } - - uriBuilder.Query = httpValueCollection.ToString(); - return uriBuilder.Uri; - } - - /// - /// Add parameter to URI - /// - /// - /// - /// - /// - public static Uri AddQueryParameter(this Uri uri, string name, string value) - { - var httpValueCollection = HttpUtility.ParseQueryString(uri.Query); - - httpValueCollection.Remove(name); - httpValueCollection.Add(name, value); - - var ub = new UriBuilder(uri); - ub.Query = httpValueCollection.ToString(); - - return ub.Uri; - } - /// /// Decompress using GzipStream /// @@ -419,20 +303,6 @@ namespace CryptoExchange.Net return new ReadOnlySpan(decompressedStream.GetBuffer(), 0, (int)decompressedStream.Length); } - /// - /// Decompress using GzipStream - /// - public static ReadOnlyMemory DecompressGzip(this ReadOnlyMemory data) - { - using var decompressedStream = new MemoryStream(); - using var dataStream = MemoryMarshal.TryGetArray(data, out var arraySegment) - ? new MemoryStream(arraySegment.Array!, arraySegment.Offset, arraySegment.Count) - : new MemoryStream(data.ToArray()); - using var deflateStream = new GZipStream(dataStream, CompressionMode.Decompress); - deflateStream.CopyTo(decompressedStream); - return new ReadOnlyMemory(decompressedStream.GetBuffer(), 0, (int)decompressedStream.Length); - } - /// /// Decompress using GzipStream /// @@ -445,22 +315,6 @@ namespace CryptoExchange.Net return new ReadOnlySpan(output.GetBuffer(), 0, (int)output.Length); } - /// - /// Decompress using DeflateStream - /// - /// - /// - public static ReadOnlyMemory Decompress(this ReadOnlyMemory input) - { - var output = new MemoryStream(); - - using var compressStream = new MemoryStream(input.ToArray()); - using var decompressor = new DeflateStream(compressStream, CompressionMode.Decompress); - decompressor.CopyTo(output); - output.Position = 0; - return new ReadOnlyMemory(output.GetBuffer(), 0, (int)output.Length); - } - /// /// Whether the trading mode is linear /// diff --git a/CryptoExchange.Net/Interfaces/IMessageAccessor.cs b/CryptoExchange.Net/Interfaces/IMessageAccessor.cs deleted file mode 100644 index d0a3773..0000000 --- a/CryptoExchange.Net/Interfaces/IMessageAccessor.cs +++ /dev/null @@ -1,109 +0,0 @@ -using CryptoExchange.Net.Converters.MessageParsing; -using CryptoExchange.Net.Objects; -using System; -using System.Diagnostics.CodeAnalysis; -using System.IO; -using System.Threading.Tasks; - -namespace CryptoExchange.Net.Interfaces -{ - /// - /// Message accessor - /// - public interface IMessageAccessor - { - /// - /// Is this a valid message - /// - bool IsValid { get; } - /// - /// Is the original data available for retrieval - /// - bool OriginalDataAvailable { get; } - /// - /// The underlying data object - /// - object? Underlying { get; } - /// - /// Clear internal data structure - /// - void Clear(); - /// - /// Get the type of node - /// - /// - NodeType? GetNodeType(); - /// - /// Get the type of node - /// - /// Access path - /// - NodeType? GetNodeType(MessagePath path); - /// - /// Get the value of a path - /// - /// - /// - /// - T? GetValue(MessagePath path); - /// - /// Get the values of an array - /// - /// - /// - /// - T?[]? GetValues(MessagePath path); - /// - /// Deserialize the message into this type - /// - /// - /// - /// -#if NET5_0_OR_GREATER - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2092:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2095:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] -#endif - CallResult Deserialize(Type type, MessagePath? path = null); - /// - /// Deserialize the message into this type - /// - /// - /// -#if NET5_0_OR_GREATER - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2092:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] - [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2095:RequiresUnreferencedCode", Justification = "JsonSerializerOptions provided here has TypeInfoResolver set")] -#endif - CallResult Deserialize(MessagePath? path = null); - - /// - /// Get the original string value - /// - /// - string GetOriginalString(); - } - - /// - /// Stream message accessor - /// - public interface IStreamMessageAccessor : IMessageAccessor - { - /// - /// Load a stream message - /// - /// - /// - Task Read(Stream stream, bool bufferStream); - } - - /// - /// Byte message accessor - /// - public interface IByteMessageAccessor : IMessageAccessor - { - /// - /// Load a data message - /// - /// - CallResult Read(ReadOnlyMemory data); - } -} diff --git a/CryptoExchange.Net/Objects/Options/SocketExchangeOptions.cs b/CryptoExchange.Net/Objects/Options/SocketExchangeOptions.cs index a3e7ef4..9500267 100644 --- a/CryptoExchange.Net/Objects/Options/SocketExchangeOptions.cs +++ b/CryptoExchange.Net/Objects/Options/SocketExchangeOptions.cs @@ -75,11 +75,6 @@ namespace CryptoExchange.Net.Objects.Options /// public int? ReceiveBufferSize { get; set; } - /// - /// Whether or not to use the updated deserialization logic, default is true - /// - public bool UseUpdatedDeserialization { get; set; } = true; - /// /// Create a copy of this options /// @@ -101,7 +96,6 @@ namespace CryptoExchange.Net.Objects.Options item.RateLimitingBehaviour = RateLimitingBehaviour; item.RateLimiterEnabled = RateLimiterEnabled; item.ReceiveBufferSize = ReceiveBufferSize; - item.UseUpdatedDeserialization = UseUpdatedDeserialization; return item; } } diff --git a/CryptoExchange.Net/Objects/Sockets/WebSocketParameters.cs b/CryptoExchange.Net/Objects/Sockets/WebSocketParameters.cs index 8057716..5ce4c1a 100644 --- a/CryptoExchange.Net/Objects/Sockets/WebSocketParameters.cs +++ b/CryptoExchange.Net/Objects/Sockets/WebSocketParameters.cs @@ -73,11 +73,6 @@ namespace CryptoExchange.Net.Objects.Sockets /// The buffer size to use for receiving data /// public int? ReceiveBufferSize { get; set; } = null; - - /// - /// Whether or not to use the updated deserialization logic - /// - public bool UseUpdatedDeserialization { get; set; } /// /// ctor diff --git a/CryptoExchange.Net/Sockets/Default/CryptoExchangeWebSocketClient.cs b/CryptoExchange.Net/Sockets/Default/CryptoExchangeWebSocketClient.cs index dc38561..11a2f7b 100644 --- a/CryptoExchange.Net/Sockets/Default/CryptoExchangeWebSocketClient.cs +++ b/CryptoExchange.Net/Sockets/Default/CryptoExchangeWebSocketClient.cs @@ -95,9 +95,6 @@ namespace CryptoExchange.Net.Sockets.Default /// public event Func? OnClose; - /// - public event Func, Task>? OnStreamMessage; - /// public event Func? OnRequestSent; @@ -139,10 +136,7 @@ namespace CryptoExchange.Net.Sockets.Default _sendEvent = new AsyncResetEvent(); _sendBuffer = new ConcurrentQueue(); _ctsSource = new CancellationTokenSource(); - if (websocketParameters.UseUpdatedDeserialization) - _receiveBufferSize = websocketParameters.ReceiveBufferSize ?? 65536; - else - _receiveBufferSize = websocketParameters.ReceiveBufferSize ?? _defaultReceiveBufferSize; + _receiveBufferSize = websocketParameters.ReceiveBufferSize ?? 65536; _closeSem = new SemaphoreSlim(1, 1); _socket = CreateSocket(); @@ -225,7 +219,9 @@ namespace CryptoExchange.Net.Sockets.Default catch (Exception e) { if (ct.IsCancellationRequested) + { _logger.SocketConnectingCanceled(Id); + } else if (!_ctsSource.IsCancellationRequested) { // if _ctsSource was canceled this was already logged @@ -271,11 +267,10 @@ namespace CryptoExchange.Net.Sockets.Default var sendTask = SendLoopAsync(); Task receiveTask; #if !NETSTANDARD2_0 - if (Parameters.UseUpdatedDeserialization) - receiveTask = ReceiveLoopNewAsync(); - else + receiveTask = ReceiveLoopNewAsync(); +#else + receiveTask = ReceiveLoopAsync(); #endif - receiveTask = ReceiveLoopAsync(); var timeoutTask = Parameters.Timeout != null && Parameters.Timeout > TimeSpan.FromSeconds(0) ? CheckTimeoutAsync() : Task.CompletedTask; await Task.WhenAll(sendTask, receiveTask, timeoutTask).ConfigureAwait(false); _logger.SocketFinishedProcessing(Id); @@ -578,6 +573,7 @@ namespace CryptoExchange.Net.Sockets.Default } } +#if NETSTANDARD2_0 /// /// Loop for receiving and reassembling data /// @@ -666,10 +662,7 @@ namespace CryptoExchange.Net.Sockets.Default if (_logger.IsEnabled(LogLevel.Trace)) _logger.SocketReceivedSingleMessage(Id, receiveResult.Count); - if (!Parameters.UseUpdatedDeserialization) - await ProcessData(receiveResult.MessageType, new ReadOnlyMemory(buffer.Array!, buffer.Offset, receiveResult.Count)).ConfigureAwait(false); - else - ProcessDataNew(receiveResult.MessageType, new ReadOnlySpan(buffer.Array!, buffer.Offset, receiveResult.Count)); + ProcessDataNew(receiveResult.MessageType, new ReadOnlySpan(buffer.Array!, buffer.Offset, receiveResult.Count)); } else { @@ -703,11 +696,7 @@ namespace CryptoExchange.Net.Sockets.Default _logger.SocketReassembledMessage(Id, multipartStream!.Length); // Get the underlying buffer of the memory stream holding the written data and delimit it (GetBuffer return the full array, not only the written part) - - if (!Parameters.UseUpdatedDeserialization) - await ProcessData(receiveResult.MessageType, new ReadOnlyMemory(multipartStream!.GetBuffer(), 0, (int)multipartStream.Length)).ConfigureAwait(false); - else - ProcessDataNew(receiveResult.MessageType, new ReadOnlySpan(multipartStream!.GetBuffer(), 0, (int)multipartStream.Length)); + ProcessDataNew(receiveResult.MessageType, new ReadOnlySpan(multipartStream!.GetBuffer(), 0, (int)multipartStream.Length)); } else { @@ -732,6 +721,7 @@ namespace CryptoExchange.Net.Sockets.Default _logger.SocketReceiveLoopFinished(Id); } } +#endif #if !NETSTANDARD2_0 /// @@ -895,18 +885,6 @@ namespace CryptoExchange.Net.Sockets.Default _connection.HandleStreamMessage2(type, data); } - /// - /// Process a stream message - /// - /// - /// - /// - protected async Task ProcessData(WebSocketMessageType type, ReadOnlyMemory data) - { - LastActionTime = DateTime.UtcNow; - await (OnStreamMessage?.Invoke(type, data) ?? Task.CompletedTask).ConfigureAwait(false); - } - /// /// Checks if there is no data received for a period longer than the specified timeout /// diff --git a/CryptoExchange.Net/Sockets/Default/Interfaces/IWebsocket.cs b/CryptoExchange.Net/Sockets/Default/Interfaces/IWebsocket.cs index 3aa4f13..22fe927 100644 --- a/CryptoExchange.Net/Sockets/Default/Interfaces/IWebsocket.cs +++ b/CryptoExchange.Net/Sockets/Default/Interfaces/IWebsocket.cs @@ -16,10 +16,6 @@ namespace CryptoExchange.Net.Sockets.Default.Interfaces /// event Func OnClose; /// - /// Websocket message received event - /// - event Func, Task> OnStreamMessage; - /// /// Websocket sent event, RequestId as parameter /// event Func OnRequestSent; diff --git a/CryptoExchange.Net/Sockets/Default/SocketConnection.cs b/CryptoExchange.Net/Sockets/Default/SocketConnection.cs index 196990d..4d93e54 100644 --- a/CryptoExchange.Net/Sockets/Default/SocketConnection.cs +++ b/CryptoExchange.Net/Sockets/Default/SocketConnection.cs @@ -111,11 +111,6 @@ namespace CryptoExchange.Net.Sockets.Default /// public event Action? ActivityUnpaused; - /// - /// Unhandled message event - /// - public event Action? UnhandledMessage; - /// /// Connection was rate limited and couldn't be established /// @@ -269,8 +264,6 @@ namespace CryptoExchange.Net.Sockets.Default private SocketStatus _status; private readonly IMessageSerializer _serializer; - private IByteMessageAccessor? _stringMessageAccessor; - private IByteMessageAccessor? _byteMessageAccessor; private ISocketMessageHandler? _byteMessageConverter; private ISocketMessageHandler? _textMessageConverter; @@ -291,11 +284,6 @@ namespace CryptoExchange.Net.Sockets.Default /// The underlying websocket /// private readonly IWebsocket _socket; - - /// - /// Cache for deserialization, only caches for a single message - /// - private readonly Dictionary _deserializationCache = new Dictionary(); /// /// New socket connection @@ -310,7 +298,6 @@ namespace CryptoExchange.Net.Sockets.Default _socket = socketFactory.CreateWebsocket(logger, this, parameters); _logger.SocketCreatedForAddress(_socket.Id, parameters.Uri.ToString()); - _socket.OnStreamMessage += HandleStreamMessage; _socket.OnRequestSent += HandleRequestSentAsync; _socket.OnRequestRateLimited += HandleRequestRateLimitedAsync; _socket.OnConnectRateLimited += HandleConnectRateLimitedAsync; @@ -671,144 +658,6 @@ namespace CryptoExchange.Net.Sockets.Default } } - /// - /// Handle a message - /// - protected virtual async Task HandleStreamMessage(WebSocketMessageType type, ReadOnlyMemory data) - { - var sw = Stopwatch.StartNew(); - var receiveTime = DateTime.UtcNow; - string? originalData = null; - - // 1. Decrypt/Preprocess if necessary - data = ApiClient.PreprocessStreamMessage(this, type, data); - - // 2. Read data into accessor - IByteMessageAccessor accessor; - if (type == WebSocketMessageType.Binary) - accessor = _stringMessageAccessor ??= ApiClient.CreateAccessor(type); - else - accessor = _byteMessageAccessor ??= ApiClient.CreateAccessor(type); - - var result = accessor.Read(data); - try - { - bool outputOriginalData = ApiClient.ApiOptions.OutputOriginalData ?? ApiClient.ClientOptions.OutputOriginalData; - if (outputOriginalData) - { - originalData = accessor.GetOriginalString(); - _logger.ReceivedData(SocketId, originalData); - } - - if (!accessor.IsValid && !ApiClient.ProcessUnparsableMessages) - { - _logger.FailedToParse(SocketId, result.Error!.Message ?? result.Error!.ErrorDescription!); - return; - } - - // 3. Determine the identifying properties of this message - var listenId = ApiClient.GetListenerIdentifier(accessor); - if (listenId == null) - { - originalData ??= "[OutputOriginalData is false]"; - if (!ApiClient.UnhandledMessageExpected) - _logger.FailedToEvaluateMessage(SocketId, originalData); - - UnhandledMessage?.Invoke(accessor); - return; - } - - bool processed = false; - var totalUserTime = 0; - - List localListeners; - lock (_listenersLock) - localListeners = _listeners.ToList(); - - foreach (var processor in localListeners) - { - foreach (var listener in processor.MessageMatcher.GetHandlerLinks(listenId)) - { - processed = true; - _logger.ProcessorMatched(SocketId, listener.ToString(), listenId); - - // 4. Determine the type to deserialize to for this processor - var messageType = listener.DeserializationType; - if (messageType == null) - { - _logger.ReceivedMessageNotRecognized(SocketId, processor.Id); - continue; - } - - if (processor is Subscription subscriptionProcessor && subscriptionProcessor.Status == SubscriptionStatus.Subscribing) - { - // If this message is for this listener then it is automatically confirmed, even if the subscription is not (yet) confirmed - subscriptionProcessor.Status = SubscriptionStatus.Subscribed; - if (subscriptionProcessor.SubscriptionQuery?.TimeoutBehavior == TimeoutBehavior.Succeed) - // If this subscription has a query waiting for a timeout (success if there is no error response) - // then time it out now as the data is being received, so we assume it's successful - subscriptionProcessor.SubscriptionQuery.Timeout(); - } - - // 5. Deserialize the message - _deserializationCache.TryGetValue(messageType, out var deserialized); - - if (deserialized == null) - { - var desResult = processor.Deserialize(accessor, messageType); - if (!desResult) - { - _logger.FailedToDeserializeMessage(SocketId, desResult.Error?.ToString(), desResult.Error?.Exception); - continue; - } - - deserialized = desResult.Data; - _deserializationCache.Add(messageType, deserialized); - } - - // 6. Pass the message to the handler - try - { - var innerSw = Stopwatch.StartNew(); - processor.Handle(this, receiveTime, originalData, deserialized, listener); - if (processor is Query query && query.RequiredResponses != 1) - _logger.LogDebug($"[Sckt {SocketId}] [Req {query.Id}] responses: {query.CurrentResponses}/{query.RequiredResponses}"); - totalUserTime += (int)innerSw.ElapsedMilliseconds; - } - catch (Exception ex) - { - _logger.UserMessageProcessingFailed(SocketId, ex.Message, ex); - if (processor is Subscription subscription) - subscription.InvokeExceptionHandler(ex); - } - - } - } - - if (!processed) - { - if (!ApiClient.UnhandledMessageExpected) - { - List listenerIds; - lock (_listenersLock) - listenerIds = _listeners.Select(l => l.MessageMatcher.ToString()).ToList(); - - _logger.ReceivedMessageNotMatchedToAnyListener(SocketId, listenId, string.Join(",", listenerIds)); - UnhandledMessage?.Invoke(accessor); - } - - return; - } - - _logger.MessageProcessed(SocketId, sw.ElapsedMilliseconds, sw.ElapsedMilliseconds - totalUserTime); - } - finally - { - _deserializationCache.Clear(); - accessor.Clear(); - } - } - /// /// Connect the websocket /// @@ -886,16 +735,8 @@ namespace CryptoExchange.Net.Sockets.Default subscription.CancellationTokenRegistration.Value.Dispose(); bool anyDuplicateSubscription; - if (ApiClient.ClientOptions.UseUpdatedDeserialization) - { - lock (_listenersLock) - anyDuplicateSubscription = _listeners.OfType().Any(x => x != subscription && x.MessageRouter.Routes.All(l => subscription.MessageRouter.ContainsCheck(l))); - } - else - { - lock (_listenersLock) - anyDuplicateSubscription = _listeners.OfType().Any(x => x != subscription && x.MessageMatcher.HandlerLinks.All(l => subscription.MessageMatcher.ContainsCheck(l))); - } + lock (_listenersLock) + anyDuplicateSubscription = _listeners.OfType().Any(x => x != subscription && x.MessageRouter.Routes.All(l => subscription.MessageRouter.ContainsCheck(l))); bool shouldCloseConnection; lock (_listenersLock) @@ -947,12 +788,6 @@ namespace CryptoExchange.Net.Sockets.Default _socket.Dispose(); } - /// - /// Whether or not a new subscription can be added to this connection - /// - /// - public bool CanAddSubscription() => Status == SocketStatus.None || Status == SocketStatus.Connected; - /// /// Add a subscription to this connection /// diff --git a/CryptoExchange.Net/Sockets/Default/Subscription.cs b/CryptoExchange.Net/Sockets/Default/Subscription.cs index 73d0490..2cc1a56 100644 --- a/CryptoExchange.Net/Sockets/Default/Subscription.cs +++ b/CryptoExchange.Net/Sockets/Default/Subscription.cs @@ -70,11 +70,6 @@ namespace CryptoExchange.Net.Sockets.Default /// public bool Authenticated { get; } - /// - /// Matcher for this subscription - /// - public MessageMatcher MessageMatcher { get; set; } - /// /// Router for this subscription /// @@ -154,6 +149,7 @@ namespace CryptoExchange.Net.Sockets.Default /// /// Handle an unsubscription query response /// + #warning ? public virtual void HandleUnsubQueryResponse(SocketConnection connection, object message) { } /// @@ -172,19 +168,6 @@ namespace CryptoExchange.Net.Sockets.Default /// protected abstract Query? GetUnsubQuery(SocketConnection connection); - /// - public virtual CallResult Deserialize(IMessageAccessor message, Type type) => message.Deserialize(type); - - /// - /// Handle an update message - /// - public CallResult Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object data, MessageHandlerLink matcher) - { - ConnectionInvocations++; - TotalInvocations++; - return matcher.Handle(connection, receiveTime, originalData, data); - } - /// /// Handle an update message /// @@ -224,12 +207,12 @@ namespace CryptoExchange.Net.Sockets.Default /// The id of the subscription /// Subscription status /// Number of times this subscription got a message - /// Matcher for this subscription + /// Router for this subscription public record SubscriptionState( int Id, SubscriptionStatus Status, int Invocations, - MessageMatcher ListenMatcher + MessageRouter MessageRouter ); /// @@ -238,7 +221,7 @@ namespace CryptoExchange.Net.Sockets.Default /// public SubscriptionState GetState() { - return new SubscriptionState(Id, Status, TotalInvocations, MessageMatcher); + return new SubscriptionState(Id, Status, TotalInvocations, MessageRouter); } } } diff --git a/CryptoExchange.Net/Sockets/HighPerf/HighPerfSocketConnection.cs b/CryptoExchange.Net/Sockets/HighPerf/HighPerfSocketConnection.cs index 5d4f77e..c452670 100644 --- a/CryptoExchange.Net/Sockets/HighPerf/HighPerfSocketConnection.cs +++ b/CryptoExchange.Net/Sockets/HighPerf/HighPerfSocketConnection.cs @@ -245,7 +245,9 @@ namespace CryptoExchange.Net.Sockets.HighPerf public virtual ValueTask SendAsync(T obj) { if (_serializer is IByteMessageSerializer byteSerializer) + { return SendBytesAsync(byteSerializer.Serialize(obj)); + } else if (_serializer is IStringMessageSerializer stringSerializer) { if (obj is string str) diff --git a/CryptoExchange.Net/Sockets/Interfaces/IMessageProcessor.cs b/CryptoExchange.Net/Sockets/Interfaces/IMessageProcessor.cs index c98f846..24e5d5b 100644 --- a/CryptoExchange.Net/Sockets/Interfaces/IMessageProcessor.cs +++ b/CryptoExchange.Net/Sockets/Interfaces/IMessageProcessor.cs @@ -15,27 +15,12 @@ namespace CryptoExchange.Net.Sockets.Interfaces /// public int Id { get; } /// - /// The matcher for this listener - /// - public MessageMatcher MessageMatcher { get; } - /// /// The message router for this processor /// public MessageRouter MessageRouter { get; } /// /// Handle a message /// - CallResult Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object result, MessageHandlerLink matchedHandler); - /// - /// Handle a message - /// CallResult? Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object result, MessageRoute route); - /// - /// Deserialize a message into object of type - /// - /// - /// - /// - CallResult Deserialize(IMessageAccessor accessor, Type type); } } diff --git a/CryptoExchange.Net/Sockets/MessageMatcher.cs b/CryptoExchange.Net/Sockets/MessageMatcher.cs deleted file mode 100644 index b208f44..0000000 --- a/CryptoExchange.Net/Sockets/MessageMatcher.cs +++ /dev/null @@ -1,185 +0,0 @@ -using CryptoExchange.Net.Objects; -using CryptoExchange.Net.Sockets.Default; -using System; -using System.Collections.Generic; -using System.Linq; - -namespace CryptoExchange.Net.Sockets -{ - /// - /// Message link type - /// - public enum MessageLinkType - { - /// - /// Match when the listen id matches fully to the value - /// - Full, - /// - /// Match when the listen id starts with the value - /// - StartsWith - } - - /// - /// Matches a message listen id to a specific listener - /// - public class MessageMatcher - { - /// - /// Linkers in this matcher - /// - public MessageHandlerLink[] HandlerLinks { get; } - - /// - /// ctor - /// - private MessageMatcher(params MessageHandlerLink[] links) - { - HandlerLinks = links; - } - - /// - /// Create message matcher - /// - public static MessageMatcher Create(string value) - { - return new MessageMatcher(new MessageHandlerLink(MessageLinkType.Full, value, (con, receiveTime, originalData, msg) => new CallResult(default, null, null))); - } - - /// - /// Create message matcher - /// - public static MessageMatcher Create(string value) - { - return new MessageMatcher(new MessageHandlerLink(MessageLinkType.Full, value, (con, receiveTime, originalData, msg) => new CallResult(default, null, null))); - } - - /// - /// Create message matcher - /// - public static MessageMatcher Create(string value, Func handler) - { - return new MessageMatcher(new MessageHandlerLink(MessageLinkType.Full, value, handler)); - } - - /// - /// Create message matcher - /// - public static MessageMatcher Create(IEnumerable values, Func handler) - { - return new MessageMatcher(values.Select(x => new MessageHandlerLink(MessageLinkType.Full, x, handler)).ToArray()); - } - - /// - /// Create message matcher - /// - public static MessageMatcher Create(MessageLinkType type, string value, Func handler) - { - return new MessageMatcher(new MessageHandlerLink(type, value, handler)); - } - - /// - /// Create message matcher - /// - public static MessageMatcher Create(params MessageHandlerLink[] linkers) - { - return new MessageMatcher(linkers); - } - - /// - /// Whether this matcher contains a specific link - /// - public bool ContainsCheck(MessageHandlerLink link) => HandlerLinks.Any(x => x.Type == link.Type && x.Value == link.Value); - - /// - /// Get any handler links matching with the listen id - /// - public IEnumerable GetHandlerLinks(string listenId) => HandlerLinks.Where(x => x.Check(listenId)); - - /// - public override string ToString() => string.Join(",", HandlerLinks.Select(x => x.ToString())); - } - - /// - /// Message handler link - /// - public abstract class MessageHandlerLink - { - /// - /// Type of check - /// - public MessageLinkType Type { get; } - /// - /// String value of the check - /// - public string Value { get; } - /// - /// Deserialization type - /// - public abstract Type DeserializationType { get; } - - /// - /// ctor - /// - public MessageHandlerLink(MessageLinkType type, string value) - { - Type = type; - Value = value; - } - - /// - /// Whether this listen id matches this link - /// - public bool Check(string listenId) - { - if (Type == MessageLinkType.Full) - return Value.Equals(listenId, StringComparison.Ordinal); - - return listenId.StartsWith(Value, StringComparison.Ordinal); - } - - /// - /// Message handler - /// - public abstract CallResult Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object data); - - /// - public override string ToString() => $"{Type} match for \"{Value}\""; - } - - /// - /// Message handler link - /// - public class MessageHandlerLink: MessageHandlerLink - { - private Func _handler; - - /// - public override Type DeserializationType => typeof(TServer); - - /// - /// ctor - /// - public MessageHandlerLink(string value, Func handler) - : this(MessageLinkType.Full, value, handler) - { - } - - /// - /// ctor - /// - public MessageHandlerLink(MessageLinkType type, string value, Func handler) - : base(type, value) - { - _handler = handler; - } - - - /// - public override CallResult Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object data) - { - return _handler(connection, receiveTime, originalData, (TServer)data); - } - } -} diff --git a/CryptoExchange.Net/Sockets/Query.cs b/CryptoExchange.Net/Sockets/Query.cs index 3796768..55362a3 100644 --- a/CryptoExchange.Net/Sockets/Query.cs +++ b/CryptoExchange.Net/Sockets/Query.cs @@ -59,11 +59,6 @@ namespace CryptoExchange.Net.Sockets /// public object? Response { get; set; } - /// - /// Matcher for this query - /// - public MessageMatcher MessageMatcher { get; set; } - /// /// Router for this query /// @@ -146,9 +141,6 @@ namespace CryptoExchange.Net.Sockets /// public async Task WaitAsync(TimeSpan timeout, CancellationToken ct) => await _event.WaitAsync(timeout, ct).ConfigureAwait(false); - /// - public virtual CallResult Deserialize(IMessageAccessor message, Type type) => message.Deserialize(type); - /// /// Mark request as timeout /// @@ -160,11 +152,6 @@ namespace CryptoExchange.Net.Sockets /// public abstract void Fail(Error error); - /// - /// Handle a response message - /// - public abstract CallResult Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object message, MessageHandlerLink check); - /// /// Handle a response message /// @@ -223,35 +210,6 @@ namespace CryptoExchange.Net.Sockets return Result ?? CallResult.SuccessResult; } - /// - public override CallResult Handle(SocketConnection connection, DateTime receiveTime, string? originalData, object message, MessageHandlerLink check) - { - if (!PreCheckMessage(connection, message)) - return CallResult.SuccessResult; - - CurrentResponses++; - if (CurrentResponses == RequiredResponses) - Response = message; - - if (Result?.Success != false) - // If an error result is already set don't override that - Result = check.Handle(connection, receiveTime, originalData, message); - - if (CurrentResponses == RequiredResponses) - { - Completed = true; - _event.Set(); - OnComplete?.Invoke(); - } - - return Result; - } - - /// - /// Validate if a message is actually processable by this query - /// - public virtual bool PreCheckMessage(SocketConnection connection, object message) => true; - /// public override void Timeout() { diff --git a/CryptoExchange.Net/Testing/Implementations/TestSocket.cs b/CryptoExchange.Net/Testing/Implementations/TestSocket.cs index 35ea438..34934e6 100644 --- a/CryptoExchange.Net/Testing/Implementations/TestSocket.cs +++ b/CryptoExchange.Net/Testing/Implementations/TestSocket.cs @@ -28,7 +28,6 @@ namespace CryptoExchange.Net.Testing.Implementations public event Func? OnError; #pragma warning restore 0067 public event Func? OnRequestSent; - public event Func, Task>? OnStreamMessage; public event Func? OnOpen; public int Id { get; } @@ -45,14 +44,10 @@ namespace CryptoExchange.Net.Testing.Implementations public static readonly object lastIdLock = new object(); #endif - private bool _newDeserialization; - public SocketConnection? Connection { get; set; } - public TestSocket(bool newDeserialization, string address) + public TestSocket(string address) { - _newDeserialization = newDeserialization; - Uri = new Uri(address); lock (lastIdLock) { @@ -107,17 +102,10 @@ namespace CryptoExchange.Net.Testing.Implementations public void InvokeMessage(string data) { - if (!_newDeserialization) - { - OnStreamMessage?.Invoke(WebSocketMessageType.Text, new ReadOnlyMemory(Encoding.UTF8.GetBytes(data))).Wait(); - } - else - { - if (Connection == null) - throw new ArgumentNullException(nameof(Connection)); + if (Connection == null) + throw new ArgumentNullException(nameof(Connection)); - Connection.HandleStreamMessage2(WebSocketMessageType.Text, Encoding.UTF8.GetBytes(data)); - } + Connection.HandleStreamMessage2(WebSocketMessageType.Text, Encoding.UTF8.GetBytes(data)); } public Task ReconnectAsync() => Task.CompletedTask; diff --git a/CryptoExchange.Net/Testing/SocketIntegrationTest.cs b/CryptoExchange.Net/Testing/SocketIntegrationTest.cs index f099bcc..1501c45 100644 --- a/CryptoExchange.Net/Testing/SocketIntegrationTest.cs +++ b/CryptoExchange.Net/Testing/SocketIntegrationTest.cs @@ -18,7 +18,7 @@ namespace CryptoExchange.Net.Testing /// /// Get a client instance /// - public abstract TClient GetClient(ILoggerFactory loggerFactory, bool newDeserialization); + public abstract TClient GetClient(ILoggerFactory loggerFactory); /// /// Whether the test should be run. By default integration tests aren't executed, can be set to true to force execution. @@ -34,11 +34,11 @@ namespace CryptoExchange.Net.Testing /// Create a client /// /// - protected TClient CreateClient(bool useNewDeserialization) + protected TClient CreateClient() { var fact = new LoggerFactory(); fact.AddProvider(new TraceLoggerProvider()); - return GetClient(fact, useNewDeserialization); + return GetClient(fact); } /// @@ -58,16 +58,15 @@ namespace CryptoExchange.Net.Testing /// Execute a REST endpoint call and check for any errors or warnings. /// /// Type of the update - /// Whether to use the new deserialization method /// The call expression /// Whether an update is expected /// Whether this is an authenticated request - public async Task RunAndCheckUpdate(bool useNewDeserialization, Expression>, Task>>> expression, bool expectUpdate, bool authRequest) + public async Task RunAndCheckUpdate(Expression>, Task>>> expression, bool expectUpdate, bool authRequest) { if (!ShouldRun()) return; - var client = CreateClient(useNewDeserialization); + var client = CreateClient(); var expressionBody = (MethodCallExpression)expression.Body; if (authRequest && !Authenticated) diff --git a/CryptoExchange.Net/Testing/TestHelpers.cs b/CryptoExchange.Net/Testing/TestHelpers.cs index 797c7be..169d186 100644 --- a/CryptoExchange.Net/Testing/TestHelpers.cs +++ b/CryptoExchange.Net/Testing/TestHelpers.cs @@ -63,7 +63,7 @@ namespace CryptoExchange.Net.Testing internal static TestSocket ConfigureSocketClient(T client, string address) where T : BaseSocketClient { - var socket = new TestSocket(client.ClientOptions.UseUpdatedDeserialization, address); + var socket = new TestSocket(address); foreach (var apiClient in client.ApiClients.OfType()) { apiClient.SocketFactory = new TestWebsocketFactory(socket);