PageRenderTime 46ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System.ServiceModel/System.ServiceModel.Channels/SvcHttpHandler.cs

https://bitbucket.org/steenlund/mono-2.6.7-for-amiga
C# | 218 lines | 146 code | 28 blank | 44 comment | 14 complexity | 2c90da0fd6c4807d252344dabd5ac441 MD5 | raw file
Possible License(s): LGPL-2.0, MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, LGPL-2.1
  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 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. using System.ServiceModel;
  36. using System.ServiceModel.Activation;
  37. using System.ServiceModel.Configuration;
  38. using System.ServiceModel.Description;
  39. namespace System.ServiceModel.Channels {
  40. internal class WcfListenerInfo
  41. {
  42. public WcfListenerInfo ()
  43. {
  44. Pending = new List<HttpContext> ();
  45. ProcessRequestHandles = new List<ManualResetEvent> ();
  46. }
  47. public IChannelListener Listener { get; set; }
  48. public List<ManualResetEvent> ProcessRequestHandles { get; private set; }
  49. public List<HttpContext> Pending { get; private set; }
  50. }
  51. internal class WcfListenerInfoCollection : KeyedCollection<IChannelListener,WcfListenerInfo>
  52. {
  53. protected override IChannelListener GetKeyForItem (WcfListenerInfo info)
  54. {
  55. return info.Listener;
  56. }
  57. }
  58. internal class SvcHttpHandler : IHttpHandler
  59. {
  60. static object type_lock = new object ();
  61. Type type;
  62. Type factory_type;
  63. string path;
  64. ServiceHostBase host;
  65. WcfListenerInfoCollection listeners = new WcfListenerInfoCollection ();
  66. Dictionary<HttpContext,AutoResetEvent> wcf_wait_handles = new Dictionary<HttpContext,AutoResetEvent> ();
  67. AutoResetEvent wait_for_request_handle = new AutoResetEvent (false);
  68. int close_state;
  69. public SvcHttpHandler (Type type, Type factoryType, string path)
  70. {
  71. this.type = type;
  72. this.factory_type = factoryType;
  73. this.path = path;
  74. }
  75. public bool IsReusable
  76. {
  77. get { return true; }
  78. }
  79. public ServiceHostBase Host {
  80. get { return host; }
  81. }
  82. public HttpContext WaitForRequest (IChannelListener listener)
  83. {
  84. if (close_state > 0)
  85. return null;
  86. var wait = new ManualResetEvent (false);
  87. var info = listeners [listener];
  88. if (info.Pending.Count == 0) {
  89. info.ProcessRequestHandles.Add (wait);
  90. wait_for_request_handle.Set ();
  91. wait.WaitOne ();
  92. info.ProcessRequestHandles.Remove (wait);
  93. }
  94. var ctx = listeners [listener].Pending [0];
  95. listeners [listener].Pending.RemoveAt (0);
  96. return ctx;
  97. }
  98. IChannelListener FindBestMatchListener (HttpContext ctx)
  99. {
  100. var actx = new AspNetHttpContextInfo (ctx);
  101. // Select the best-match listener.
  102. IChannelListener best = null;
  103. string rel = null;
  104. foreach (var li in listeners) {
  105. var l = li.Listener;
  106. if (!l.GetProperty<HttpListenerManager> ().FilterHttpContext (actx))
  107. continue;
  108. if (l.Uri.Equals (ctx.Request.Url)) {
  109. best = l;
  110. break;
  111. }
  112. }
  113. // FIXME: the matching must be better-considered.
  114. foreach (var li in listeners) {
  115. var l = li.Listener;
  116. if (!l.GetProperty<HttpListenerManager> ().FilterHttpContext (actx))
  117. continue;
  118. if (!ctx.Request.Url.ToString ().StartsWith (l.Uri.ToString (), StringComparison.Ordinal))
  119. continue;
  120. if (best == null)
  121. best = l;
  122. }
  123. return best;
  124. /*
  125. var actx = new AspNetHttpContextInfo (ctx);
  126. foreach (var i in listeners)
  127. if (i.Listener.GetProperty<HttpListenerManager> ().FilterHttpContext (actx))
  128. return i.Listener;
  129. throw new InvalidOperationException ();
  130. */
  131. }
  132. public void ProcessRequest (HttpContext context)
  133. {
  134. EnsureServiceHost ();
  135. var wait = new AutoResetEvent (false);
  136. var l = FindBestMatchListener (context);
  137. var i = listeners [l];
  138. lock (i) {
  139. i.Pending.Add (context);
  140. wcf_wait_handles [context] = wait;
  141. if (i.ProcessRequestHandles.Count > 0)
  142. i.ProcessRequestHandles [0].Set ();
  143. }
  144. wait.WaitOne ();
  145. }
  146. public void EndRequest (IChannelListener listener, HttpContext context)
  147. {
  148. var wait = wcf_wait_handles [context];
  149. wcf_wait_handles.Remove (context);
  150. wait.Set ();
  151. }
  152. // called from SvcHttpHandlerFactory's remove callback (i.e.
  153. // unloading asp.net). It closes ServiceHost, then the host
  154. // in turn closes the listener and the channels it opened.
  155. // The channel listener calls CloseServiceChannel() to stop
  156. // accepting further requests on its shutdown.
  157. public void Close ()
  158. {
  159. host.Close ();
  160. host = null;
  161. }
  162. public void RegisterListener (IChannelListener listener)
  163. {
  164. lock (type_lock)
  165. listeners.Add (new WcfListenerInfo () {Listener = listener});
  166. }
  167. public void UnregisterListener (IChannelListener listener)
  168. {
  169. listeners.Remove (listener);
  170. }
  171. void EnsureServiceHost ()
  172. {
  173. lock (type_lock) {
  174. if (host != null)
  175. return;
  176. //ServiceHost for this not created yet
  177. var baseUri = new Uri (new Uri (HttpContext.Current.Request.Url.GetLeftPart (UriPartial.Authority)), path);
  178. if (factory_type != null) {
  179. host = ((ServiceHostFactory) Activator.CreateInstance (factory_type)).CreateServiceHost (type, new Uri [] {baseUri});
  180. }
  181. else
  182. host = new ServiceHost (type, baseUri);
  183. host.Extensions.Add (new VirtualPathExtension (baseUri.AbsolutePath));
  184. host.Open ();
  185. // Not precise, but it needs some wait time to have all channels start requesting. And it is somehow required.
  186. Thread.Sleep (500);
  187. }
  188. }
  189. }
  190. }