public void SocketMessages_Should_ContainOriginalDataIfEnabled(bool enabled) { // arrange var client = new TestSocketClient(new SocketClientOptions("") { ReconnectInterval = TimeSpan.Zero, LogLevel = LogLevel.Debug, OutputOriginalData = enabled }); var socket = client.CreateSocket(); socket.ShouldReconnect = true; socket.CanConnect = true; socket.DisconnectTime = DateTime.UtcNow; var sub = new SocketConnection(client, socket); var rstEvent = new ManualResetEvent(false); string original = null; sub.AddSubscription(SocketSubscription.CreateForIdentifier(10, "TestHandler", true, (messageEvent) => { original = messageEvent.OriginalData; rstEvent.Set(); })); client.ConnectSocketSub(sub); // act socket.InvokeMessage("{\"property\": 123}"); rstEvent.WaitOne(1000); // assert Assert.IsTrue(original == (enabled ? "{\"property\": 123}" : null)); }
protected virtual SocketConnection ParibuGetWebsocket(string address, bool authenticated) { address = address.TrimEnd('/').Replace("{appid}", PusherApplicationId); var socketResult = sockets.Where(s => s.Value.Socket.Url.TrimEnd('/') == address.TrimEnd('/') && (s.Value.Authenticated == authenticated || !authenticated) && s.Value.Connected).OrderBy(s => s.Value.SubscriptionCount).FirstOrDefault(); var result = socketResult.Equals(default(KeyValuePair <int, SocketConnection>)) ? null : socketResult.Value; if (result != null) { if (result.SubscriptionCount < SocketCombineTarget || (sockets.Count >= MaxSocketConnections && sockets.All(s => s.Value.SubscriptionCount >= SocketCombineTarget))) { // Use existing socket if it has less than target connections OR it has the least connections and we can't make new return(result); } } // Create new socket var socket = CreateSocket(address); var socketConnection = new SocketConnection(this, socket); socketConnection.UnhandledMessage += HandleUnhandledMessage; foreach (var kvp in genericHandlers) { var handler = SocketSubscription.CreateForIdentifier(NextId(), kvp.Key, false, kvp.Value); socketConnection.AddSubscription(handler); } return(socketConnection); }
public void SocketMessages_Should_BeProcessedInDataHandlers() { // arrange var client = new TestSocketClient(new SocketClientOptions("") { ReconnectInterval = TimeSpan.Zero, LogLevel = LogLevel.Debug }); var socket = client.CreateSocket(); socket.ShouldReconnect = true; socket.CanConnect = true; socket.DisconnectTime = DateTime.UtcNow; var sub = new SocketConnection(client, socket); var rstEvent = new ManualResetEvent(false); JToken result = null; sub.AddSubscription(SocketSubscription.CreateForIdentifier(10, "TestHandler", true, (messageEvent) => { result = messageEvent.JsonData; rstEvent.Set(); })); client.ConnectSocketSub(sub); // act socket.InvokeMessage("{\"property\": 123}"); rstEvent.WaitOne(1000); // assert Assert.IsTrue((int)result["property"] == 123); }
protected virtual SocketConnection OkexGetSocketConnection(string address, bool authenticated) { address = authenticated ? "wss://ws.okx.com:8443/ws/v5/private" : "wss://ws.okx.com:8443/ws/v5/public"; if (DemoTradingService) { address = authenticated ? "wss://wspap.okx.com:8443/ws/v5/private?brokerId=9999" : "wss://wspap.okx.com:8443/ws/v5/public?brokerId=9999"; } var socketResult = sockets .Where(s => s.Value.Socket.Url.TrimEnd('/') == address.TrimEnd('/') && (s.Value.Authenticated == authenticated || !authenticated) && s.Value.Connected) .OrderBy(s => s.Value.SubscriptionCount) .FirstOrDefault(); var result = socketResult.Equals(default(KeyValuePair <int, SocketConnection>)) ? null : socketResult.Value; if (result != null) { if (result.SubscriptionCount < SocketCombineTarget || (sockets.Count >= MaxSocketConnections && sockets.All(s => s.Value.SubscriptionCount >= SocketCombineTarget))) { // Use existing socket if it has less than target connections OR it has the least connections and we can't make new return(result); } } // Create new socket var socket = CreateSocket(address); var socketConnection = new SocketConnection(this, socket); socketConnection.UnhandledMessage += HandleUnhandledMessage; foreach (var kvp in genericHandlers) { var handler = SocketSubscription.CreateForIdentifier(NextId(), kvp.Key, false, kvp.Value); socketConnection.AddSubscription(handler); } return(socketConnection); }
/// <inheritdoc /> protected override async Task <CallResult <UpdateSubscription> > SubscribeAsync <T>(string url, object?request, string?identifier, bool authenticated, Action <DataEvent <T> > dataHandler) { SocketConnection? socketConnection; SocketSubscription subscription; var released = false; await semaphoreSlim.WaitAsync().ConfigureAwait(false); try { socketConnection = GetSocketConnection(url, authenticated); if (socketConnection == null) { KucoinToken token; var clientOptions = KucoinClient.DefaultOptions.Copy(); KucoinApiCredentials?thisCredentials = (KucoinApiCredentials?)authProvider?.Credentials; if (thisCredentials != null) { clientOptions.FuturesApiCredentials = new KucoinApiCredentials(thisCredentials.Key !.GetString(), thisCredentials.Secret !.GetString(), thisCredentials.PassPhrase.GetString()); } // Create new socket IWebsocket socket; if (SocketFactory is WebsocketFactory) { using (var restClient = new KucoinClient(clientOptions)) { WebCallResult <KucoinToken> tokenResult = await((KucoinClientFutures)restClient.Futures).GetWebsocketToken(authenticated).ConfigureAwait(false); if (!tokenResult) { return(new CallResult <UpdateSubscription>(null, tokenResult.Error)); } token = tokenResult.Data; } socket = CreateSocket(token.Servers.First().Endpoint + "?token=" + token.Token); } else { socket = CreateSocket("test"); } socketConnection = new SocketConnection(this, socket); foreach (var kvp in genericHandlers) { socketConnection.AddSubscription(SocketSubscription.CreateForIdentifier(NextId(), kvp.Key, false, kvp.Value)); } } subscription = AddSubscription(request, identifier, true, socketConnection, dataHandler); if (SocketCombineTarget == 1) { // Can release early when only a single sub per connection semaphoreSlim.Release(); released = true; } var connectResult = await ConnectIfNeededAsync(socketConnection, authenticated).ConfigureAwait(false); if (!connectResult) { return(new CallResult <UpdateSubscription>(null, connectResult.Error)); } } finally { //When the task is ready, release the semaphore. It is vital to ALWAYS release the semaphore when we are ready, or else we will end up with a Semaphore that is forever locked. //This is why it is important to do the Release within a try...finally clause; program execution may crash or take a different path, this way you are guaranteed execution if (!released) { semaphoreSlim.Release(); } } if (request != null) { var subResult = await SubscribeAndWaitAsync(socketConnection, request, subscription).ConfigureAwait(false); if (!subResult) { await socketConnection.CloseAsync(subscription).ConfigureAwait(false); return(new CallResult <UpdateSubscription>(null, subResult.Error)); } } else { subscription.Confirmed = true; } socketConnection.ShouldReconnect = true; return(new CallResult <UpdateSubscription>(new UpdateSubscription(socketConnection, subscription), null)); }