private void OnSnapshot(BitfinexWebSocketWrapper webSocket, int channelId, string[][] entries)
        {
            try
            {
                Channel channel;

                lock (_locker)
                {
                    BitfinexWebSocketChannels channels;
                    if (!_channelsByWebSocket.TryGetValue(webSocket, out channels))
                    {
                        return;
                    }

                    if (!channels.TryGetValue(channelId, out channel))
                    {
                        _brokerage.OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, -1, $"Message received from unknown channel Id {channelId}"));
                        return;
                    }
                }

                switch (channel.Name.ToLowerInvariant())
                {
                case "book":
                    ProcessOrderBookSnapshot(channel, entries);
                    return;
                }
            }
            catch (Exception e)
            {
                Log.Error(e);
                throw;
            }
        }
예제 #2
0
        private void OnUnsubscribe(BitfinexWebSocketWrapper webSocket, Messages.ChannelUnsubscribing data)
        {
            try
            {
                lock (_locker)
                {
                    List <BitfinexChannel> channels;
                    if (!_channelsByWebSocket.TryGetValue(webSocket, out channels))
                    {
                        return;
                    }

                    channels.Remove(channels.First(x => x.ChannelId == data.ChannelId));

                    if (channels.Count != 0)
                    {
                        return;
                    }

                    _channelsByWebSocket.TryRemove(webSocket, out channels);
                }

                webSocket.Close();
                webSocket.ConnectionHandler.DisposeSafely();
            }
            catch (Exception e)
            {
                Log.Error(e);
                throw;
            }
        }
        private void OnSubscribe(BitfinexWebSocketWrapper webSocket, ChannelSubscription data)
        {
            try
            {
                lock (_locker)
                {
                    var channel = new Channel(data.Channel, _symbolMapper.GetLeanSymbol(data.Symbol, SecurityType.Crypto, Market.Bitfinex));

                    BitfinexWebSocketChannels channels;
                    if (!_channelsByWebSocket.TryGetValue(webSocket, out channels))
                    {
                        _onSubscribeEvent.Set();
                        return;
                    }

                    channels.TryAdd(data.ChannelId, channel);

                    Log.Trace($"BitfinexSubscriptionManager.OnSubscribe(): Channel subscribed: Id:{data.ChannelId} {channel.Symbol}/{channel.Name}");

                    _onSubscribeEvent.Set();

                    webSocket.ConnectionHandler.EnableMonitoring(true);
                }
            }
            catch (Exception e)
            {
                Log.Error(e);
                throw;
            }
        }
        private void OnReconnectRequested(object sender, EventArgs e)
        {
            var connectionHandler = (DefaultConnectionHandler)sender;

            Log.Trace($"BitfinexSubscriptionManager.OnReconnectRequested(): WebSocket reconnection requested [Id: {connectionHandler.ConnectionId}]");

            BitfinexWebSocketWrapper webSocket = null;

            lock (_locker)
            {
                webSocket = _channelsByWebSocket.Keys
                            .FirstOrDefault(connection => connection.ConnectionId == connectionHandler.ConnectionId);
            }

            if (webSocket == null)
            {
                Log.Error($"BitfinexSubscriptionManager.OnReconnectRequested(): WebSocket ConnectionId not found: {connectionHandler.ConnectionId}");
                return;
            }

            Log.Trace($"BitfinexSubscriptionManager.OnReconnectRequested(): IsOpen:{webSocket.IsOpen} [Id: {connectionHandler.ConnectionId}]");

            if (!webSocket.IsOpen)
            {
                Log.Trace($"BitfinexSubscriptionManager.OnReconnectRequested(): Websocket connecting. [Id: {connectionHandler.ConnectionId}]");
                webSocket.Connect();
            }

            if (!webSocket.IsOpen)
            {
                Log.Trace($"BitfinexSubscriptionManager.OnReconnectRequested(): Websocket not open: IsOpen:{webSocket.IsOpen} [Id: {connectionHandler.ConnectionId}]");
                return;
            }

            Log.Trace($"BitfinexSubscriptionManager.OnReconnectRequested(): Reconnected: IsOpen:{webSocket.IsOpen} [Id: {connectionHandler.ConnectionId}]");

            BitfinexWebSocketChannels channels;

            lock (_locker)
            {
                if (!_channelsByWebSocket.TryGetValue(webSocket, out channels))
                {
                    return;
                }
            }

            Log.Trace($"BitfinexSubscriptionManager.OnReconnectRequested(): Resubscribing channels. [Id: {connectionHandler.ConnectionId}]");

            foreach (var channel in channels.Values)
            {
                webSocket.Send(JsonConvert.SerializeObject(new
                {
                    @event  = "subscribe",
                    channel = channel.Name,
                    pair    = _symbolMapper.GetBrokerageSymbol(channel.Symbol)
                }));
            }
        }
예제 #5
0
        private BitfinexWebSocketWrapper GetFreeWebSocket(BitfinexChannel channel)
        {
            int count;

            lock (_locker)
            {
                foreach (var kvp in _channelsByWebSocket)
                {
                    if (kvp.Value.Count < MaximumSubscriptionsPerSocket)
                    {
                        kvp.Value.Add(channel);

                        count = _channelsByWebSocket.Sum(x => x.Value.Count);
                        Log.Trace($"BitfinexSubscriptionManager.GetFreeWebSocket(): Channel added: Total channels:{count}");

                        return(kvp.Key);
                    }
                }
            }

            if (!_connectionRateLimiter.WaitToProceed(TimeSpan.Zero))
            {
                _connectionRateLimiter.WaitToProceed();
            }

            var webSocket = new BitfinexWebSocketWrapper(
                new DefaultConnectionHandler
            {
                MaximumIdleTimeSpan = TimeSpan.FromSeconds(15)
            });

            lock (_locker)
            {
                _channelsByWebSocket.TryAdd(webSocket, new List <BitfinexChannel> {
                    channel
                });

                count = _channelsByWebSocket.Sum(x => x.Value.Count);
                Log.Trace($"BitfinexSubscriptionManager.GetFreeWebSocket(): Channel added: Total channels:{count}");
            }

            webSocket.Initialize(_wssUrl);
            webSocket.Message += OnMessage;
            webSocket.Error   += OnError;

            Connect(webSocket);

            webSocket.ConnectionHandler.ConnectionLost     += OnConnectionLost;
            webSocket.ConnectionHandler.ConnectionRestored += OnConnectionRestored;
            webSocket.ConnectionHandler.ReconnectRequested += OnReconnectRequested;
            webSocket.ConnectionHandler.Initialize(webSocket.ConnectionId);

            Log.Trace("BitfinexSubscriptionManager.GetFreeWebSocket(): New websocket added: " +
                      $"Hashcode: {webSocket.GetHashCode()}, " +
                      $"WebSocket connections: {_channelsByWebSocket.Count}");

            return(webSocket);
        }
예제 #6
0
        private void OnUnsubscribe(BitfinexWebSocketWrapper webSocket, Messages.ChannelUnsubscribing data)
        {
            try
            {
                lock (_locker)
                {
                    Channel channel;
                    if (!_channels.TryRemove(data.ChannelId, out channel))
                    {
                        return;
                    }

                    _onUnsubscribeEvent.Set();

                    List <Channel> channels;
                    if (!_channelsByWebSocket.TryGetValue(webSocket, out channels))
                    {
                        return;
                    }

                    channels.Remove(channel);

                    if (channels.Count(c => c.Symbol.Equals(channel.Symbol)) == 0)
                    {
                        List <BitfinexWebSocketWrapper> subscriptions;
                        if (_subscriptionsBySymbol.TryGetValue(channel.Symbol, out subscriptions))
                        {
                            subscriptions.Remove(webSocket);

                            if (subscriptions.Count == 0)
                            {
                                _subscriptionsBySymbol.TryRemove(channel.Symbol, out subscriptions);
                            }
                        }
                    }

                    if (channels.Count != 0)
                    {
                        return;
                    }

                    _channelsByWebSocket.TryRemove(webSocket, out channels);
                }

                webSocket.Close();
                webSocket.ConnectionHandler.DisposeSafely();
            }
            catch (Exception e)
            {
                Log.Error(e);
                throw;
            }
        }
        private BitfinexWebSocketWrapper GetFreeWebSocket(Channel channel)
        {
            lock (_locker)
            {
                foreach (var kvp in _channelsByWebSocket)
                {
                    if (kvp.Value.Count < MaximumSubscriptionsPerSocket)
                    {
                        return(kvp.Key);
                    }
                }
            }

            if (!_connectionRateLimiter.WaitToProceed(TimeSpan.Zero))
            {
                _connectionRateLimiter.WaitToProceed();
            }

            var webSocket = new BitfinexWebSocketWrapper(
                new DefaultConnectionHandler
            {
                MaximumIdleTimeSpan = TimeSpan.FromSeconds(15)
            });

            lock (_locker)
            {
                _channelsByWebSocket.TryAdd(webSocket, new BitfinexWebSocketChannels());
            }

            webSocket.Initialize(_wssUrl);
            webSocket.Message += OnMessage;

            Connect(webSocket);

            webSocket.ConnectionHandler.ReconnectRequested += OnReconnectRequested;
            webSocket.ConnectionHandler.Initialize(webSocket.ConnectionId);

            int connections;

            lock (_locker)
            {
                connections = _channelsByWebSocket.Count;
            }

            Log.Trace("BitfinexSubscriptionManager.GetFreeWebSocket(): New websocket added: " +
                      $"Hashcode: {webSocket.GetHashCode()}, " +
                      $"WebSocket connections: {connections}");

            return(webSocket);
        }
예제 #8
0
        private void OnSubscribe(BitfinexWebSocketWrapper webSocket, Messages.ChannelSubscription data)
        {
            try
            {
                lock (_locker)
                {
                    var channel = new Channel(data.Channel, _symbolMapper.GetLeanSymbol(data.Symbol));

                    _channels.AddOrUpdate(data.ChannelId, channel);
                    _onSubscribeEvent.Set();

                    webSocket.ConnectionHandler.EnableMonitoring(true);
                }
            }
            catch (Exception e)
            {
                Log.Error(e);
                throw;
            }
        }
예제 #9
0
        private void OnUpdate(BitfinexWebSocketWrapper webSocket, string channelId, string[] entries)
        {
            try
            {
                BitfinexChannel channel;

                lock (_locker)
                {
                    List <BitfinexChannel> channels;
                    if (!_channelsByWebSocket.TryGetValue(webSocket, out channels))
                    {
                        _brokerage.OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, -1, $"Message received from unknown channel Id {channelId}"));
                        return;
                    }

                    channel = channels.FirstOrDefault(x => x.ChannelId == channelId);
                    if (channel == null)
                    {
                        _brokerage.OnMessage(new BrokerageMessageEvent(BrokerageMessageType.Warning, -1, $"Message received from unknown channel Id {channelId}"));
                        return;
                    }
                }

                switch (channel.Name.ToLowerInvariant())
                {
                case "book":
                    ProcessOrderBookUpdate(channel, entries);
                    return;

                case "trades":
                    ProcessTradeUpdate(channel, entries);
                    return;
                }
            }
            catch (Exception e)
            {
                Log.Error(e);
                throw;
            }
        }
예제 #10
0
        private void OnSubscribe(BitfinexWebSocketWrapper webSocket, Messages.ChannelSubscription data)
        {
            try
            {
                lock (_locker)
                {
                    List <BitfinexChannel> channels;
                    if (_channelsByWebSocket.TryGetValue(webSocket, out channels))
                    {
                        var channel = channels.First(x => x.Name == data.Channel && x.Symbol == data.Symbol);

                        channel.ChannelId = data.ChannelId;

                        webSocket.ConnectionHandler.EnableMonitoring(true);
                    }
                }
            }
            catch (Exception e)
            {
                Log.Error(e);
                throw;
            }
        }