[Mono.Security]: Add new MonoTlsProviderFactory.CreateHttpListener() API to create...
[mono.git] / mcs / class / System / System.Net / ListenerAsyncResult.cs
index aaf53b18ea71d6e53ad7afcbbddd01d30280621b..88f75e88a9941e4c7457f763497bc9f04416d6b7 100644 (file)
@@ -28,7 +28,7 @@
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
 
-#if NET_2_0 && SECURITY_DEP
+#if SECURITY_DEP
 
 using System.Threading;
 namespace System.Net {
@@ -42,6 +42,8 @@ namespace System.Net {
                HttpListenerContext context;
                object locker = new object ();
                ListenerAsyncResult forward;
+               internal bool EndCalled;
+               internal bool InGet;
 
                public ListenerAsyncResult (AsyncCallback cb, object state)
                {
@@ -49,32 +51,37 @@ namespace System.Net {
                        this.state = state;
                }
 
-               internal void Complete (string error)
+               internal void Complete (Exception exc)
                {
                        if (forward != null) {
-                               forward.Complete (error);
+                               forward.Complete (exc);
                                return;
                        }
-                       //FIXME: error_code?
-                       exception = new HttpListenerException (0, error);
+                       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;
                        if (ares.forward != null) {
-                               ares.forward.cb (ares);
+                               InvokeCallback (ares.forward);
                                return;
                        }
-                       ares.cb (ares);
+                       try {
+                               ares.cb (ares);
+                       } catch {
+                       }
                }
 
                internal void Complete (HttpListenerContext context)
@@ -91,28 +98,33 @@ namespace System.Net {
                        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.Listener.InternalEndGetContext (this);
                                        context.Response.StatusCode = 401;
-                                       context.Response.Headers ["WWW-Authenticate"] = schemes + " realm=\"\"";
+                                       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;
-                                       if (handle != null)
-                                               forward.handle = handle;
+                                       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");
+                                                       Complete (new HttpListenerException (400, "Too many authentication errors"));
                                                next = next.forward;
                                        }
-                               } else if (cb != null)
-                                       ThreadPool.QueueUserWorkItem (InvokeCallback, this);
+                               } else {
+                                       completed = true;
+                    this.synch = false;
+
+                                       if (handle != null)
+                                               handle.Set ();
+
+                                       if (cb != null)
+                                               ThreadPool.UnsafeQueueUserWorkItem (InvokeCB, this);
+                               }
                        }
                }