private async Task<AspNetWebSocket> ProcessRequestImplAsync() {
            AspNetWebSocket webSocket = null;

            try {
                // SendResponse and other asynchronous notifications cannot be process by ASP.NET after this point.
                _root.WorkerRequest.SuppressSendResponseNotifications();

                // A flush is necessary to activate the WebSocket module so that we can get its pointer.
                //
                // DevDiv #401948: We can't allow a flush failure to propagate out, otherwise the rest of
                // this method doesn't run, which could leak resources (by not invoking the user callback)
                // or cause weird behavior (by not calling CompleteTransitionToWebSocket, which could corrupt
                // server state). If the flush fails, we'll wait to propagate the exception until a safe
                // point later in this method.
                ExceptionDispatchInfo flushExceptionDispatchInfo = DoFlush();

                // Create the AspNetWebSocket. There's a chance that the client disconnected before we
                // hit this code. If this is the case, we'll pass a null WebSocketPipe to the
                // AspNetWebSocket ctor, which immediately sets the socket into an aborted state.
                UnmanagedWebSocketContext unmanagedWebSocketContext = _root.WorkerRequest.GetWebSocketContext();
                WebSocketPipe pipe = (unmanagedWebSocketContext != null) ? new WebSocketPipe(unmanagedWebSocketContext, PerfCounters.Instance) : null;
                webSocket = new AspNetWebSocket(pipe, _subProtocol);

                // slim down the HttpContext as much as possible to allow the GC to reclaim memory
                _httpContext.CompleteTransitionToWebSocket();

                // always install a new SynchronizationContext, even if the user is running in legacy SynchronizationContext mode
                AspNetSynchronizationContext syncContext = new AspNetSynchronizationContext(this);
                _httpContext.SyncContext = syncContext;

                bool webSocketRequestSucceeded = false;
                try {
                    // need to keep track of this in the manager so that we can abort if it the AppDomain goes down
                    AspNetWebSocketManager.Current.Add(webSocket);

                    // bump up the total count (the currently-executing count is recorded separately)
                    PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TOTAL_WEBSOCKETS);

                    // Release the reference to the user delegate (which might just be a simple initialization routine) so that
                    // the GC can claim it. The only thing that needs to remain alive is the Task itself, which we're referencing.
                    Task task = null;
                    syncContext.Send(_ => {
                        task = _userFunc(new AspNetWebSocketContextImpl(new HttpContextWrapper(_httpContext), _root.WorkerRequest, webSocket));
                    }, null);

                    // Was there an exception from user code? If so, rethrow (which logs).
                    ExceptionDispatchInfo exception = syncContext.ExceptionDispatchInfo;
                    if (exception != null) {
                        exception.Throw();
                    }

                    _userFunc = null;
                    await task.ConfigureAwait(continueOnCapturedContext: false);

                    // Was there an exception from the earlier call to DoFlush? If so, rethrow (which logs).
                    // This needs to occur after the user's callback finishes, otherwise ASP.NET could try
                    // to complete the request while the callback is still accessing it.
                    if (flushExceptionDispatchInfo != null) {
                        flushExceptionDispatchInfo.Throw();
                    }

                    // Any final state except Aborted is marked as 'success'.
                    // It's possible execution never reaches this point, e.g. if the user's
                    // callback throws an exception. In that case, 'webSocketRequestSucceeded'
                    // will keep its default value of false, and the performance counter
                    // will mark this request as having failed.

                    if (webSocket.State != WebSocketState.Aborted) {
                        webSocketRequestSucceeded = true;
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_SUCCEEDED_WEBSOCKETS);
                    }
                }
                finally {
                    // we need to make sure the user can't call the WebSocket any more after this point
                    _isProcessingComplete = true;
                    webSocket.DisposeInternal();
                    AspNetWebSocketManager.Current.Remove(webSocket);

                    if (!webSocketRequestSucceeded) {
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_FAILED_WEBSOCKETS);
                    }
                }
            }
            catch (Exception ex) {
                // don't let the exception propagate upward; just log it instead
                WebBaseEvent.RaiseRuntimeError(ex, null);
            }

            return webSocket;
        }
 internal void RestoreSavedAspNetSynchronizationContext(AspNetSynchronizationContext syncContext)
 {
     AsyncOperationManager.SynchronizationContext = syncContext;
     this._syncContext = syncContext;
 }
예제 #3
0
        private void ExecuteInternal(IHttpHandler handler, TextWriter writer, bool preserveForm, bool setPreviousPage, VirtualPath path, VirtualPath filePath, string physPath, Exception error, string queryStringOverride)
        {
            if (handler == null)
            {
                throw new ArgumentNullException("handler");
            }
            HttpRequest         request             = this._context.Request;
            HttpResponse        response            = this._context.Response;
            HttpApplication     applicationInstance = this._context.ApplicationInstance;
            HttpValueCollection form   = null;
            VirtualPath         path2  = null;
            string     queryStringText = null;
            TextWriter writer2         = null;
            AspNetSynchronizationContext syncContext = null;

            this.VerifyTransactionFlow(handler);
            this._context.PushTraceContext();
            this._context.SetCurrentHandler(handler);
            bool enabled = this._context.SyncContext.Enabled;

            this._context.SyncContext.Disable();
            try
            {
                try
                {
                    this._context.ServerExecuteDepth++;
                    path2 = request.SwitchCurrentExecutionFilePath(filePath);
                    if (!preserveForm)
                    {
                        form = request.SwitchForm(new HttpValueCollection());
                        if (queryStringOverride == null)
                        {
                            queryStringOverride = string.Empty;
                        }
                    }
                    if (queryStringOverride != null)
                    {
                        queryStringText         = request.QueryStringText;
                        request.QueryStringText = queryStringOverride;
                    }
                    if (writer != null)
                    {
                        writer2 = response.SwitchWriter(writer);
                    }
                    Page page = handler as Page;
                    if (page != null)
                    {
                        if (setPreviousPage)
                        {
                            page.SetPreviousPage(this._context.PreviousHandler as Page);
                        }
                        Page page2 = this._context.Handler as Page;
                        if ((page2 != null) && page2.SmartNavigation)
                        {
                            page.SmartNavigation = true;
                        }
                        if (page is IHttpAsyncHandler)
                        {
                            syncContext = this._context.InstallNewAspNetSynchronizationContext();
                        }
                    }
                    if (((handler is StaticFileHandler) || (handler is DefaultHttpHandler)) && !DefaultHttpHandler.IsClassicAspRequest(filePath.VirtualPathString))
                    {
                        try
                        {
                            response.WriteFile(physPath);
                        }
                        catch
                        {
                            error = new HttpException(0x194, string.Empty);
                        }
                    }
                    else if (!(handler is Page))
                    {
                        error = new HttpException(0x194, string.Empty);
                    }
                    else
                    {
                        if (handler is IHttpAsyncHandler)
                        {
                            bool isInCancellablePeriod = this._context.IsInCancellablePeriod;
                            if (isInCancellablePeriod)
                            {
                                this._context.EndCancellablePeriod();
                            }
                            try
                            {
                                IHttpAsyncHandler handler2 = (IHttpAsyncHandler)handler;
                                IAsyncResult      result   = handler2.BeginProcessRequest(this._context, null, null);
                                if (!result.IsCompleted)
                                {
                                    bool flag3 = false;
                                    try
                                    {
                                        try
                                        {
                                        }
                                        finally
                                        {
                                            Monitor.Exit(applicationInstance);
                                            flag3 = true;
                                        }
                                        WaitHandle asyncWaitHandle = result.AsyncWaitHandle;
                                        if (asyncWaitHandle == null)
                                        {
                                            goto Label_0210;
                                        }
                                        asyncWaitHandle.WaitOne();
                                        goto Label_0226;
Label_020A:
                                        Thread.Sleep(1);
Label_0210:
                                        if (!result.IsCompleted)
                                        {
                                            goto Label_020A;
                                        }
                                    }
                                    finally
                                    {
                                        if (flag3)
                                        {
                                            Monitor.Enter(applicationInstance);
                                        }
                                    }
                                }
Label_0226:
                                try
                                {
                                    handler2.EndProcessRequest(result);
                                }
                                catch (Exception exception)
                                {
                                    error = exception;
                                }
                                goto Label_0306;
                            }
                            finally
                            {
                                if (isInCancellablePeriod)
                                {
                                    this._context.BeginCancellablePeriod();
                                }
                            }
                        }
                        using (new DisposableHttpContextWrapper(this._context))
                        {
                            try
                            {
                                handler.ProcessRequest(this._context);
                            }
                            catch (Exception exception2)
                            {
                                error = exception2;
                            }
                        }
                    }
                }
                finally
                {
                    this._context.ServerExecuteDepth--;
                    this._context.RestoreCurrentHandler();
                    if (writer2 != null)
                    {
                        response.SwitchWriter(writer2);
                    }
                    if ((queryStringOverride != null) && (queryStringText != null))
                    {
                        request.QueryStringText = queryStringText;
                    }
                    if (form != null)
                    {
                        request.SwitchForm(form);
                    }
                    request.SwitchCurrentExecutionFilePath(path2);
                    if (syncContext != null)
                    {
                        this._context.RestoreSavedAspNetSynchronizationContext(syncContext);
                    }
                    if (enabled)
                    {
                        this._context.SyncContext.Enable();
                    }
                    this._context.PopTraceContext();
                }
            }
            catch
            {
                throw;
            }
Label_0306:
            if (error == null)
            {
                return;
            }
            if ((error is HttpException) && (((HttpException)error).GetHttpCode() != 500))
            {
                error = null;
            }
            if (path != null)
            {
                throw new HttpException(System.Web.SR.GetString("Error_executing_child_request_for_path", new object[] { path }), error);
            }
            throw new HttpException(System.Web.SR.GetString("Error_executing_child_request_for_handler", new object[] { handler.GetType().ToString() }), error);
        }
 internal AspNetSynchronizationContext InstallNewAspNetSynchronizationContext()
 {
     AspNetSynchronizationContext context = this._syncContext;
     if ((context != null) && (context == AsyncOperationManager.SynchronizationContext))
     {
         this._syncContext = new AspNetSynchronizationContext(this.ApplicationInstance);
         AsyncOperationManager.SynchronizationContext = this._syncContext;
         return context;
     }
     return null;
 }
 internal void ClearReferences()
 {
     this._appInstance = null;
     this._handler = null;
     this._handlerStack = null;
     this._currentHandler = null;
     if (this._isIntegratedPipeline)
     {
         this._items = null;
         this._syncContext = null;
     }
 }
예제 #6
0
 internal void RestoreSavedAspNetSynchronizationContext(AspNetSynchronizationContext syncContext);
 internal PageAsyncInfo(Page page)
 {
     this._page = page;
     this._app = page.Context.ApplicationInstance;
     this._syncContext = page.Context.SyncContext;
     this._completionCallback = new AsyncCallback(this.OnAsyncHandlerCompletion);
     this._callHandlersThreadpoolCallback = new WaitCallback(this.CallHandlersFromThreadpoolThread);
     this._callHandlersCancellableCallback = new WaitCallback(this.CallHandlersCancellableCallback);
 }
예제 #8
0
        private async Task <AspNetWebSocket> ProcessRequestImplAsync()
        {
            AspNetWebSocket webSocket = null;

            try {
                // SendResponse and other asynchronous notifications cannot be process by ASP.NET after this point.
                _root.WorkerRequest.SuppressSendResponseNotifications();

                // A flush is necessary to activate the WebSocket module so that we can get its pointer.
                //
                // DevDiv #401948: We can't allow a flush failure to propagate out, otherwise the rest of
                // this method doesn't run, which could leak resources (by not invoking the user callback)
                // or cause weird behavior (by not calling CompleteTransitionToWebSocket, which could corrupt
                // server state). If the flush fails, we'll wait to propagate the exception until a safe
                // point later in this method.
                ExceptionDispatchInfo flushExceptionDispatchInfo = DoFlush();

                // Create the AspNetWebSocket. There's a chance that the client disconnected before we
                // hit this code. If this is the case, we'll pass a null WebSocketPipe to the
                // AspNetWebSocket ctor, which immediately sets the socket into an aborted state.
                UnmanagedWebSocketContext unmanagedWebSocketContext = _root.WorkerRequest.GetWebSocketContext();
                WebSocketPipe             pipe = (unmanagedWebSocketContext != null) ? new WebSocketPipe(unmanagedWebSocketContext, PerfCounters.Instance) : null;
                webSocket = new AspNetWebSocket(pipe, _subProtocol);

                // slim down the HttpContext as much as possible to allow the GC to reclaim memory
                _httpContext.CompleteTransitionToWebSocket();

                // always install a new SynchronizationContext, even if the user is running in legacy SynchronizationContext mode
                AspNetSynchronizationContext syncContext = new AspNetSynchronizationContext(this);
                _httpContext.SyncContext = syncContext;

                bool webSocketRequestSucceeded = false;
                try {
                    // need to keep track of this in the manager so that we can abort if it the AppDomain goes down
                    AspNetWebSocketManager.Current.Add(webSocket);

                    // bump up the total count (the currently-executing count is recorded separately)
                    PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_TOTAL_WEBSOCKETS);

                    // Release the reference to the user delegate (which might just be a simple initialization routine) so that
                    // the GC can claim it. The only thing that needs to remain alive is the Task itself, which we're referencing.
                    Task task = null;
                    syncContext.Send(_ => {
                        task = _userFunc(new AspNetWebSocketContextImpl(new HttpContextWrapper(_httpContext), _root.WorkerRequest, webSocket));
                    }, null);

                    // Was there an exception from user code? If so, rethrow (which logs).
                    ExceptionDispatchInfo exception = syncContext.ExceptionDispatchInfo;
                    if (exception != null)
                    {
                        exception.Throw();
                    }

                    _userFunc = null;
                    await task.ConfigureAwait(continueOnCapturedContext : false);

                    // Was there an exception from the earlier call to DoFlush? If so, rethrow (which logs).
                    // This needs to occur after the user's callback finishes, otherwise ASP.NET could try
                    // to complete the request while the callback is still accessing it.
                    if (flushExceptionDispatchInfo != null)
                    {
                        flushExceptionDispatchInfo.Throw();
                    }

                    // Any final state except Aborted is marked as 'success'.
                    // It's possible execution never reaches this point, e.g. if the user's
                    // callback throws an exception. In that case, 'webSocketRequestSucceeded'
                    // will keep its default value of false, and the performance counter
                    // will mark this request as having failed.

                    if (webSocket.State != WebSocketState.Aborted)
                    {
                        webSocketRequestSucceeded = true;
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_SUCCEEDED_WEBSOCKETS);
                    }
                }
                finally {
                    // we need to make sure the user can't call the WebSocket any more after this point
                    _isProcessingComplete = true;
                    webSocket.DisposeInternal();
                    AspNetWebSocketManager.Current.Remove(webSocket);

                    if (!webSocketRequestSucceeded)
                    {
                        PerfCounters.IncrementCounter(AppPerfCounter.REQUESTS_FAILED_WEBSOCKETS);
                    }
                }
            }
            catch (Exception ex) {
                // don't let the exception propagate upward; just log it instead
                WebBaseEvent.RaiseRuntimeError(ex, null);
            }

            return(webSocket);
        }