[System]: WebRequest.GetSystemProxy(): Return custom proxy for monodroid.
[mono.git] / mcs / class / System / System.Net / ListenerAsyncResult.cs
index 7d21718f0b8181a0fdfee2cf79c4d2ed684b6c4d..88f75e88a9941e4c7457f763497bc9f04416d6b7 100644 (file)
@@ -27,7 +27,9 @@
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-#if NET_2_0
+
+#if SECURITY_DEP
+
 using System.Threading;
 namespace System.Net {
        class ListenerAsyncResult : IAsyncResult {
@@ -39,6 +41,9 @@ namespace System.Net {
                Exception exception;
                HttpListenerContext context;
                object locker = new object ();
+               ListenerAsyncResult forward;
+               internal bool EndCalled;
+               internal bool InGet;
 
                public ListenerAsyncResult (AsyncCallback cb, object state)
                {
@@ -46,24 +51,37 @@ namespace System.Net {
                        this.state = state;
                }
 
-               internal void Complete (string error)
+               internal void Complete (Exception exc)
                {
-                       //FIXME: error_code?
-                       exception = new HttpListenerException (0, error);
+                       if (forward != null) {
+                               forward.Complete (exc);
+                               return;
+                       }
+                       exception = exc;
+                       if (InGet && (exc is ObjectDisposedException))
+                               exception = new HttpListenerException (500, "Listener closed");
                        lock (locker) {
                                completed = true;
                                if (handle != null)
                                        handle.Set ();
 
                                if (cb != null)
-                                       ThreadPool.QueueUserWorkItem (InvokeCallback, this);
+                                       ThreadPool.UnsafeQueueUserWorkItem (InvokeCB, this);
                        }
                }
 
+               static WaitCallback InvokeCB = new WaitCallback (InvokeCallback);
                static void InvokeCallback (object o)
                {
                        ListenerAsyncResult ares = (ListenerAsyncResult) o;
-                       ares.cb (ares);
+                       if (ares.forward != null) {
+                               InvokeCallback (ares.forward);
+                               return;
+                       }
+                       try {
+                               ares.cb (ares);
+                       } catch {
+                       }
                }
 
                internal void Complete (HttpListenerContext context)
@@ -73,20 +91,47 @@ namespace System.Net {
 
                internal void Complete (HttpListenerContext context, bool synch)
                {
+                       if (forward != null) {
+                               forward.Complete (context, synch);
+                               return;
+                       }
                        this.synch = synch;
                        this.context = context;
                        lock (locker) {
-                               completed = true;
-                               if (handle != null)
-                                       handle.Set ();
+                               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;
+                    this.synch = false;
 
-                               if (cb != null)
-                                       ThreadPool.QueueUserWorkItem (InvokeCallback, this);
+                                       if (handle != null)
+                                               handle.Set ();
+
+                                       if (cb != null)
+                                               ThreadPool.UnsafeQueueUserWorkItem (InvokeCB, this);
+                               }
                        }
                }
 
                internal HttpListenerContext GetContext ()
                {
+                       if (forward != null)
+                               return forward.GetContext ();
                        if (exception != null)
                                throw exception;
 
@@ -94,11 +139,18 @@ namespace System.Net {
                }
                
                public object AsyncState {
-                       get { return state; }
+                       get {
+                               if (forward != null)
+                                       return forward.AsyncState;
+                               return state;
+                       }
                }
 
                public WaitHandle AsyncWaitHandle {
                        get {
+                               if (forward != null)
+                                       return forward.AsyncWaitHandle;
+
                                lock (locker) {
                                        if (handle == null)
                                                handle = new ManualResetEvent (completed);
@@ -109,11 +161,19 @@ namespace System.Net {
                }
 
                public bool CompletedSynchronously {
-                       get { return synch; }
+                       get {
+                               if (forward != null)
+                                       return forward.CompletedSynchronously;
+                               return synch;
+                       }
+
                }
 
                public bool IsCompleted {
                        get {
+                               if (forward != null)
+                                       return forward.IsCompleted;
+
                                lock (locker) {
                                        return completed;
                                }