Esempio n. 1
0
        private void SocketOnClose(CoinExStream stream)
        {
            log.Write(LogVerbosity.Debug, $"Socket {stream.StreamResult.StreamId} closed event");
            if (stream.TryReconnect)
            {
                log.Write(LogVerbosity.Info, $"Socket {stream.StreamResult.StreamId} Connection lost, going to try to reconnect");
                Task.Run(() =>
                {
                    Thread.Sleep(reconnectInterval);
                    if (!stream.Socket.Connect().Result)
                    {
                        log.Write(LogVerbosity.Debug, $"Socket {stream.StreamResult.StreamId} failed to reconnect");
                        return; // Connect() should result in a SocketClosed event so we end up here again
                    }

                    log.Write(LogVerbosity.Info, $"Socket {stream.StreamResult.StreamId} Reconnected");
                    if (stream.Request != null)
                    {
                        var resubResult = Subscribe(stream, stream.Request, true).Result;
                        if (!resubResult.Success)
                        {
                            log.Write(LogVerbosity.Info, $"Socket {stream.StreamResult.StreamId} failed to resubscribe, closing socket and trying again");
                            stream.Close(true).Wait();
                        }
                        else
                        {
                            log.Write(LogVerbosity.Info, $"Socket {stream.StreamResult.StreamId} resubscribed reconnected socket");
                        }
                    }
                });
            }
            else
            {
                log.Write(LogVerbosity.Info, $"Socket {stream.StreamResult.StreamId} closed");
                lock (subscriptions)
                    if (subscriptions.Contains(stream.Subscription))
                    {
                        subscriptions.Remove(stream.Subscription);
                    }
                stream.StreamResult.InvokeClosed();
                stream.Socket.Dispose();
                lock (sockets)
                    sockets.Remove(stream);
            }
        }
Esempio n. 2
0
        private async Task <CallResult <CoinExStreamSubscription> > Subscribe(CoinExStream stream, CoinExSocketRequest request, bool resubscribing)
        {
            if (stream.Authenticated)
            {
                var auth = await Authenticate(stream).ConfigureAwait(false);

                if (!auth.Success)
                {
                    return(new CallResult <CoinExStreamSubscription>(null, auth.Error));
                }
            }

            if (!resubscribing) // Only add the message handler once, is already done if resubscribing
            {
                stream.Socket.OnMessage += (msg) => OnMessage(stream.StreamResult.StreamId, msg);
            }

            var subConfirm = await Query <CoinExSocketRequestResponseMessage>(stream, request).ConfigureAwait(false);

            if (subConfirm.Success)
            {
                stream.Request = request;
                stream.Subscription.StreamId = stream.StreamResult.StreamId;
                stream.TryReconnect          = true;
                lock (subscriptions)
                    if (!subscriptions.Contains(stream.Subscription))
                    {
                        subscriptions.Add(stream.Subscription);
                    }
                log.Write(LogVerbosity.Info, $"Subscription {stream.Subscription.StreamId} successful");
            }
            else
            {
                log.Write(LogVerbosity.Info, $"Failed to subscribe {stream.Subscription.StreamId}: {subConfirm.Error}");
                if (!resubscribing) // If we're just trying to initialy subscribe we dont need to reconnect if we failed subbing, so close it here
                {
                    await stream.Close().ConfigureAwait(false);
                }
            }

            return(new CallResult <CoinExStreamSubscription>(stream.StreamResult, subConfirm.Error));
        }
Esempio n. 3
0
        private CallResult <CoinExStream> ConnectNewSocket()
        {
            var socket = SocketFactory.CreateWebsocket(log, baseAddress);

            log.Write(LogVerbosity.Debug, "Created new socket");
            var id     = NextStreamId();
            var stream = new CoinExStream()
            {
                Socket = socket, StreamResult = new CoinExStreamSubscription()
                {
                    StreamId = id
                }
            };

            if (apiProxy != null)
            {
                socket.SetProxy(apiProxy.Host, apiProxy.Port);
            }

            socket.SetEnabledSslProtocols(protocols);

            socket.OnClose += () => SocketOnClose(stream);
            socket.OnError += SocketOnError;
            socket.OnError += stream.StreamResult.InvokeError;
            socket.OnOpen  += SocketOnOpen;

            if (socket.Connect().Result)
            {
                lock (sockets)
                    sockets.Add(stream);
                return(new CallResult <CoinExStream>(stream, null));
            }

            socket.Dispose();
            return(new CallResult <CoinExStream>(null, new CantConnectError()));
        }
Esempio n. 4
0
        private async Task <CallResult <bool> > Authenticate(CoinExStream stream)
        {
            if (authProvider == null)
            {
                return(new CallResult <bool>(false, new NoApiCredentialsError()));
            }

            var result = await Query <CoinExSocketRequestResponseMessage>(stream, new CoinExSocketRequest(ServerSubject, AuthenticateAction, GetAuthParameters())).ConfigureAwait(false);

            if (!result.Success)
            {
                log.Write(LogVerbosity.Debug, "Failed to authenticate: " + result.Error);
                return(new CallResult <bool>(false, result.Error));
            }

            if (result.Data.Status != SuccessString)
            {
                log.Write(LogVerbosity.Debug, "Failed to authenticate: " + result.Data.Status);
                return(new CallResult <bool>(false, new ServerError(result.Data.Status)));
            }

            log.Write(LogVerbosity.Debug, "Successfully authenticated");
            return(new CallResult <bool>(true, null));
        }
Esempio n. 5
0
        private async Task <CallResult <T> > Query <T>(CoinExStream stream, CoinExSocketRequest request)
        {
            return(await Task.Run(() =>
            {
                log.Write(LogVerbosity.Debug, $"Querying socket {stream.Subscription.StreamId} for {request.Method}");
                ManualResetEvent evnt = new ManualResetEvent(false);
                CallResult <CoinExSocketRequestResponse <T> > result = null;
                request.Id = NextRequestId();
                var onMessageAction = new Action <string>((msg) =>
                {
                    log.Write(LogVerbosity.Debug, "Socket received query response: " + msg);

                    var token = JToken.Parse(msg);
                    if ((int?)token["id"] != request.Id)
                    {
                        return;
                    }

                    if (token["error"].Type == JTokenType.Null)
                    {
                        result = Deserialize <CoinExSocketRequestResponse <T> >(msg);
                    }
                    else
                    {
                        var errorResult = Deserialize <CoinExSocketError>(token["error"].ToString());
                        if (!errorResult.Success)
                        {
                            result = new CallResult <CoinExSocketRequestResponse <T> >(null, new ServerError("Unknown error: " + token["error"]));
                        }
                        else
                        {
                            result = new CallResult <CoinExSocketRequestResponse <T> >(null, new ServerError(errorResult.Data.Code, errorResult.Data.Message));
                        }
                    }

                    evnt?.Set();
                });

                stream.Socket.OnMessage += onMessageAction;
                var data = JsonConvert.SerializeObject(request);
                log.Write(LogVerbosity.Debug, "Sending data: " + data);
                stream.Socket.Send(data);
                evnt.WaitOne(subResponseTimeout);
                stream.Socket.OnMessage -= onMessageAction;
                evnt.Dispose();
                evnt = null;
                if (result == null)
                {
                    return new CallResult <T>(default(T), new ServerError("No response from server"));
                }
                if (!result.Success)
                {
                    return new CallResult <T>(default(T), result.Error);
                }
                if (result.Data.Error != null)
                {
                    return new CallResult <T>(default(T), new ServerError(result.Data.Error.Code, result.Data.Error.Message));
                }

                return new CallResult <T>(result.Data.Result, null);
            }).ConfigureAwait(false));
        }