New tests.
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / HttpChannelListener.cs
index 0b8ff30d5af616c28022097d46ac6ae8310ecc02..988d431c508e8402f8023c85f9eca6361bb680ee 100644 (file)
@@ -33,6 +33,7 @@ using System.Net;
 using System.Net.Security;
 using System.ServiceModel;
 using System.ServiceModel.Description;
+using System.ServiceModel.Dispatcher;
 using System.ServiceModel.Security;
 using System.Text;
 
@@ -41,18 +42,12 @@ namespace System.ServiceModel.Channels
        internal class HttpSimpleChannelListener<TChannel> : HttpChannelListenerBase<TChannel>
                where TChannel : class, IChannel
        {
-               HttpListenerManager<TChannel> httpChannelManager;
-
                public HttpSimpleChannelListener (HttpTransportBindingElement source,
                        BindingContext context)
                        : base (source, context)
                {
                }
 
-               public HttpListener Http {
-                       get {  return httpChannelManager.HttpListener; }
-               }
-
                object creator_lock = new object ();
 
                protected override TChannel CreateChannel (TimeSpan timeout)
@@ -66,39 +61,13 @@ namespace System.ServiceModel.Channels
                {
                        if (typeof (TChannel) == typeof (IReplyChannel))
                                return (TChannel) (object) new HttpSimpleReplyChannel ((HttpSimpleChannelListener<IReplyChannel>) (object) this);
-                       // FIXME: session channel support
-                       if (typeof (TChannel) == typeof (IReplySessionChannel))
-                               throw new NotImplementedException ();
 
                        throw new NotSupportedException (String.Format ("Channel type {0} is not supported", typeof (TChannel)));
                }
 
-               protected override void OnOpen (TimeSpan timeout)
-               {
-                       base.OnOpen (timeout);
-                       StartListening (timeout);
-               }
-
-               protected override void OnAbort ()
-               {
-                       httpChannelManager.Stop (true);
-               }
-
-               protected override void OnClose (TimeSpan timeout)
-               {
-                       if (State == CommunicationState.Closed)
-                               return;
-                       base.OnClose (timeout);
-                       // FIXME: it is said that channels are not closed
-                       // when the channel listener is closed.
-                       // http://blogs.msdn.com/drnick/archive/2006/03/22/557642.aspx
-                       httpChannelManager.Stop (false);
-               }
-
-               void StartListening (TimeSpan timeout)
+               protected override HttpListenerManager CreateListenerManager ()
                {
-                       httpChannelManager = new HttpListenerManager<TChannel> (this);
-                       httpChannelManager.Open (timeout);
+                       return new HttpSimpleListenerManager (this, Source, SecurityTokenManager, ChannelDispatcher);
                }
        }
 
@@ -111,56 +80,42 @@ namespace System.ServiceModel.Channels
                {
                }
 
-               SvcHttpHandler http_handler;
-               internal SvcHttpHandler HttpHandler {
-                       get {
-                               if (http_handler == null)
-                                       http_handler = SvcHttpHandlerFactory.GetHandlerForListener (this);
-                               return http_handler;
-                       }
-               }
-
                protected override TChannel CreateChannel (TimeSpan timeout)
                {
                        if (typeof (TChannel) == typeof (IReplyChannel))
                                return (TChannel) (object) new AspNetReplyChannel ((AspNetChannelListener<IReplyChannel>) (object) this);
-                       // FIXME: session channel support
-                       if (typeof (TChannel) == typeof (IReplySessionChannel))
-                               throw new NotImplementedException ();
 
                        throw new NotSupportedException (String.Format ("Channel type {0} is not supported", typeof (TChannel)));
                }
 
-               protected override void OnAbort ()
-               {
-                       HttpHandler.UnregisterListener (this);
-               }
-
-               protected override void OnOpen (TimeSpan timeout)
+               protected override HttpListenerManager CreateListenerManager ()
                {
-                       base.OnOpen (timeout);
-                       HttpHandler.RegisterListener (this);
-               }
-
-               protected override void OnClose (TimeSpan timeout)
-               {
-                       HttpHandler.UnregisterListener (this);
-                       base.OnClose (timeout);
+                       return new AspNetListenerManager (this, Source, SecurityTokenManager, ChannelDispatcher);
                }
        }
 
        internal abstract class HttpChannelListenerBase<TChannel> : InternalChannelListenerBase<TChannel>
                where TChannel : class, IChannel
        {
-               HttpTransportBindingElement source;
-               BindingContext context;
                List<TChannel> channels = new List<TChannel> ();
                MessageEncoder encoder;
+               HttpListenerManager httpChannelManager;
+
+               internal static HttpChannelListenerBase<TChannel>CurrentHttpChannelListener;
 
                public HttpChannelListenerBase (HttpTransportBindingElement source,
                        BindingContext context)
                        : base (context)
                {
+                       if (ServiceHostBase.CurrentServiceHostHack != null)
+                               DispatcherBuilder.ChannelDispatcherSetter = delegate (ChannelDispatcher cd) { this.ChannelDispatcher = cd; };
+
+                       this.Source = source;
+                       // The null Uri check looks weird, but it seems the listener can be built without it.
+                       // See HttpTransportBindingElementTest.BuildChannelListenerWithoutListenUri().
+                       if (Uri != null && source.Scheme != Uri.Scheme)
+                               throw new ArgumentException (String.Format ("Requested listen uri scheme must be {0}, but was {1}.", source.Scheme, Uri.Scheme));
+
                        foreach (BindingElement be in context.RemainingBindingElements) {
                                MessageEncodingBindingElement mbe = be as MessageEncodingBindingElement;
                                if (mbe != null) {
@@ -170,12 +125,25 @@ namespace System.ServiceModel.Channels
                        }
                        if (encoder == null)
                                encoder = new TextMessageEncoder (MessageVersion.Default, Encoding.UTF8);
+
+                       if (context.BindingParameters.Contains (typeof (ServiceCredentials)))
+                               SecurityTokenManager = new ServiceCredentialsSecurityTokenManager ((ServiceCredentials) context.BindingParameters [typeof (ServiceCredentials)]);
+               }
+
+               internal ChannelDispatcher ChannelDispatcher { get; set; }
+
+               public HttpTransportBindingElement Source { get; private set; }
+
+               public HttpListenerManager ListenerManager {
+                       get {  return httpChannelManager; }
                }
 
                public MessageEncoder MessageEncoder {
                        get { return encoder; }
                }
 
+               public ServiceCredentialsSecurityTokenManager SecurityTokenManager { get; private set; }
+
                protected override TChannel OnAcceptChannel (TimeSpan timeout)
                {
                        TChannel ch = CreateChannel (timeout);
@@ -189,19 +157,28 @@ namespace System.ServiceModel.Channels
                        throw new NotImplementedException ();
                }
 
-               protected override void OnAbort ()
+               protected abstract HttpListenerManager CreateListenerManager ();
+
+               protected override void OnOpen (TimeSpan timeout)
                {
-                       OnClose (TimeSpan.Zero);
+                       httpChannelManager = CreateListenerManager ();
+                       Properties.Add (httpChannelManager);
+                       httpChannelManager.Open (timeout);
                }
 
-               protected override void OnOpen (TimeSpan timeout)
+               protected override void OnAbort ()
                {
+                       httpChannelManager.Stop (true);
                }
 
                protected override void OnClose (TimeSpan timeout)
                {
-                       DateTime start = DateTime.Now;
-                       base.OnClose (timeout - (DateTime.Now - start));
+                       if (State == CommunicationState.Closed)
+                               return;
+                       base.OnClose (timeout);
+                       // The channels are kept open when the creator channel listener is closed.
+                       // http://blogs.msdn.com/drnick/archive/2006/03/22/557642.aspx
+                       httpChannelManager.Stop (false);
                }
        }
 }