[Mono.Security]: Add 'MonoTlsProvider.SupportsCleanShutdown' and 'MonoTlsSettings...
[mono.git] / mcs / class / System / System.Net / ListenerAsyncResult.cs
1 //
2 // System.Net.ListenerAsyncResult
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // Copyright (c) 2005 Ximian, Inc (http://www.ximian.com)
8 //
9
10 //
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30
31 using System.Threading;
32 namespace System.Net {
33         class ListenerAsyncResult : IAsyncResult {
34                 ManualResetEvent handle;
35                 bool synch;
36                 bool completed;
37                 AsyncCallback cb;
38                 object state;
39                 Exception exception;
40                 HttpListenerContext context;
41                 object locker = new object ();
42                 ListenerAsyncResult forward;
43                 internal bool EndCalled;
44                 internal bool InGet;
45
46                 public ListenerAsyncResult (AsyncCallback cb, object state)
47                 {
48                         this.cb = cb;
49                         this.state = state;
50                 }
51
52                 internal void Complete (Exception exc)
53                 {
54                         if (forward != null) {
55                                 forward.Complete (exc);
56                                 return;
57                         }
58                         exception = exc;
59                         if (InGet && (exc is ObjectDisposedException))
60                                 exception = new HttpListenerException (500, "Listener closed");
61                         lock (locker) {
62                                 completed = true;
63                                 if (handle != null)
64                                         handle.Set ();
65
66                                 if (cb != null)
67                                         ThreadPool.UnsafeQueueUserWorkItem (InvokeCB, this);
68                         }
69                 }
70
71                 static WaitCallback InvokeCB = new WaitCallback (InvokeCallback);
72                 static void InvokeCallback (object o)
73                 {
74                         ListenerAsyncResult ares = (ListenerAsyncResult) o;
75                         if (ares.forward != null) {
76                                 InvokeCallback (ares.forward);
77                                 return;
78                         }
79                         try {
80                                 ares.cb (ares);
81                         } catch {
82                         }
83                 }
84
85                 internal void Complete (HttpListenerContext context)
86                 {
87                         Complete (context, false);
88                 }
89
90                 internal void Complete (HttpListenerContext context, bool synch)
91                 {
92                         if (forward != null) {
93                                 forward.Complete (context, synch);
94                                 return;
95                         }
96                         this.synch = synch;
97                         this.context = context;
98                         lock (locker) {
99                                 AuthenticationSchemes schemes = context.Listener.SelectAuthenticationScheme (context);
100                                 if ((schemes == AuthenticationSchemes.Basic || context.Listener.AuthenticationSchemes == AuthenticationSchemes.Negotiate) && context.Request.Headers ["Authorization"] == null) {
101                                         context.Response.StatusCode = 401;
102                                         context.Response.Headers ["WWW-Authenticate"] = schemes + " realm=\"" + context.Listener.Realm + "\"";
103                                         context.Response.OutputStream.Close ();
104                                         IAsyncResult ares = context.Listener.BeginGetContext (cb, state);
105                                         this.forward = (ListenerAsyncResult) ares;
106                                         lock (forward.locker) {
107                                                 if (handle != null)
108                                                         forward.handle = handle;
109                                         }
110                                         ListenerAsyncResult next = forward;
111                                         for (int i = 0; next.forward != null; i++) {
112                                                 if (i > 20)
113                                                         Complete (new HttpListenerException (400, "Too many authentication errors"));
114                                                 next = next.forward;
115                                         }
116                                 } else {
117                                         completed = true;
118                     this.synch = false;
119
120                                         if (handle != null)
121                                                 handle.Set ();
122
123                                         if (cb != null)
124                                                 ThreadPool.UnsafeQueueUserWorkItem (InvokeCB, this);
125                                 }
126                         }
127                 }
128
129                 internal HttpListenerContext GetContext ()
130                 {
131                         if (forward != null)
132                                 return forward.GetContext ();
133                         if (exception != null)
134                                 throw exception;
135
136                         return context;
137                 }
138                 
139                 public object AsyncState {
140                         get {
141                                 if (forward != null)
142                                         return forward.AsyncState;
143                                 return state;
144                         }
145                 }
146
147                 public WaitHandle AsyncWaitHandle {
148                         get {
149                                 if (forward != null)
150                                         return forward.AsyncWaitHandle;
151
152                                 lock (locker) {
153                                         if (handle == null)
154                                                 handle = new ManualResetEvent (completed);
155                                 }
156                                 
157                                 return handle;
158                         }
159                 }
160
161                 public bool CompletedSynchronously {
162                         get {
163                                 if (forward != null)
164                                         return forward.CompletedSynchronously;
165                                 return synch;
166                         }
167
168                 }
169
170                 public bool IsCompleted {
171                         get {
172                                 if (forward != null)
173                                         return forward.IsCompleted;
174
175                                 lock (locker) {
176                                         return completed;
177                                 }
178                         }
179                 }
180         }
181 }
182