Enable the System build for monodroid
[mono.git] / mcs / class / System / System.Net / ListenerAsyncResult.cs
index c63f047231d8e5343bf2a9226ae72310708b742d..c0b6854a2d3c198479a1e80846cd73919824f947 100644 (file)
@@ -41,6 +41,7 @@ namespace System.Net {
                Exception exception;
                HttpListenerContext context;
                object locker = new object ();
+               ListenerAsyncResult forward;
 
                public ListenerAsyncResult (AsyncCallback cb, object state)
                {
@@ -50,6 +51,10 @@ namespace System.Net {
 
                internal void Complete (string error)
                {
+                       if (forward != null) {
+                               forward.Complete (error);
+                               return;
+                       }
                        //FIXME: error_code?
                        exception = new HttpListenerException (0, error);
                        lock (locker) {
@@ -65,7 +70,14 @@ namespace System.Net {
                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)
@@ -75,26 +87,45 @@ 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 ();
-
-                               if ((context.Listener.AuthenticationSchemes == AuthenticationSchemes.Basic || context.Listener.AuthenticationSchemes == AuthenticationSchemes.Negotiate) && context.Request.Headers ["Authorization"] == null) {
-                                       context.Listener.EndGetContext (this);
+                               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"] = AuthenticationSchemes.Basic + " realm=\"\"";
+                                       context.Response.Headers ["WWW-Authenticate"] = schemes + " realm=\"" + context.Listener.Realm + "\"";
                                        context.Response.OutputStream.Close ();
-                                       context.Listener.BeginGetContext (cb, state);
-                               } else if (cb != null)
-                                       ThreadPool.QueueUserWorkItem (InvokeCallback, this);
+                                       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 ("Too many authentication errors");
+                                               next = next.forward;
+                                       }
+                               } else {
+                                       completed = true;
+                                       if (handle != null)
+                                               handle.Set ();
+
+                                       if (cb != null)
+                                               ThreadPool.QueueUserWorkItem (InvokeCallback, this);
+                               }
                        }
                }
 
                internal HttpListenerContext GetContext ()
                {
+                       if (forward != null)
+                               return forward.GetContext ();
                        if (exception != null)
                                throw exception;
 
@@ -102,11 +133,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);
@@ -117,11 +155,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;
                                }