// 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; } } }
/// <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; } }
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); }
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)); }
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); }
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)); } }); }
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(); }