// internal for testing
        internal async Task Reconnect(IConnection connection, string connectionData)
        {
            var reconnectUrl = UrlBuilder.BuildReconnect(connection, Name, connectionData);

            if (ConnectionState.Disconnected == connection.State || !_webSocket.IsConnected)
            {
                while (TransportHelper.VerifyLastActive(connection) && connection.EnsureReconnecting() && !_disconnectToken.IsCancellationRequested)
                {
                    try
                    {
                        await StartWebSocket(connection, reconnectUrl);

                        if (connection.ChangeState(ConnectionState.Reconnecting, ConnectionState.Connected))
                        {
                            connection.OnReconnected();
                        }

                        break;
                    }
                    catch (OperationCanceledException)
                    {
                        break;
                    }
                    catch (Exception ex)
                    {
                        connection.OnError(ex);
                    }
                    await Task.Delay(ReconnectDelay);
                }
            }
        }
        // fire and forget
        private async void DoReconnect()
        {
            var reconnectUrl = UrlBuilder.BuildReconnect(_connection, Name, _connectionData);

            while (TransportHelper.VerifyLastActive(_connection) && _connection.EnsureReconnecting())
            {
                try
                {
                    await Task.Delay(ReconnectDelay);
                    await PerformConnect(reconnectUrl);

                    break;
                }
                catch (OperationCanceledException)
                {
                    break;
                }
                catch (Exception ex)
                {
                    if (ExceptionHelper.IsRequestAborted(ex))
                    {
                        break;
                    }

                    _connection.OnError(ex);
                }
            }
        }
        private async Task DoReconnect()
        {
            var reconnectUrl = UrlBuilder.BuildReconnect(connection, Name, connectionData);

            while (TransportHelper.VerifyLastActive(connection))
            {
                if (connection.EnsureReconnecting())
                {
                    try
                    {
                        PerformConnect(reconnectUrl);
                        break;
                    }
                    catch (OperationCanceledException)
                    {
                        break;
                    }
                    catch (Exception ex)
                    {
                        connection.OnError(ex);
                    }
                    await Task.Delay(ReconnectDelay, CancellationToken.None).ConfigureAwait(false);
                }
                else
                {
                    break;
                }
            }
        }
Esempio n. 4
0
 /// <summary>
 /// Sets LastActiveAt to the current time
 /// </summary>
 void IConnection.MarkActive()
 {
     // Ensure that we haven't gone to sleep since our last "active" marking.
     if (TransportHelper.VerifyLastActive(this))
     {
         _lastActiveAt = DateTime.UtcNow;
     }
 }
Esempio n. 5
0
        public void AppendCustomQueryStringAppendsConnectionQueryString(string connectionQs, string expected)
        {
            var connection = new Connection("http://foo.com", connectionQs);

            var urlQs = TransportHelper.AppendCustomQueryString(connection, "http://foo.com");

            Assert.Equal(urlQs, expected);
        }
Esempio n. 6
0
        public void GetReceiveQueryStringAppendsConnectionQueryString(string connectionQs, string expected)
        {
            var connection = new Connection("http://foo.com", connectionQs);

            connection.ConnectionToken = "";

            var urlQs = TransportHelper.GetReceiveQueryString(connection, null, "");

            Assert.True(urlQs.EndsWith(expected));
        }
Esempio n. 7
0
        public void OnInitializedFiresFromInitializeMessage()
        {
            bool timedOut, disconnected, triggered = false;
            var  connection = new Connection("http://foo.com");

            TransportHelper.ProcessResponse(connection, "{\"S\":1, \"M\":[]}", out timedOut, out disconnected, () =>
            {
                triggered = true;
            });

            Assert.True(triggered);
        }
Esempio n. 8
0
        public void Abort(IConnection connection, TimeSpan timeout, string connectionData)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            // Save the connection.ConnectionToken since race issue that connection.ConnectionToken can be set to null in different thread
            var connectionToken = connection.ConnectionToken;

            if (connectionToken == null)
            {
                connection.Trace(TraceLevels.Messages, "Connection already disconnected, skipping abort.");
                return;
            }

            // Abort should never complete before any of its previous calls
            lock (_abortLock)
            {
                if (_disposed)
                {
                    return;
                }

                // Ensure that an abort request is only made once
                if (!_startedAbort)
                {
                    _startedAbort = true;

                    string url = connection.Url + "abort" + String.Format(CultureInfo.InvariantCulture,
                                                                          _abortQueryString,
                                                                          _transportName,
                                                                          connection.Protocol,
                                                                          connectionData,
                                                                          Uri.EscapeDataString(connectionToken),
                                                                          null);

                    url += TransportHelper.AppendCustomQueryString(connection, url);

                    _httpClient.Post(url, connection.PrepareRequest, isLongRunning: false).Catch((ex, state) =>
                    {
                        // If there's an error making an http request set the reset event
                        ((TransportAbortHandler)state).CompleteAbort();
                    },
                                                                                                 this);

                    if (!_abortResetEvent.WaitOne(timeout))
                    {
                        connection.Trace(TraceLevels.Events, "Abort never fired");
                    }
                }
            }
        }
        public void RollTargetLocality_AllInOneRealm_AlwaysFound()
        {
            var realm      = new Realm();
            var localities = new List <Locality>(Enumerable.Range(1, 10).Select(index => new Locality {
                Name = $"{index}", Owner = realm
            }));
            var dice = new LinearDice(1);

            for (var i = 0; i < 100; i++)
            {
                var targetLocality = TransportHelper.RollTargetLocality(localities, dice, realm, localities.First());
                targetLocality.Should().NotBeNull();
            }
        }
        public TransportInitializationHandler(IHttpClient httpClient,
                                              IConnection connection,
                                              string connectionData,
                                              string transport,
                                              CancellationToken disconnectToken,
                                              TransportHelper transportHelper)
        {
            if (connection == null)
            {
                throw new ArgumentNullException("connection");
            }

            _connection      = connection;
            _httpClient      = httpClient;
            _connectionData  = connectionData;
            _transport       = transport;
            _transportHelper = transportHelper;

            _initializationTask    = new DispatchingTaskCompletionSource <object>();
            _initializationInvoker = new ThreadSafeInvoker();

            // Default event
            OnFailure = () => { };

            // We want to fail if the disconnect token is tripped while we're waiting on initialization
            try
            {
                _tokenCleanup = disconnectToken.SafeRegister(
                    _ => Fail(new OperationCanceledException(Resources.Error_ConnectionCancelled, disconnectToken)),
                    state: null);
            }
            catch (ObjectDisposedException)
            {
                // We only dispose this token after cancelling it, so consider this cancellation.
                // The ODE is only thrown on .NET 4.5.2 and below (.NET 4.6 no longer throws ODE from CTS.Register)
                Fail(new OperationCanceledException(Resources.Error_ConnectionCancelled, disconnectToken));
            }

            TaskAsyncHelper.Delay(connection.TotalTransportConnectTimeout)
            .Then(() =>
            {
                // don't timeout once connect request has finished
                if (Interlocked.CompareExchange(ref _state, InitializationState.Failed, InitializationState.Initial) ==
                    InitializationState.Initial)
                {
                    Fail(new TimeoutException(Resources.Error_TransportTimedOutTryingToConnect));
                }
            });
        }
Esempio n. 11
0
        public void ProcessResponseCapturesOnReceivedExceptions()
        {
            bool timedOut, disconnected;
            var  ex         = new Exception();
            var  connection = new Mock <Client.IConnection>(MockBehavior.Strict);

            connection.Setup(c => c.OnReceived(It.IsAny <JToken>())).Throws(ex);
            connection.Setup(c => c.OnError(ex));
            connection.Setup(c => c.MarkLastMessage());

            // PersistentResponse
            TransportHelper.ProcessResponse(connection.Object, "{\"M\":{}}", out timedOut, out disconnected);

            // HubResponse (WebSockets)
            TransportHelper.ProcessResponse(connection.Object, "{\"I\":{}}", out timedOut, out disconnected);

            connection.VerifyAll();
        }