/// <summary> /// Initializes a new instance of the <see cref="Connection"/> class. /// </summary> /// <param name="url">The url to connect to.</param> /// <param name="queryString">The query string data to pass to the server.</param> public Connection(string url, string queryString) { if (url == null) { throw new ArgumentNullException("url"); } if (url.Contains("?")) { throw new ArgumentException(String.Format(CultureInfo.CurrentCulture, Resources.Error_UrlCantContainQueryStringDirectly), "url"); } if (!url.EndsWith("/", StringComparison.Ordinal)) { url += "/"; } Url = url; QueryString = queryString; _groups = new HashSet <string>(); Items = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase); State = ConnectionState.Disconnected; _disconnectCts = new SafeCancellationTokenSource(); _disconnectTimeoutOperation = DisposableAction.Empty; }
protected virtual void InitializePersistentState() { _hostShutdownToken = _context.Environment.GetShutdownToken(); _requestLifeTime = new HttpRequestLifeTime(this, WriteQueue, Trace, ConnectionId); // Create the TCS that completes when the task returned by PersistentConnection.OnConnected does. _connectTcs = new TaskCompletionSource <object>(); // Create a token that represents the end of this connection's life _connectionEndTokenSource = new SafeCancellationTokenSource(); _connectionEndToken = _connectionEndTokenSource.Token; // Handle the shutdown token's callback so we can end our token if it trips _hostRegistration = _hostShutdownToken.SafeRegister(state => { ((SafeCancellationTokenSource)state).Cancel(); }, _connectionEndTokenSource); // When the connection ends release the request _connectionEndRegistration = CancellationToken.SafeRegister(state => { ((HttpRequestLifeTime)state).Complete(); }, _requestLifeTime); }
public IReadOnlyList <Activity> GetActivities(IObservable <Activity> observable) { var cancellationToken = new SafeCancellationTokenSource(); var activityObserver = new GitHubActivityObserver(_logger, cancellationToken, _lastObservation); observable.Subscribe(activityObserver, cancellationToken.Token); cancellationToken.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(5)); var observedActivities = activityObserver.ObservedActivities; if (observedActivities.Count > 0) { foreach (var observedActivity in observedActivities) { if (observedActivity.CreatedAt > _lastObservation) { _lastObservation = observedActivity.CreatedAt; } } _lastObservation = _lastObservation.AddMilliseconds(1); } return(activityObserver.ObservedActivities); }
public Task <IClientResponse> ProcessRequest(string url, Action <IClientRequest> prepareRequest, Dictionary <string, string> postData, bool disableWrites) { if (url == null) { throw new ArgumentNullException("url"); } if (prepareRequest == null) { throw new ArgumentNullException("prepareRequest"); } var uri = new Uri(url); PersistentConnection connection; if (!_shutDownToken.IsCancellationRequested && TryGetConnection(uri.LocalPath, out connection)) { var tcs = new TaskCompletionSource <IClientResponse>(); var clientTokenSource = new SafeCancellationTokenSource(); var request = new Request(uri, clientTokenSource.Cancel, postData, User); prepareRequest(request); Response response = null; response = new Response(clientTokenSource.Token, () => tcs.TrySetResult(response)) { DisableWrites = disableWrites }; var hostContext = new HostContext(request, response); hostContext.Items[HostConstants.ShutdownToken] = _shutDownTokenSource.Token; connection.Initialize(DependencyResolver, hostContext); connection.ProcessRequestAsync(hostContext).ContinueWith(task => { if (task.IsFaulted) { tcs.TrySetException(task.Exception); } else if (task.IsCanceled) { tcs.TrySetCanceled(); } else { tcs.TrySetResult(response); } response.Close(); clientTokenSource.Dispose(); }); return(tcs.Task); } return(TaskAsyncHelper.FromError <IClientResponse>(new InvalidOperationException("Not a valid end point"))); }
public GitHubActivityObserver( ILogger logger, SafeCancellationTokenSource cancellationToken, DateTimeOffset lastObservation) { _logger = logger; _cancellationToken = cancellationToken; _lastObservation = lastObservation; _observedActivities = new List <Activity>(); }
public async Task <bool> OpenAsync(object args = null) { if (_isOpen) { return(await RunFunctionIfOpenAsyncA(delegate { IsEnabledAllowed = true; }).ConfigureAwait(false)); } lock (_isOpenSemaphoreLocker) { if (!SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) { _isOpenSemaphore = new SemaphoreSlimSafeRelease(1, 1); } } try { await _isOpenSemaphore.WaitAsync().ConfigureAwait(false); if (!_isOpen) { lock (_ctsLocker) { _cts?.Dispose(); _cts = new SafeCancellationTokenSource(); _cancToken = _cts.Token; } await OpenMayOverrideAsync(args).ConfigureAwait(false); IsOpen = true; IsEnabledAllowed = true; await RegisterBackEventHandlersAsync().ConfigureAwait(false); //Logger.Add_TPL($"OpenableObservablePage.OpenAsync: {GetType().Name} is now open", Logger.AppEventsLogFilename, Logger.Severity.Info, false); return(true); } } catch (Exception ex) { if (SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) { await Logger.AddAsync(GetType().Name + ex.ToString(), Logger.ForegroundLogFilename); } } finally { SemaphoreSlimSafeRelease.TryRelease(_isOpenSemaphore); } return(false); }
public async Task <bool> CloseAsync(object args = null) { if (!_isOpen) { return(await RunFunctionIfOpenAsyncA(delegate { IsEnabledAllowed = false; }).ConfigureAwait(false)); } lock (_ctsLocker) { _cts?.CancelSafe(true); } try { await _isOpenSemaphore.WaitAsync().ConfigureAwait(false); if (_isOpen) { lock (_ctsLocker) { _cts?.Dispose(); _cts = null; _cancToken = new CancellationToken(true); // CancellationToken is not nullable and not disposable } await UnregisterBackEventHandlersAsync(); IsEnabledAllowed = false; IsOpen = false; await CloseMayOverrideAsync(args).ConfigureAwait(false); return(true); } } catch (Exception ex) { if (SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) { await Logger.AddAsync(GetType().Name + ex.ToString(), Logger.ForegroundLogFilename); } } finally { lock (_isOpenSemaphoreLocker) { SemaphoreSlimSafeRelease.TryDispose(_isOpenSemaphore); _isOpenSemaphore = null; } } return(false); }
public ClientStream(INetworkObserver networkObserver, SafeCancellationTokenSource callCancelledTokenSource) { _cancelToken = _cancelTokenSource.Token; _callCancelledTokenSource = callCancelledTokenSource; networkObserver.OnCancel = () => { _cancelTokenSource.Cancel(useNewThread: false); _callCancelledTokenSource.Cancel(); }; networkObserver.OnClose = OnClose; networkObserver.OnWrite = OnWrite; }
public async Task <bool> OpenAsync(object args = null) { if (!_isOpen) { lock (_isOpenSemaphoreLocker) { if (!SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) { _isOpenSemaphore = new SemaphoreSlimSafeRelease(1, 1); } } try { await _isOpenSemaphore.WaitAsync().ConfigureAwait(false); if (!_isOpen) { lock (_ctsLocker) { _cts?.Dispose(); _cts = new SafeCancellationTokenSource(); _cancToken = _cts.Token; } await OpenMayOverrideAsync(args).ConfigureAwait(false); IsOpen = true; IsEnabledAllowed = true; return(true); } } catch (Exception ex) { if (SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) { await Logger.AddAsync(GetType().Name + ex.ToString(), Logger.ForegroundLogFilename); } } finally { SemaphoreSlimSafeRelease.TryRelease(_isOpenSemaphore); } } if (_isOpen) { await SetIsEnabledAsync(true).ConfigureAwait(false); } return(false); }
//protected Func<Task> _runAsSoonAsOpen = null; #endregion properties #region open close public async Task<bool> OpenAsync(object args = null) { if (_isOpen) return false; if (!SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) _isOpenSemaphore = new SemaphoreSlimSafeRelease(1, 1); try { await _isOpenSemaphore.WaitAsync().ConfigureAwait(false); if (!_isOpen) { lock (_ctsLocker) { _cts?.Dispose(); _cts = new SafeCancellationTokenSource(); _cancToken = _cts.Token; } await OpenMayOverrideAsync(args).ConfigureAwait(false); IsOpen = true; //try //{ // var runAsSoonAsOpen = _runAsSoonAsOpen; // if (runAsSoonAsOpen != null) // { // Task asSoonAsOpen = Task.Run(runAsSoonAsOpen, CancToken); // } //} //catch { } //finally { _runAsSoonAsOpen = null; } return true; } } catch (Exception ex) { if (SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) await Logger.AddAsync(GetType().Name + ex.ToString(), Logger.ForegroundLogFilename); } finally { SemaphoreSlimSafeRelease.TryRelease(_isOpenSemaphore); } return false; }
protected void InitializePersistentState() { _hostShutdownToken = _context.HostShutdownToken(); Completed = new TaskCompletionSource <object>(); // Create a token that represents the end of this connection's life _connectionEndTokenSource = new SafeCancellationTokenSource(); _connectionEndToken = _connectionEndTokenSource.Token; // Handle the shutdown token's callback so we can end our token if it trips _hostRegistration = _hostShutdownToken.SafeRegister(state => { state.Cancel(); }, _connectionEndTokenSource); }
/// <summary> /// Stops the <see cref="Connection"/> without sending an abort message to the server. /// </summary> public void Disconnect() { lock (_stateLock) { // Do nothing if the connection is offline if (State != ConnectionState.Disconnected) { _disconnectTimeoutOperation.Dispose(); _disconnectCts.Cancel(); _disconnectCts.Dispose(); _disconnectCts = new SafeCancellationTokenSource(); State = ConnectionState.Disconnected; // TODO: Do we want to trigger Closed if we are connecting? if (Closed != null) { Closed(); } } } }
protected virtual void InitializePersistentState() { _hostShutdownToken = _context.HostShutdownToken(); _requestLifeTime = new HttpRequestLifeTime(WriteQueue, Trace, ConnectionId); // Create a token that represents the end of this connection's life _connectionEndTokenSource = new SafeCancellationTokenSource(); _connectionEndToken = _connectionEndTokenSource.Token; // Handle the shutdown token's callback so we can end our token if it trips _hostRegistration = _hostShutdownToken.SafeRegister(state => { ((SafeCancellationTokenSource)state).Cancel(); }, _connectionEndTokenSource); // When the connection ends release the request _connectionEndRegistration = CancellationToken.SafeRegister(state => { ((HttpRequestLifeTime)state).Complete(); }, _requestLifeTime); }
public ResponseStream() { _currentStream = new MemoryStream(); _cancellationTokenSource = new SafeCancellationTokenSource(); _cancellationToken = _cancellationTokenSource.Token; }
public async Task<bool> CloseAsync() { if (!_isOpen) return false; lock (_ctsLocker) { _cts?.CancelSafe(true); } try { await _isOpenSemaphore.WaitAsync().ConfigureAwait(false); if (_isOpen) { lock (_ctsLocker) { _cts?.Dispose(); _cts = null; _cancToken = new CancellationToken(true); // CancellationToken is not nullable and not disposable } IsOpen = false; await CloseMayOverrideAsync().ConfigureAwait(false); return true; } } catch (Exception ex) { if (SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) await Logger.AddAsync(GetType().Name + ex.ToString(), Logger.ForegroundLogFilename); } finally { SemaphoreSlimSafeRelease.TryDispose(_isOpenSemaphore); _isOpenSemaphore = null; } return false; }
public async Task<bool> OpenAsync(object args = null) { if (!_isOpen) { if (!SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) _isOpenSemaphore = new SemaphoreSlimSafeRelease(1, 1); try { await _isOpenSemaphore.WaitAsync().ConfigureAwait(false); if (!_isOpen) { lock (_ctsLocker) { _cts?.Dispose(); _cts = new SafeCancellationTokenSource(); _cancToken = _cts.Token; } await OpenMayOverrideAsync(args).ConfigureAwait(false); IsOpen = true; IsEnabledAllowed = true; return true; } } catch (Exception ex) { if (SemaphoreSlimSafeRelease.IsAlive(_isOpenSemaphore)) await Logger.AddAsync(GetType().Name + ex.ToString(), Logger.ForegroundLogFilename); } finally { SemaphoreSlimSafeRelease.TryRelease(_isOpenSemaphore); } } if (_isOpen) await SetIsEnabledAsync(true).ConfigureAwait(false); return false; }
private Task <IClientResponse> ProcessRequest(string httpMethod, string url, Action <IClientRequest> prepareRequest, IDictionary <string, string> postData, bool disableWrites = false) { if (url == null) { throw new ArgumentNullException("url"); } if (prepareRequest == null) { throw new ArgumentNullException("prepareRequest"); } if (_appFunc == null) { throw new InvalidOperationException(); } if (_shutDownToken.IsCancellationRequested) { return(TaskAsyncHelper.FromError <IClientResponse>(new InvalidOperationException("Service unavailable"))); } var tcs = new TaskCompletionSource <IClientResponse>(); var clientTokenSource = new SafeCancellationTokenSource(); var env = new Dictionary <string, object>(); // Server specific setup env[OwinConstants.Version] = "1.0"; // Request specific setup var uri = new Uri(url); env[OwinConstants.RequestProtocol] = "HTTP/1.1"; env[OwinConstants.CallCancelled] = clientTokenSource.Token; env[OwinConstants.RequestMethod] = httpMethod; env[OwinConstants.RequestPathBase] = String.Empty; env[OwinConstants.RequestPath] = uri.LocalPath; env[OwinConstants.RequestQueryString] = uri.Query.Length > 0 ? uri.Query.Substring(1) : String.Empty; env[OwinConstants.RequestScheme] = uri.Scheme; env[OwinConstants.RequestBody] = GetRequestBody(postData); var headers = new Dictionary <string, string[]>(); env[OwinConstants.RequestHeaders] = headers; headers.SetHeader("X-Server", "MemoryHost"); headers.SetHeader("X-Server-Name", InstanceName); if (httpMethod == "POST") { headers.SetHeader("Content-Type", "application/x-www-form-urlencoded"); } // Run the client function to initialize the request prepareRequest(new Request(env, clientTokenSource.Cancel)); var networkObservable = new NetworkObservable(disableWrites); var clientStream = new ClientStream(networkObservable); var serverStream = new ServerStream(networkObservable); var response = new Response(clientStream); // Trigger the tcs on flush. This mimicks the client side networkObservable.OnFlush = () => tcs.TrySetResult(response); // Cancel the network observable on cancellation of the token clientTokenSource.Token.Register(networkObservable.Cancel); env[OwinConstants.ResponseBody] = serverStream; env[OwinConstants.ResponseHeaders] = new Dictionary <string, string[]>(); _appFunc(env).ContinueWith(task => { object statusCode; if (env.TryGetValue(OwinConstants.ResponseStatusCode, out statusCode) && (int)statusCode == 403) { tcs.TrySetException(new InvalidOperationException("Forbidden")); } else if (task.IsFaulted) { tcs.TrySetException(task.Exception.InnerExceptions); } else if (task.IsCanceled) { tcs.TrySetCanceled(); } else { tcs.TrySetResult(response); } // Close the server stream when the request has ended serverStream.Close(); clientTokenSource.Dispose(); }); return(tcs.Task); }