Fix binding for MexHttps
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / SvcHttpHandler.cs
1 //
2 // SvcHttpHandler.cs
3 //
4 // Author:
5 //      Ankit Jain  <jankit@novell.com>
6 //      Atsushi Enomoto <atsushi@ximian.com>
7 //
8 // Copyright (C) 2006,2009-2010 Novell, Inc.  http://www.novell.com
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29 using System;
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.Linq;
33 using System.Web;
34 using System.Threading;
35
36 using System.ServiceModel;
37 using System.ServiceModel.Activation;
38 using System.ServiceModel.Channels.Http;
39 using System.ServiceModel.Configuration;
40 using System.ServiceModel.Description;
41
42 namespace System.ServiceModel.Channels
43 {
44         internal class SvcHttpHandler : IHttpHandler
45         {
46                 internal static SvcHttpHandler Current;
47
48                 static object type_lock = new object ();
49
50                 Type type;
51                 Type factory_type;
52                 string path;
53                 ServiceHostBase host;
54                 Dictionary<HttpContext,ManualResetEvent> wcf_wait_handles = new Dictionary<HttpContext,ManualResetEvent> ();
55                 int close_state;
56
57                 public SvcHttpHandler (Type type, Type factoryType, string path)
58                 {
59                         this.type = type;
60                         this.factory_type = factoryType;
61                         this.path = path;
62                 }
63
64                 public bool IsReusable 
65                 {
66                         get { return true; }
67                 }
68
69                 public ServiceHostBase Host {
70                         get { return host; }
71                 }
72
73                 public void ProcessRequest (HttpContext context)
74                 {
75                         EnsureServiceHost ();
76
77                         var table = HttpListenerManagerTable.GetOrCreate (host);
78                         var manager = table.GetOrCreateManager (context.Request.Url, null);
79                         if (manager == null)
80                                 manager = table.GetOrCreateManager (host.BaseAddresses [0], null);
81                         var wait = new ManualResetEvent (false);
82                         wcf_wait_handles [context] = wait;
83                         manager.ProcessNewContext (new System.ServiceModel.Channels.Http.AspNetHttpContextInfo (this, context));
84                         // This method must not return until the RequestContext
85                         // explicitly finishes replying. Otherwise xsp will
86                         // close the connection after this method call.
87                         wait.WaitOne ();
88                 }
89
90                 public void EndHttpRequest (HttpContext context)
91                 {
92                         ManualResetEvent wait;
93                         if (!wcf_wait_handles.TryGetValue (context, out wait))
94                                 return;
95
96                         wcf_wait_handles.Remove (context);
97                         if (wait != null)
98                                 wait.Set ();
99                 }
100
101                 // called from SvcHttpHandlerFactory's remove callback (i.e.
102                 // unloading asp.net). It closes ServiceHost, then the host
103                 // in turn closes the listener and the channels it opened.
104                 // The channel listener calls CloseServiceChannel() to stop
105                 // accepting further requests on its shutdown.
106                 public void Close ()
107                 {
108                         host.Close ();
109                         host = null;
110                 }
111
112                 void EnsureServiceHost ()
113                 {
114                         lock (type_lock) {
115                                 Current = this;
116                                 try {
117                                         EnsureServiceHostCore ();
118                                 } finally {
119                                         Current = null;
120                                 }
121                         }
122                 }
123
124                 void EnsureServiceHostCore ()
125                 {
126                         if (host != null)
127                                 return;
128
129                         //ServiceHost for this not created yet
130                         var baseUri = new Uri (new Uri (HttpContext.Current.Request.Url.GetLeftPart (UriPartial.Authority)), path);
131 //                      if (factory_type != null) {
132 //                              host = ((ServiceHostFactory) Activator.CreateInstance (factory_type)).CreateServiceHost (type, new Uri [] {baseUri});
133 //                      }
134 //                      else
135                                 host = new ServiceHost (type, baseUri);
136                         host.Extensions.Add (new VirtualPathExtension (baseUri.AbsolutePath));
137
138                         host.Open ();
139                 }
140         }
141 }