Thread safe cancellation token source. Allows the following: - Cancel will no-op if the token is disposed. - Dispose may be called after Cancel.
상속: IDisposable
예제 #1
0
파일: Response.cs 프로젝트: Jozef89/SignalR
 public ResponseStream(bool disableWrites, Action flush)
 {
     _disableWrites = disableWrites;
     _flush = flush;
     _currentStream = new MemoryStream();
     _cancellationTokenSource = new SafeCancellationTokenSource();
     _cancellationToken = _cancellationTokenSource.Token;
 }
예제 #2
0
        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;
        }
예제 #3
0
        public Task<IClientResponse> ProcessRequest(string url, Action<IClientRequest> prepareRequest, IDictionary<string, string> postData, bool disableWrites)
        {
            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.CallCancelled] = clientTokenSource.Token;
            string method = postData == null ? "GET" : "POST";
            env[OwinConstants.RequestMethod] = method;
            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;

            if (method == "POST")
            {
                headers.SetHeader("Content-Type", "application/x-www-form-urlencoded");
            }

            // Run the client function to initialize the request
            prepareRequest(new Request(env, clientTokenSource.Cancel));

            Response response = null;
            response = new Response(disableWrites, () => tcs.TrySetResult(response));
            env[OwinConstants.ResponseBody] = response.GetResponseStream();
            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);
                }

                response.Close();
                clientTokenSource.Dispose();
            });

            return tcs.Task;
        }
        protected virtual Task 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);

            return InitializeMessageId();
        }
예제 #5
0
        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;
        }
        protected virtual 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);
        }
예제 #7
0
        /// <summary>
        /// Starts the <see cref="Connection"/>.
        /// </summary>
        /// <param name="transport">The transport to use.</param>
        /// <returns>A task that represents when the connection has started.</returns>
        public Task Start(IClientTransport transport)
        {
            _disconnectCts = new SafeCancellationTokenSource();
            if (!ChangeState(ConnectionState.Disconnected, ConnectionState.Connecting))
            {
                return TaskAsyncHelper.Empty;
            }

            _transport = transport;

            return Negotiate(transport);
        }
예제 #8
0
파일: MemoryHost.cs 프로젝트: rustd/SignalR
        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"));
        }
        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);
        }
예제 #10
0
파일: Response.cs 프로젝트: rustd/SignalR
 public ResponseStream()
 {
     _currentStream = new MemoryStream();
     _cancellationTokenSource = new SafeCancellationTokenSource();
     _cancellationToken = _cancellationTokenSource.Token;
 }