Пример #1
0
        /// <summary>
        /// Begins a Real Time Messaging API session and connects via a websocket.
        /// Will reconnect automatically.
        /// </summary>
        /// <param name="manualPresenceSubscription">Only deliver presence events when requested by subscription.</param>
        /// <param name="batchPresenceAware">Group presence change notices in <see cref="PresenceChange"/> events when possible.</param>
        /// <param name="cancellationToken"></param>
        public async Task <ConnectResponse> Connect(bool batchPresenceAware = false, bool manualPresenceSubscription = false, CancellationToken?cancellationToken = null)
        {
            if (Connected)
            {
                throw new InvalidOperationException("Already connecting or connected");
            }

            var connectResponse = await _client.Rtm.Connect(manualPresenceSubscription, batchPresenceAware, cancellationToken).ConfigureAwait(false);

            _webSocket?.Dispose();
            _webSocket = _webSocketFactory.Create(connectResponse.Url);

            var openedTask = _webSocket.Opened
                             .Merge(_webSocket.Errors.SelectMany(Observable.Throw <Unit>))
                             .FirstAsync()
                             .ToTask(cancellationToken);

            _webSocket.Open();
            await openedTask.ConfigureAwait(false);

            _eventSubscription?.Dispose();
            _eventSubscription = _webSocket.Messages
                                 .Select(m => JsonConvert.DeserializeObject <Event>(m, _jsonSettings.SerializerSettings))
                                 .Subscribe(_rawEvents);

            _reconnection?.Dispose();
            _reconnection = _webSocket.Closed
                            .SelectMany(_ => Observable.FromAsync(() => Connect(batchPresenceAware, manualPresenceSubscription, cancellationToken), _scheduler)
                                        .RetryWithDelay(TimeSpan.FromSeconds(1), TimeSpan.FromSeconds(5), TimeSpan.FromMinutes(5), _scheduler))
                            .Subscribe();

            return(connectResponse);
        }
Пример #2
0
 /// <summary>
 /// Releases unmanaged and - optionally - managed resources.
 /// </summary>
 /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
 protected virtual void Dispose(bool dispose)
 {
     if (dispose)
     {
         _socket.Dispose();
     }
 }
Пример #3
0
        /// <inheritdoc />
        public virtual async Task Connect()
        {
            if (Socket != null)
            {
                throw new JsonRpcAlreadyConnectedException();
            }

            Socket?.Dispose();
            RequestMgr.Reset();

            ReceiveCancellationTokenSource = new CancellationTokenSource();

            if (Logger?.IsEnabled(LogEventLevel.Information) ?? false)
            {
                Logger.Information("Connecting to {Host}", ServerUri);
            }

            Socket = WebSocketFactory.Create();
            try
            {
                await Socket.ConnectAsync(ServerUri, CancellationToken.None).ConfigureAwait(false);
            }
            catch (Exception ex)
            {
                Logger?.Error(ex, "Exception during ConnectAsync");
                Socket.Dispose();
                Socket = null;
                throw;
            }

            InternalOnConnected();
        }
        private static void RunOrderBookWebSocket(Dictionary <string, string> dict)
        {
            RequireArgs(dict, "exchangeName");
            var api = ExchangeAPI.GetExchangeAPI(dict["exchangeName"]);

            if (api == null)
            {
                throw new ArgumentException("Cannot find exchange with name {0}", dict["exchangeName"]);
            }
            var apiSymbols = api.GetSymbols();

            string[] symbols = dict["symbols"].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);
            foreach (string symbol in symbols)
            {
                if (!apiSymbols.Contains(symbol))
                {
                    throw new ArgumentException(string.Format("Symbol {0} does not exist in API {1}, valid symbols: {2}", symbol, api.Name, string.Join(",", apiSymbols.OrderBy(s => s))));
                }
            }

            IWebSocket socket = api.GetOrderBookWebSocket(message =>
            {
                //print the top bid and ask with amount
                var topBid = message.Bids.FirstOrDefault();
                var topAsk = message.Asks.FirstOrDefault();
                Console.WriteLine($"[{message.Symbol}:{message.SequenceId}] {topBid.Value.Price} ({topBid.Value.Amount}) | {topAsk.Value.Price} ({topAsk.Value.Amount})");
            }, symbols: symbols);

            Console.WriteLine("Press any key to quit.");
            SetWebSocketEvents(socket);
            Console.ReadKey();
            socket.Dispose();
        }
Пример #5
0
 /// <summary>
 /// Releases unmanaged and - optionally - managed resources.
 /// </summary>
 /// <param name="dispose"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
 protected virtual void Dispose(bool dispose)
 {
     if (dispose)
     {
         _cancellationTokenSource.Dispose();
         _socket.Dispose();
     }
 }
Пример #6
0
        public void TestDisposeWebSocket()
        {
            WebSocketJetConnection webSocketJetConnection = new WebSocketJetConnection("ws://172.19.191.179:8081");
            IWebSocket             webSocket = A.Fake <IWebSocket>();

            webSocketJetConnection.SetWebSocket(webSocket);

            webSocketJetConnection.Dispose();

            A.CallTo(() => webSocket.Dispose()).MustHaveHappened(Repeated.Exactly.Once);
        }
Пример #7
0
        //public List<IWebSocket> this[string metadata]
        //{
        //    get
        //    {
        //        if (clientsByMetadata.ContainsKey(metadata))
        //        {
        //            return clientsByMetadata[metadata];
        //        }

        //        return new List<IWebSocket>();
        //    }
        //}

        private void OnHandShaken(IWebSocket webSocket, ClientHandshake clientHandshake)
        {
            var handler = handlerFactory.Create(clientHandshake.ResourceName);

            if (handler != null)
            {
                webSocket.Received     = handler.Received;
                webSocket.Disconnected = sender =>
                {
                    var found = clientsByMetadata.FirstOrDefault(kv => kv.Value.Exists(ws => ws == sender));
                    if (found.Value != null)
                    {
                        found.Value.Remove((WebSocket)sender);
                        if (!found.Value.Any())
                        {
                            clientsByMetadata.Remove(found.Key);
                        }
                        // A web socket with the metaData has been disconnected from the server
                        handler.Disconnected(found.Key);
                    }
                };
                webSocket.Error = handler.Error;

                var metadata = GetMetadata(clientHandshake, webSocket);

                // A web socket with the metaData has been connected to the server
                handler.Connected(metadata);

                if (!clientsByMetadata.ContainsKey(metadata))
                {
                    clientsByMetadata.Add(metadata, new List <IWebSocket> {
                        webSocket
                    });
                }
                else
                {
                    //clientsByMetaData[metaData].Dispose();
                    clientsByMetadata[metadata].Add(webSocket);
                }

                // Begin receiving data from the client
                webSocket.ReceiveAsync();
            }
            else
            {
                if (Log.IsDebugEnabled)
                {
                    Log.Debug("There was no handler found for the resource name");
                }
                // If nothing is handling client connections
                // the client connection should be closed
                webSocket.Dispose();
            }
        }
Пример #8
0
#pragma warning disable S3241 // Methods should not return values that are never used
        private async Task StartListening(CancellationToken cancellationToken = default)
#pragma warning restore S3241 // Methods should not return values that are never used
        {
            try
            {
                while (webSocket.State == WebSocketState.Open)
                {
                    logger?.LogDebug("Waiting for new message");
                    var message = await ReadNextMessage(cancellationToken);

                    logger?.LogDebug("Received new message from websocket");
                    logger?.LogTrace("Received: '{message}'", message);

                    string eventString = null;
                    int?   channelId   = null;

                    if (!string.IsNullOrEmpty(message))
                    {
                        var token = JToken.Parse(message);
                        switch (token)
                        {
                        case JObject _:
                            var messageObj = JObject.Parse(message);
                            eventString = (string)messageObj.GetValue("event");
                            break;

                        case JArray arrayToken:
                            // Data / private messages
                            if (int.TryParse(arrayToken.First.ToString(), out var localChannelId))
                            {
                                channelId = localChannelId;
                            }

                            eventString = channelId != null ? "data" : "private";
                            break;
                        }

                        InvokeDataReceived(new KrakenMessageEventArgs(eventString, message, channelId));
                    }
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex, "Error while listening or reading new messages from WebSocket");
                // TODO: Disconnected-Event
                throw;
            }
            finally
            {
                logger?.LogInformation("Closing WebSocket");
                webSocket.Dispose();
            }
        }
Пример #9
0
        public void TestDisposeClosesWebSocketIfConnected()
        {
            WebSocketJetConnection webSocketJetConnection = new WebSocketJetConnection("ws://172.19.191.179:8081");
            IWebSocket             webSocket = WebSocketFakesFactory.CreateWebSocketThatConnectsAndClosesSuccessful();

            webSocketJetConnection.SetWebSocket(webSocket);
            webSocketJetConnection.Connect(A.Dummy <Action <bool> >(), 1000.0);

            webSocketJetConnection.Dispose();

            A.CallTo(() => webSocket.Close(CloseStatusCode.Away)).MustHaveHappened(Repeated.Exactly.Once).Then(
                A.CallTo(() => webSocket.Dispose()).MustHaveHappened(Repeated.Exactly.Once));
        }
Пример #10
0
        public void Dispose()
        {
            if (!_disposed)
            {
                _disposed = true;
                _webSocket.Dispose();

                foreach (ISubscription subscription in _subscriptions.Values)
                {
                    subscription.Dispose();
                }

                _subscriptions.Clear();
            }
        }
Пример #11
0
        // This may be triggered remotely by the server or locally by Close/Dispose()
        private void Closed(IWebSocket sender, WebSocketClosedEventArgs args)
        {
            if (sender != null)
            {
                sender.Dispose();

                // Distroy keepalive timer before close connection
                if (_timer != null)
                {
                    _timer.Cancel();
                    _timer = null;
                }

                CoreApplication.Properties.Remove("connected");
                CoreApplication.Properties.Remove("clientSocket");
            }
        }
Пример #12
0
        protected async Task RunWebSocket(string exchangeName, Func <IExchangeAPI, Task <IWebSocket> > getWebSocket)
        {
            using var api = ExchangeAPI.GetExchangeAPI(exchangeName);

            Console.WriteLine("Connecting web socket to {0}...", api.Name);

            IWebSocket socket = null;
            var        tcs    = new TaskCompletionSource <bool>();

            // ReSharper disable once AccessToModifiedClosure
            var disposable = KeepSessionAlive(() =>
            {
                socket?.Dispose();
                tcs.TrySetResult(true);
            });

            try
            {
                socket = await getWebSocket(api);

                socket.Connected += _ =>
                {
                    Console.WriteLine("Web socket connected.");
                    return(Task.CompletedTask);
                };
                socket.Disconnected += _ =>
                {
                    Console.WriteLine("Web socket disconnected.");

                    // ReSharper disable once AccessToDisposedClosure
                    disposable.Dispose();

                    return(Task.CompletedTask);
                };

                await tcs.Task;
            }
            catch
            {
                disposable.Dispose();
                throw;
            }
        }
        /// <summary>
        /// Implement <see cref="IDisposable"/> pattern for inheritable classes.
        /// </summary>
        /// <param name="disposing">If <c>true</c> - dispose managed objects.</param>
        protected virtual void Dispose(
            Boolean disposing)
        {
            if (!disposing ||
                _webSocket == null)
            {
                return;
            }

            _webSocket.Opened -= OnOpened;
            _webSocket.Closed -= OnClosed;

            _webSocket.MessageReceived -= OnMessageReceived;
            _webSocket.DataReceived    -= OnDataReceived;

            _webSocket.Error -= HandleError;

            _webSocket.Dispose();
        }
        private static void RunTradesWebSocket(Dictionary <string, string> dict)
        {
            RequireArgs(dict, "exchangeName");
            var api = ExchangeAPI.GetExchangeAPI(dict["exchangeName"]);

            if (api == null)
            {
                throw new ArgumentException("Cannot find exchange with name {0}", dict["exchangeName"]);
            }

            string[] symbols = dict["symbols"].Split(",".ToCharArray(), StringSplitOptions.RemoveEmptyEntries);

            IWebSocket socket = api.GetTradesWebSocket(message =>
            {
                Console.WriteLine($"{message.Key}: {message.Value}");
            }, symbols: symbols);

            Console.WriteLine("Press any key to quit.");
            SetWebSocketEvents(socket);
            Console.ReadKey();
            socket.Dispose();
        }
Пример #15
0
#pragma warning disable S3241 // Methods should not return values that are never used
        private async Task StartListening(CancellationToken cancellationToken = default)
#pragma warning restore S3241 // Methods should not return values that are never used
        {
            try
            {
                while (webSocket.State == WebSocketState.Open)
                {
                    logger?.LogDebug("Waiting for new message");
                    var message = await ReadNextMessage(cancellationToken);

                    logger?.LogDebug("Received new message from websocket");
                    logger?.LogTrace("Received: '{message}'", message);

                    string eventString = null;
                    int?   channelId   = null;

                    if (!string.IsNullOrEmpty(message))
                    {
                        var token = JToken.Parse(message);
                        switch (token)
                        {
                        case JObject _:
                            var messageObj = JObject.Parse(message);
                            eventString = (string)messageObj.GetValue("event");
                            break;

                        case JArray arrayToken:
                            // Data / private messages
                            if (int.TryParse(arrayToken.First.ToString(), out var localChannelId))
                            {
                                channelId = localChannelId;
                            }

                            eventString = channelId != null ? "data" : "private";
                            break;
                        }

                        InvokeDataReceived(new KrakenMessageEventArgs(eventString, message, channelId));
                    }
                }
            }
            catch (Exception ex)
            {
                logger?.LogError(ex, "Error while listening or reading new messages from WebSocket");
            }
            finally
            {
                logger?.LogInformation("Closing WebSocket");
                webSocket.Dispose();
            }
#if false
            //reconnect
            while (true)
            {
                logger?.LogInformation("Attempting reconnect..");
                await Task.Delay(1 * 1000);

                webSocket = new DefaultWebSocket(new ClientWebSocket());
                try
                {
                    await ConnectAsync();

                    await Task.Delay(1 * 1000);

                    var ev = ReConnected;
                    if (ev != null)
                    {
                        InvokeAllHandlers(ev.GetInvocationList(), null);
                    }
                    return;
                }
                catch
                {
                    try { webSocket.Dispose(); } catch { }
                    await Task.Delay(20 * 1000);
                }
                await Task.Delay(10 * 1000);
            }
#endif
        }