/// <summary>
        /// Begins an ansynchronous receive operation.
        /// </summary>
        /// <param name="callback">The callback method.</param>
        /// <param name="state">The user state.</param>
        /// <returns>The result of the asynchronous operation.</returns>
        public IAsyncResult BeginReceive(AsyncCallback callback, object state)
        {
            ListenerAsyncResult result =
                new ListenerAsyncResult()
                {
                    Buffer = new byte[65535],
                    EndPoint = this.endPoint,
                    Callback = callback,
                    State = state
                };

            result.AsyncResult = this.socket.BeginReceiveFrom(result.Buffer, 0, 65535, SocketFlags.None, ref result.EndPoint, OnSocketCallback, result);

            return result;
        }
        public HttpListenerContext GetContext()
        {
            if (_state == State.Stopped)
            {
                throw new InvalidOperationException(SR.Format(SR.net_listener_mustcall, "Start()"));
            }
            if (_prefixes.Count == 0)
            {
                throw new InvalidOperationException(SR.Format(SR.net_listener_mustcall, "AddPrefix()"));
            }

            ListenerAsyncResult ares = (ListenerAsyncResult)BeginGetContext(null, null);

            ares._inGet = true;

            return(EndGetContext(ares));
        }
        private static void InvokeCallback(object o)
        {
            ListenerAsyncResult ares = (ListenerAsyncResult)o;

            if (ares._forward != null)
            {
                InvokeCallback(ares._forward);
                return;
            }
            try
            {
                ares._cb(ares);
            }
            catch
            {
            }
        }
Exemple #4
0
        public HttpListenerContext EndGetContext(IAsyncResult asyncResult)
        {
            CheckDisposed();
            if (asyncResult == null)
            {
                throw new ArgumentNullException(nameof(asyncResult));
            }

            ListenerAsyncResult ares = asyncResult as ListenerAsyncResult;

            if (ares == null)
            {
                throw new ArgumentException(SR.net_io_invalidasyncresult, nameof(asyncResult));
            }
            if (ares._endCalled)
            {
                throw new InvalidOperationException(SR.Format(SR.net_io_invalidendcall, nameof(EndGetContext)));
            }

            ares._endCalled = true;

            if (!ares.IsCompleted)
            {
                ares.AsyncWaitHandle.WaitOne();
            }

            lock ((_asyncWaitQueue as ICollection).SyncRoot)
            {
                int idx = _asyncWaitQueue.IndexOf(ares);
                if (idx >= 0)
                {
                    _asyncWaitQueue.RemoveAt(idx);
                }
            }

            HttpListenerContext context = ares.GetContext();

            context.ParseAuthentication(SelectAuthenticationScheme(context));

            return(context);
        }
        public HttpListenerContext EndGetContext(IAsyncResult asyncResult)
        {
            CheckDisposed();
            if (asyncResult == null)
            {
                throw new ArgumentNullException("asyncResult");
            }

            ListenerAsyncResult ares = asyncResult as ListenerAsyncResult;

            if (ares == null)
            {
                throw new ArgumentException("Wrong IAsyncResult.", "asyncResult");
            }
            if (ares.EndCalled)
            {
                throw new ArgumentException("Cannot reuse this IAsyncResult");
            }
            ares.EndCalled = true;

            if (!ares.IsCompleted)
            {
                ares.AsyncWaitHandle.WaitOne();
            }

            lock (wait_queue)
            {
                int idx = wait_queue.IndexOf(ares);
                if (idx >= 0)
                {
                    wait_queue.RemoveAt(idx);
                }
            }

            HttpListenerContext context = ares.GetContext();

            context.ParseAuthentication(SelectAuthenticationScheme(context));
            return(context); // This will throw on error.
        }
Exemple #6
0
        internal void RegisterContext(HttpListenerContext context)
        {
            lock (_registry)
                _registry[context] = context;

            ListenerAsyncResult ares = null;

            lock (_waitQueue)
            {
                if (_waitQueue.Count == 0)
                {
                    lock (_ctxQueue)
                        _ctxQueue.Add(context);
                }
                else
                {
                    ares = (ListenerAsyncResult)_waitQueue[0];
                    _waitQueue.RemoveAt(0);
                }
            }
            ares?.Complete(context);
        }
Exemple #7
0
 internal void RegisterContext(HttpListenerContext context)
 {
     try {
         Monitor.Enter(registry);
         registry [context] = context;
         Monitor.Enter(wait_queue);
         Monitor.Enter(ctx_queue);
         if (wait_queue.Count == 0)
         {
             ctx_queue.Add(context);
         }
         else
         {
             ListenerAsyncResult ares = (ListenerAsyncResult)wait_queue [0];
             wait_queue.RemoveAt(0);
             ares.Complete(context);
         }
     } finally {
         Monitor.Exit(ctx_queue);
         Monitor.Exit(wait_queue);
         Monitor.Exit(registry);
     }
 }
        private void Cleanup(bool close_existing)
        {
            Hashtable obj = this.registry;

            lock (obj)
            {
                if (close_existing)
                {
                    foreach (object obj2 in this.registry.Keys)
                    {
                        HttpListenerContext httpListenerContext = (HttpListenerContext)obj2;
                        httpListenerContext.Connection.Close();
                    }
                    this.registry.Clear();
                }
                ArrayList obj3 = this.ctx_queue;
                lock (obj3)
                {
                    foreach (object obj4 in this.ctx_queue)
                    {
                        HttpListenerContext httpListenerContext2 = (HttpListenerContext)obj4;
                        httpListenerContext2.Connection.Close();
                    }
                    this.ctx_queue.Clear();
                }
                ArrayList obj5 = this.wait_queue;
                lock (obj5)
                {
                    foreach (object obj6 in this.wait_queue)
                    {
                        ListenerAsyncResult listenerAsyncResult = (ListenerAsyncResult)obj6;
                        listenerAsyncResult.Complete("Listener was closed.");
                    }
                    this.wait_queue.Clear();
                }
            }
        }
Exemple #9
0
        internal void RegisterContext(HttpListenerContext context)
        {
            lock (registry)
                registry [context] = context;

            ListenerAsyncResult ares = null;

            lock (wait_queue) {
                if (wait_queue.Count == 0)
                {
                    lock (ctx_queue)
                        ctx_queue.Add(context);
                }
                else
                {
                    ares = (ListenerAsyncResult)wait_queue [0];
                    wait_queue.RemoveAt(0);
                }
            }
            if (ares != null)
            {
                ares.Complete(context);
            }
        }
        private static unsafe void WaitCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
            ListenerAsyncResult asyncResult = (ListenerAsyncResult)ThreadPoolBoundHandle.GetNativeOverlappedState(nativeOverlapped);

            IOCompleted(asyncResult, errorCode, numBytes);
        }
        private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes)
        {
            object result = null;
            try
            {
                GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() errorCode:[" + errorCode.ToString() + "] numBytes:[" + numBytes.ToString() + "]");

                if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                    errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener;
                    if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
                    {
                        // at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
                        // points to it we need to hook up our authentication handling code here.
                        bool stoleBlob = false;
                        try
                        {
                            if (httpWebListener.ValidateRequest(asyncResult.m_RequestContext))
                            {
                                result = httpWebListener.HandleAuthentication(asyncResult.m_RequestContext, out stoleBlob);
                            }
                        }
                        finally
                        {
                            if (stoleBlob)
                            {
                                // The request has been handed to the user, which means this code can't reuse the blob.  Reset it here.
                                asyncResult.m_RequestContext = result == null ? new AsyncRequestContext(asyncResult) : null;
                            }
                            else
                            {
                                asyncResult.m_RequestContext.Reset(0, 0);
                            }
                        }
                    }
                    else
                    {
                        asyncResult.m_RequestContext.Reset(asyncResult.m_RequestContext.RequestBlob->RequestId, numBytes);
                    }

                    // We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
                    if (result==null)
                    {
                        uint statusCode = asyncResult.QueueBeginGetContext();
                        if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                            statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
                        {
                            // someother bad error, possible(?) return values are:
                            // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
                            result = new HttpListenerException((int)statusCode);
                        }
                    }
                    if (result==null) {
                        return;
                    }
                }

                // complete the async IO and invoke the callback
                GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() calling Complete()");
            }
            catch (Exception exception)
            {
                if (NclUtilities.IsFatal(exception)) throw;

                GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() Caught exception:" + exception.ToString());
                result = exception;
            }
            asyncResult.InvokeCallback(result);
        }
Exemple #12
0
        private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes)
        {
            object result = null;
            try
            {
                if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"errorCode:[{errorCode}] numBytes:[{numBytes}]");

                if (errorCode != Interop.HttpApi.ERROR_SUCCESS &&
                    errorCode != Interop.HttpApi.ERROR_MORE_DATA)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener;
                    if (errorCode == Interop.HttpApi.ERROR_SUCCESS)
                    {
                        // at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
                        // points to it we need to hook up our authentication handling code here.
                        bool stoleBlob = false;
                        try
                        {
                            if (httpWebListener.ValidateRequest(asyncResult._requestContext))
                            {
                                result = httpWebListener.HandleAuthentication(asyncResult._requestContext, out stoleBlob);
                            }
                        }
                        finally
                        {
                            if (stoleBlob)
                            {
                                // The request has been handed to the user, which means this code can't reuse the blob.  Reset it here.
                                asyncResult._requestContext = result == null ? new AsyncRequestContext(httpWebListener.RequestQueueBoundHandle, asyncResult) : null;
                            }
                            else
                            {
                                asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, 0, 0);
                            }
                        }
                    }
                    else
                    {
                        asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, asyncResult._requestContext.RequestBlob->RequestId, numBytes);
                    }

                    // We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
                    if (result == null)
                    {
                        uint statusCode = asyncResult.QueueBeginGetContext();
                        if (statusCode != Interop.HttpApi.ERROR_SUCCESS &&
                            statusCode != Interop.HttpApi.ERROR_IO_PENDING)
                        {
                            // someother bad error, possible return values are:
                            // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
                            result = new HttpListenerException((int)statusCode);
                        }
                    }
                    if (result == null)
                    {
                        return;
                    }
                }

                // complete the async IO and invoke the callback
                if (NetEventSource.IsEnabled) NetEventSource.Info(null, "Calling Complete()");
            }
            catch (Exception exception) when (!ExceptionCheck.IsFatal(exception))
            {
                if (NetEventSource.IsEnabled) NetEventSource.Info(null, $"Caught exception: {exception}");
                result = exception;
            }
            asyncResult.InvokeCallback(result);
        }
Exemple #13
0
		public IAsyncResult BeginGetContext (AsyncCallback callback, Object state)
		{
			CheckDisposed ();
			if (!listening)
				throw new InvalidOperationException ("Please, call Start before using this method.");

			ListenerAsyncResult ares = new ListenerAsyncResult (callback, state);

			// lock wait_queue early to avoid race conditions
			lock (wait_queue) {
				lock (ctx_queue) {
					HttpListenerContext ctx = GetContextFromQueue ();
					if (ctx != null) {
						ares.Complete (ctx, true);
						return ares;
					}
				}

				wait_queue.Add (ares);
			}

			return ares;
		}
Exemple #14
0
        public IAsyncResult BeginGetContext(AsyncCallback callback, object state)
        {
            if (NetEventSource.IsEnabled) NetEventSource.Enter(this);
            ListenerAsyncResult asyncResult = null;
            try
            {
                CheckDisposed();
                if (_state == State.Stopped)
                {
                    throw new InvalidOperationException(SR.Format(SR.net_listener_mustcall, "Start()"));
                }
                // prepare the ListenerAsyncResult object (this will have it's own
                // event that the user can wait on for IO completion - which means we
                // need to signal it when IO completes)
                asyncResult = new ListenerAsyncResult(this, state, callback);
                uint statusCode = asyncResult.QueueBeginGetContext();
                if (statusCode != Interop.HttpApi.ERROR_SUCCESS &&
                    statusCode != Interop.HttpApi.ERROR_IO_PENDING)
                {
                    // someother bad error, return values are:
                    // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
                    throw new HttpListenerException((int)statusCode);
                }
            }
            catch (Exception exception)
            {
                if (NetEventSource.IsEnabled) NetEventSource.Error(this, $"BeginGetContext {exception}");
                throw;
            }
            finally
            {
                if (NetEventSource.IsEnabled) NetEventSource.Exit(this);
            }

            return asyncResult;
        }
Exemple #15
0
        static void InvokeCallback(object o)
        {
            ListenerAsyncResult ares = (ListenerAsyncResult)o;

            ares.cb(ares);
        }
        /// <summary>
        /// Begins an asynchronous send operation.
        /// </summary>
        /// <param name="buffer">The buffer.</param>
        /// <param name="offset">The offset.</param>
        /// <param name="length">The sending data length.</param>
        /// <param name="endPoint">The end point.</param>
        /// <param name="callback">The callback method.</param>
        /// <param name="state">The user state.</param>
        /// <returns>The asynchronous result.</returns>
        public IAsyncResult BeginSend(byte[] buffer, int offset, int length, IPEndPoint endPoint, AsyncCallback callback, object state)
        {
            ListenerAsyncResult result =
                new ListenerAsyncResult()
                {
                    Callback = callback,
                    State = state
                };

            result.AsyncResult = this.socket.BeginSendTo(buffer, offset, length, SocketFlags.None, endPoint, OnSocketCallback, result);

            return result;
        }
 internal AsyncRequestContext(ListenerAsyncResult result)
 {
     this.m_Result = result;
     base.BaseConstruction(this.Allocate(0));
 }
        private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes)
        {
            object result = null;

            try
            {
                GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() errorCode:[" + errorCode.ToString() + "] numBytes:[" + numBytes.ToString() + "]");

                if (errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                    errorCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_MORE_DATA)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener;
                    if (errorCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS)
                    {
                        // at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
                        // points to it we need to hook up our authentication handling code here.
                        bool stoleBlob = false;
                        try
                        {
                            if (httpWebListener.ValidateRequest(asyncResult.m_RequestContext))
                            {
                                result = httpWebListener.HandleAuthentication(asyncResult.m_RequestContext, out stoleBlob);
                            }
                        }
                        finally
                        {
                            if (stoleBlob)
                            {
                                // The request has been handed to the user, which means this code can't reuse the blob.  Reset it here.
                                asyncResult.m_RequestContext = result == null ? new AsyncRequestContext(asyncResult) : null;
                            }
                            else
                            {
                                asyncResult.m_RequestContext.Reset(0, 0);
                            }
                        }
                    }
                    else
                    {
                        asyncResult.m_RequestContext.Reset(asyncResult.m_RequestContext.RequestBlob->RequestId, numBytes);
                    }

                    // We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
                    if (result == null)
                    {
                        uint statusCode = asyncResult.QueueBeginGetContext();
                        if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                            statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
                        {
                            // someother bad error, possible(?) return values are:
                            // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
                            result = new HttpListenerException((int)statusCode);
                        }
                    }
                    if (result == null)
                    {
                        return;
                    }
                }

                // complete the async IO and invoke the callback
                GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() calling Complete()");
            }
            catch (Exception exception)
            {
                if (NclUtilities.IsFatal(exception))
                {
                    throw;
                }

                GlobalLog.Print("ListenerAsyncResult#" + ValidationHelper.HashString(asyncResult) + "::WaitCallback() Caught exception:" + exception.ToString());
                result = exception;
            }
            asyncResult.InvokeCallback(result);
        }
Exemple #19
0
        internal void Complete(HttpListenerContext context, bool synch)
        {
            if (this.forward != null)
            {
                this.forward.Complete(context, synch);
                return;
            }
            this.synch   = synch;
            this.context = context;
            object obj = this.locker;

            lock (obj)
            {
                AuthenticationSchemes authenticationSchemes = context.Listener.SelectAuthenticationScheme(context);
                if ((authenticationSchemes == AuthenticationSchemes.Basic || context.Listener.AuthenticationSchemes == AuthenticationSchemes.Negotiate) && context.Request.Headers["Authorization"] == null)
                {
                    context.Response.StatusCode = 401;
                    context.Response.Headers["WWW-Authenticate"] = string.Concat(new object[]
                    {
                        authenticationSchemes,
                        " realm=\"",
                        context.Listener.Realm,
                        "\""
                    });
                    context.Response.OutputStream.Close();
                    IAsyncResult asyncResult = context.Listener.BeginGetContext(this.cb, this.state);
                    this.forward = (ListenerAsyncResult)asyncResult;
                    object obj2 = this.forward.locker;
                    lock (obj2)
                    {
                        if (this.handle != null)
                        {
                            this.forward.handle = this.handle;
                        }
                    }
                    ListenerAsyncResult listenerAsyncResult = this.forward;
                    int num = 0;
                    while (listenerAsyncResult.forward != null)
                    {
                        if (num > 20)
                        {
                            this.Complete("Too many authentication errors");
                        }
                        listenerAsyncResult = listenerAsyncResult.forward;
                        num++;
                    }
                }
                else
                {
                    this.completed = true;
                    if (this.handle != null)
                    {
                        this.handle.Set();
                    }
                    if (this.cb != null)
                    {
                        ThreadPool.QueueUserWorkItem(new WaitCallback(ListenerAsyncResult.InvokeCallback), this);
                    }
                }
            }
        }
 internal AsyncRequestContext(ListenerAsyncResult result)
 {
     this.m_Result = result;
     base.BaseConstruction(this.Allocate(0));
 }
        private static void IOCompleted(ListenerAsyncResult asyncResult, uint errorCode, uint numBytes)
        {
            object result = null;

            try
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, $"errorCode:[{errorCode}] numBytes:[{numBytes}]");
                }

                if (errorCode != Interop.HttpApi.ERROR_SUCCESS &&
                    errorCode != Interop.HttpApi.ERROR_MORE_DATA)
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    HttpListener httpWebListener = asyncResult.AsyncObject as HttpListener;
                    if (errorCode == Interop.HttpApi.ERROR_SUCCESS)
                    {
                        // at this point we have received an unmanaged HTTP_REQUEST and memoryBlob
                        // points to it we need to hook up our authentication handling code here.
                        bool stoleBlob = false;
                        try
                        {
                            if (httpWebListener.ValidateRequest(asyncResult._requestContext))
                            {
                                result = httpWebListener.HandleAuthentication(asyncResult._requestContext, out stoleBlob);
                            }
                        }
                        finally
                        {
                            if (stoleBlob)
                            {
                                // The request has been handed to the user, which means this code can't reuse the blob.  Reset it here.
                                asyncResult._requestContext = result == null ? new AsyncRequestContext(httpWebListener.RequestQueueBoundHandle, asyncResult) : null;
                            }
                            else
                            {
                                asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, 0, 0);
                            }
                        }
                    }
                    else
                    {
                        asyncResult._requestContext.Reset(httpWebListener.RequestQueueBoundHandle, asyncResult._requestContext.RequestBlob->RequestId, numBytes);
                    }

                    // We need to issue a new request, either because auth failed, or because our buffer was too small the first time.
                    if (result == null)
                    {
                        uint statusCode = asyncResult.QueueBeginGetContext();
                        if (statusCode != Interop.HttpApi.ERROR_SUCCESS &&
                            statusCode != Interop.HttpApi.ERROR_IO_PENDING)
                        {
                            // someother bad error, possible return values are:
                            // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
                            result = new HttpListenerException((int)statusCode);
                        }
                    }
                    if (result == null)
                    {
                        return;
                    }
                }

                // complete the async IO and invoke the callback
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, "Calling Complete()");
                }
            }
            catch (Exception exception) when(!ExceptionCheck.IsFatal(exception))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.Info(null, $"Caught exception: {exception}");
                }
                result = exception;
            }
            asyncResult.InvokeCallback(result);
        }
        WaitCallback(
            Object state,
            bool signaled)
        {
            GlobalLog.Print("entering the WaitCallback()");
            //
            // take the ListenerAsyncResult object from the state
            //

            ListenerAsyncResult AResult = ( ListenerAsyncResult )state;

            GlobalLog.Print("got the AResult object");

            bool syncComplete = AResult.CompletedSynchronously;

            if (!syncComplete)
            {
                //
                // we've been called by the thread, the event was signaled
                // call HackedGetOverlappedResult() to find out about the IO
                //

                GlobalLog.Print("WaitCallback()!call didn't complete sync calling HackedGetOverlappedResult():");

                AResult.m_BytesReturned =
                    Win32.HackedGetOverlappedResult(
                        AResult.m_Overlapped);

                if (AResult.m_BytesReturned <= 0)
                {
                    //
                    // something went wrong throw for now, later we should
                    // call into ul call again
                    //

                    throw new InvalidOperationException("UlReceiveHttpRequest(callback) failure m_BytesReturned:" + Convert.ToString(AResult.m_BytesReturned));
                }

                if (AResult.m_BufferSize < AResult.m_BytesReturned)
                {
                    //
                    // this is anlogous to the syncronous case in which we get
                    // result == NativeMethods.ERROR_MORE_DATA
                    // basically the buffer is not big enought to accomodate the
                    // reqeust that came in, so grow it to the needed size, copy
                    // the valid data, and reissue the async call and queue it
                    // up to the ThreadPool
                    //

                    throw new InvalidOperationException("UlReceiveHttpRequest(callback) buffer too small, was:" + Convert.ToString(AResult.m_BufferSize) + " should be:" + Convert.ToString(AResult.m_BytesReturned));
                }
            }

            GlobalLog.Print("WaitCallback()!I/O status is"
                            + " AResult.m_BytesReturned: " + Convert.ToString(AResult.m_BytesReturned)
                            + " AResult.m_Overlapped: " + Convert.ToString(AResult.m_Overlapped)
                            + " AResult.m_SyncComplete: " + Convert.ToString(AResult.CompletedSynchronously));

            //
            // complete the async IO and invoke the callback
            //

            AResult.InvokeCallback(syncComplete, new HttpListenerWebRequest(AResult.m_Buffer, AResult.m_BytesReturned, m_AppPoolHandle));

            return;
        } // WaitCallback()
        private static unsafe void WaitCallback(uint errorCode, uint numBytes, NativeOverlapped *nativeOverlapped)
        {
            ListenerAsyncResult asyncResult = (ListenerAsyncResult)Overlapped.Unpack(nativeOverlapped).AsyncResult;
            object result = null;

            try
            {
                if ((errorCode != 0) && (errorCode != 0xea))
                {
                    asyncResult.ErrorCode = (int)errorCode;
                    result = new HttpListenerException((int)errorCode);
                }
                else
                {
                    HttpListener asyncObject = asyncResult.AsyncObject as HttpListener;
                    if (errorCode == 0)
                    {
                        bool stoleBlob = false;
                        try
                        {
                            result = asyncObject.HandleAuthentication(asyncResult.m_RequestContext, out stoleBlob);
                        }
                        finally
                        {
                            if (stoleBlob)
                            {
                                asyncResult.m_RequestContext = (result == null) ? new AsyncRequestContext(asyncResult) : null;
                            }
                            else
                            {
                                asyncResult.m_RequestContext.Reset(0L, 0);
                            }
                        }
                    }
                    else
                    {
                        asyncResult.m_RequestContext.Reset(asyncResult.m_RequestContext.RequestBlob.RequestId, numBytes);
                    }
                    if (result == null)
                    {
                        uint num = asyncResult.QueueBeginGetContext();
                        if ((num != 0) && (num != 0x3e5))
                        {
                            result = new HttpListenerException((int)num);
                        }
                    }
                    if (result == null)
                    {
                        return;
                    }
                }
            }
            catch (Exception exception)
            {
                if (NclUtilities.IsFatal(exception))
                {
                    throw;
                }
                result = exception;
            }
            asyncResult.InvokeCallback(result);
        }
 internal AsyncRequestContext(ThreadPoolBoundHandle boundHandle, ListenerAsyncResult result)
 {
     _result = result;
     BaseConstruction(Allocate(boundHandle, 0));
 }
        BeginGetRequest(
            AsyncCallback requestCallback,
            Object stateObject)
        {
            //
            // Validation
            //

            if (m_AppPoolHandle == NativeMethods.INVALID_HANDLE_VALUE)
            {
                throw new InvalidOperationException("The AppPool handle is invalid");
            }

            //
            // prepare the ListenerAsyncResult object ( this will have it's own
            // event that the user can wait on for IO completion - which means we
            // need to signal it when IO completes )
            //

            GlobalLog.Print("BeginGetRequest() creating ListenerAsyncResult");

            ListenerAsyncResult AResult = new ListenerAsyncResult(
                stateObject,
                requestCallback);

            AutoResetEvent m_Event = new AutoResetEvent(false);

            Marshal.WriteIntPtr(
                AResult.m_Overlapped,
                Win32.OverlappedhEventOffset,
                m_Event.Handle);

            //
            // issue unmanaged call until we read enough data:
            // usually starting with a InitialBufferSize==4096 bytes we should be
            // able to get all the headers ( and part of the entity body, if any
            // is present ), if we don't, if the call didn't fail for othe reasons,
            // we get indication in BytesReturned, on how big the buffer should be
            // to receive the data available, so usually the second call will
            // succeed, but we have to consider the case of two competing calls
            // for the same RequestId, and that's why we need a loop and not just
            // a try/retry-expecting-success fashion
            //

            int result;

            for (;;)
            {
                //
                // check if we're in a healthy state
                //
                if (AResult.m_Retries++ > m_MaxRetries)
                {
                    throw new InvalidOperationException("UlReceiveHttpRequest() Too many retries");
                }

                result =
                    ComNetOS.IsWinNt ?

                    UlSysApi.UlReceiveHttpRequest(
                        m_AppPoolHandle,
                        AResult.m_RequestId,
                        UlConstants.UL_RECEIVE_REQUEST_FLAG_COPY_BODY,
                        AResult.m_Buffer,
                        AResult.m_BufferSize,
                        ref AResult.m_BytesReturned,
                        AResult.m_Overlapped)

                :

                    UlVxdApi.UlReceiveHttpRequestHeaders(
                        m_AppPoolHandle,
                        AResult.m_RequestId,
                        0,
                        AResult.m_Buffer,
                        AResult.m_BufferSize,
                        ref AResult.m_BytesReturned,
                        AResult.m_Overlapped);

                GlobalLog.Print("UlReceiveHttpRequest() returns:"
                                + Convert.ToString(result));

                if (result == NativeMethods.ERROR_SUCCESS || result == NativeMethods.ERROR_IO_PENDING)
                {
                    //
                    // synchronous success or successfull pending: we are done
                    //

                    break;
                }

                if (result == NativeMethods.ERROR_INVALID_PARAMETER)
                {
                    //
                    // we might get this if somebody stole our RequestId,
                    // set RequestId to null
                    //

                    AResult.m_RequestId = 0;

                    //
                    // and start all over again with the buffer we
                    // just allocated
                    //

                    continue;
                }

                if (result == NativeMethods.ERROR_MORE_DATA)
                {
                    //
                    // the buffer was not big enough to fit the headers, we need
                    // to read the RequestId returned, grow the buffer, keeping
                    // the data already transferred
                    //

                    AResult.m_RequestId = Marshal.ReadInt64(IntPtrHelper.Add(AResult.m_Buffer, m_RequestIdOffset));

                    //
                    // allocate a new buffer of the required size
                    //

                    IntPtr NewBuffer = Marshal.AllocHGlobal(AResult.m_BytesReturned);

                    //
                    // copy the data already read from the old buffer into the
                    // new one
                    //

                    NativeMethods.CopyMemory(NewBuffer, AResult.m_Buffer, AResult.m_BufferSize);


                    //
                    // free the old buffer
                    //

                    Marshal.FreeHGlobal(AResult.m_Buffer);

                    //
                    // update buffer pointer and size
                    //

                    AResult.m_Buffer        = NewBuffer;
                    AResult.m_BufferSize    = AResult.m_BytesReturned;
                    AResult.m_BytesReturned = 0;

                    //
                    // and start all over again with the new buffer
                    //

                    continue;
                }

                //
                // someother bad error, possible( ? ) return values are:
                //
                // ERROR_INVALID_HANDLE
                // ERROR_INSUFFICIENT_BUFFER
                // ERROR_OPERATION_ABORTED
                // ERROR_IO_PENDING
                //

                throw new InvalidOperationException("UlReceiveHttpRequest() failed, err#" + Convert.ToString(result));
            }

            //
            // we get here only if a break happens, i.e.
            // 1) syncronous completion
            // 2) the IO pended
            //

            if (result == NativeMethods.ERROR_SUCCESS)
            {
                //
                // set syncronous completion to true
                //

                AResult.Complete(true);

                //
                // and call the internal callback
                //

                WaitCallback(AResult, false);
            }
            else
            {
                //
                // create a new delegate
                // and spin a new thread from the thread pool to wake up when the
                // event is signaled and call the delegate
                //

                ThreadPool.RegisterWaitForSingleObject(
                    m_Event,
                    new WaitOrTimerCallback(WaitCallback),
                    AResult,
                    -1,
                    true);
            }

            GlobalLog.Print("returning AResult");

            return(AResult);
        } // StartListen()
Exemple #26
0
		internal void Complete (HttpListenerContext context, bool synch)
		{
			if (forward != null) {
				forward.Complete (context, synch);
				return;
			}
			this.synch = synch;
			this.context = context;
			lock (locker) {
				AuthenticationSchemes schemes = context.Listener.SelectAuthenticationScheme (context);
				if ((schemes == AuthenticationSchemes.Basic || context.Listener.AuthenticationSchemes == AuthenticationSchemes.Negotiate) && context.Request.Headers ["Authorization"] == null) {
					context.Response.StatusCode = 401;
					context.Response.Headers ["WWW-Authenticate"] = schemes + " realm=\"" + context.Listener.Realm + "\"";
					context.Response.OutputStream.Close ();
					IAsyncResult ares = context.Listener.BeginGetContext (cb, state);
					this.forward = (ListenerAsyncResult) ares;
					lock (forward.locker) {
						if (handle != null)
							forward.handle = handle;
					}
					ListenerAsyncResult next = forward;
					for (int i = 0; next.forward != null; i++) {
						if (i > 20)
							Complete (new HttpListenerException (400, "Too many authentication errors"));
						next = next.forward;
					}
				} else {
					completed = true;
					if (handle != null)
						handle.Set ();

					if (cb != null)
						ThreadPool.UnsafeQueueUserWorkItem (InvokeCB, this);
				}
			}
		}
 internal AsyncRequestContext(ListenerAsyncResult result)
 {
     m_Result = result;
     BaseConstruction(Allocate(0));
 }
 public IAsyncResult BeginGetContext(AsyncCallback callback, object state)
 {
     if (Logging.On)
     {
         Logging.Enter(Logging.HttpListener, this, "BeginGetContext", "");
     }
     ListenerAsyncResult objectValue = null;
     try
     {
         this.CheckDisposed();
         if (this.m_State == null)
         {
             throw new InvalidOperationException(SR.GetString("net_listener_mustcall", new object[] { "Start()" }));
         }
         objectValue = new ListenerAsyncResult(this, state, callback);
         uint num = objectValue.QueueBeginGetContext();
         if ((num != 0) && (num != 0x3e5))
         {
             throw new HttpListenerException((int) num);
         }
     }
     catch (Exception exception)
     {
         if (Logging.On)
         {
             Logging.Exception(Logging.HttpListener, this, "BeginGetContext", exception);
         }
         throw;
     }
     finally
     {
         if (Logging.On)
         {
             Logging.Enter(Logging.HttpListener, this, "BeginGetContext", "IAsyncResult#" + ValidationHelper.HashString(objectValue));
         }
     }
     return objectValue;
 }
Exemple #29
0
 internal AsyncRequestContext(ThreadPoolBoundHandle boundHandle, ListenerAsyncResult result)
 {
     _result = result;
     BaseConstruction(Allocate(boundHandle, 0));
 }
        internal void Complete(HttpListenerContext context, bool synch)
        {
            if (_forward != null)
            {
                _forward.Complete(context, synch);
                return;
            }
            _synch   = synch;
            _context = context;
            lock (_locker)
            {
                bool authFailure = false;
                try
                {
                    context.AuthenticationSchemes = context._listener.SelectAuthenticationScheme(context);
                }
                catch (OutOfMemoryException oom)
                {
                    context.AuthenticationSchemes = AuthenticationSchemes.Anonymous;
                    _exception = oom;
                }
                catch
                {
                    authFailure = true;
                    context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                }

                if (context.AuthenticationSchemes != AuthenticationSchemes.None &&
                    (context.AuthenticationSchemes & AuthenticationSchemes.Anonymous) != AuthenticationSchemes.Anonymous &&
                    (context.AuthenticationSchemes & AuthenticationSchemes.Basic) != AuthenticationSchemes.Basic)
                {
                    authFailure = true;
                    context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
                }
                else if (context.AuthenticationSchemes == AuthenticationSchemes.Basic)
                {
                    HttpStatusCode errorCode  = HttpStatusCode.Unauthorized;
                    string         authHeader = context.Request.Headers["Authorization"];
                    if (authHeader == null ||
                        !HttpListenerContext.IsBasicHeader(authHeader) ||
                        authHeader.Length < AuthenticationTypes.Basic.Length + 2 ||
                        !HttpListenerContext.TryParseBasicAuth(authHeader.Substring(AuthenticationTypes.Basic.Length + 1), out errorCode, out string _, out string __))
                    {
                        authFailure = true;
                        context.Response.StatusCode = (int)errorCode;
                        if (errorCode == HttpStatusCode.Unauthorized)
                        {
                            context.Response.Headers["WWW-Authenticate"] = context.AuthenticationSchemes + " realm=\"" + context._listener.Realm + "\"";
                        }
                    }
                }

                if (authFailure)
                {
                    context.Response.OutputStream.Close();
                    IAsyncResult ares = context._listener.BeginGetContext(_cb, _state);
                    _forward = (ListenerAsyncResult)ares;
                    lock (_forward._locker)
                    {
                        if (_handle != null)
                        {
                            _forward._handle = _handle;
                        }
                    }
                    ListenerAsyncResult next = _forward;
                    for (int i = 0; next._forward != null; i++)
                    {
                        if (i > 20)
                        {
                            Complete(new HttpListenerException((int)HttpStatusCode.Unauthorized, SR.net_listener_auth_errors));
                        }
                        next = next._forward;
                    }
                }
                else
                {
                    _completed = true;
                    _synch     = false;

                    if (_handle != null)
                    {
                        _handle.Set();
                    }

                    if (_cb != null)
                    {
                        ThreadPool.UnsafeQueueUserWorkItem(s_invokeCB, this);
                    }
                }
            }
        }
        public IAsyncResult BeginGetContext(AsyncCallback callback, object state) {
            if(Logging.On)Logging.Enter(Logging.HttpListener, this, "BeginGetContext", "");
            ListenerAsyncResult asyncResult = null;
            try {
                CheckDisposed();
                if (m_State==State.Stopped) {
                    throw new InvalidOperationException(SR.GetString(SR.net_listener_mustcall, "Start()"));
                }
                // prepare the ListenerAsyncResult object (this will have it's own
                // event that the user can wait on for IO completion - which means we
                // need to signal it when IO completes)
                asyncResult = new ListenerAsyncResult(this, state, callback);
                uint statusCode = asyncResult.QueueBeginGetContext();
                if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS &&
                    statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_IO_PENDING)
                {
                    // someother bad error, possible(?) return values are:
                    // ERROR_INVALID_HANDLE, ERROR_INSUFFICIENT_BUFFER, ERROR_OPERATION_ABORTED
                    throw new HttpListenerException((int)statusCode);
                }
            } catch (Exception exception) {
                if(Logging.On)Logging.Exception(Logging.HttpListener, this, "BeginGetContext", exception);
                throw;
            } finally {
                if(Logging.On)Logging.Enter(Logging.HttpListener, this, "BeginGetContext", "IAsyncResult#" + ValidationHelper.HashString(asyncResult));
            }

            return asyncResult;
        }