using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+using System.Linq;
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;
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)
{
- if (typeof (TChannel) == typeof (IReplyChannel))
- return (TChannel) (object) new HttpSimpleReplyChannel ((HttpSimpleChannelListener<IReplyChannel>) (object) this);
-
- // FIXME: implement more
- throw new NotImplementedException ();
+ lock (creator_lock) {
+ return CreateChannelCore (timeout);
+ }
}
- protected override void OnOpen (TimeSpan timeout)
+ TChannel CreateChannelCore (TimeSpan timeout)
{
- base.OnOpen (timeout);
- StartListening (timeout);
- }
+ if (typeof (TChannel) == typeof (IReplyChannel))
+ return (TChannel) (object) new HttpSimpleReplyChannel ((HttpSimpleChannelListener<IReplyChannel>) (object) this);
- protected override void OnClose (TimeSpan timeout)
- {
- base.OnClose (timeout);
- httpChannelManager.Stop ();
+ throw new NotSupportedException (String.Format ("Channel type {0} is not supported", typeof (TChannel)));
}
- void StartListening (TimeSpan timeout)
+ protected override HttpListenerManager CreateListenerManager ()
{
- httpChannelManager = new HttpListenerManager<TChannel> (this);
- httpChannelManager.Open (timeout);
+ return new HttpSimpleListenerManager (this, Source, SecurityTokenManager, ChannelDispatcher);
}
}
if (typeof (TChannel) == typeof (IReplyChannel))
return (TChannel) (object) new AspNetReplyChannel ((AspNetChannelListener<IReplyChannel>) (object) this);
- // FIXME: implement more
- throw new NotImplementedException ();
+ throw new NotSupportedException (String.Format ("Channel type {0} is not supported", typeof (TChannel)));
+ }
+
+ protected override HttpListenerManager CreateListenerManager ()
+ {
+ return new AspNetListenerManager (this, Source, SecurityTokenManager, ChannelDispatcher);
}
}
- internal abstract class HttpChannelListenerBase<TChannel> : ChannelListenerBase<TChannel>
+ internal abstract class HttpChannelListenerBase<TChannel> : InternalChannelListenerBase<TChannel>
where TChannel : class, IChannel
{
- HttpTransportBindingElement source;
- BindingContext context;
- Uri listen_uri;
List<TChannel> channels = new List<TChannel> ();
MessageEncoder encoder;
+ HttpListenerManager httpChannelManager;
+
+ internal static HttpChannelListenerBase<TChannel>CurrentHttpChannelListener;
public HttpChannelListenerBase (HttpTransportBindingElement source,
BindingContext context)
- : base (context.Binding)
+ : base (context)
{
- accept_channel_delegate = new Func<TimeSpan,TChannel> (OnAcceptChannel);
+ 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));
- // FIXME: consider ListenUriMode
- // FIXME: there should be some way to post-provide Uri in case of null listenerUri in context.
- listen_uri = context.ListenUriBaseAddress != null ?
- new Uri (context.ListenUriBaseAddress, context.ListenUriRelativeAddress) : null;
foreach (BindingElement be in context.RemainingBindingElements) {
MessageEncodingBindingElement mbe = be as MessageEncodingBindingElement;
if (mbe != null) {
}
if (encoder == null)
encoder = new TextMessageEncoder (MessageVersion.Default, Encoding.UTF8);
- }
- public MessageEncoder MessageEncoder {
- get { return encoder; }
+ if (context.BindingParameters.Contains (typeof (ServiceCredentials)))
+ SecurityTokenManager = new ServiceCredentialsSecurityTokenManager ((ServiceCredentials) context.BindingParameters [typeof (ServiceCredentials)]);
}
- public override Uri Uri {
- get { return listen_uri; }
+ internal ChannelDispatcher ChannelDispatcher { get; set; }
+
+ public HttpTransportBindingElement Source { get; private set; }
+
+ public HttpListenerManager ListenerManager {
+ get { return httpChannelManager; }
}
- protected IList<TChannel> Channels {
- get { return channels; }
+ public MessageEncoder MessageEncoder {
+ get { return encoder; }
}
+ public ServiceCredentialsSecurityTokenManager SecurityTokenManager { get; private set; }
+
protected override TChannel OnAcceptChannel (TimeSpan timeout)
{
TChannel ch = CreateChannel (timeout);
- Channels.Add (ch);
return ch;
}
protected abstract TChannel CreateChannel (TimeSpan timeout);
- Func<TimeSpan,TChannel> accept_channel_delegate;
-
- protected override IAsyncResult OnBeginAcceptChannel (
- TimeSpan timeout, AsyncCallback callback,
- object asyncState)
- {
- return accept_channel_delegate.BeginInvoke (timeout, callback, asyncState);
- }
-
- protected override TChannel OnEndAcceptChannel (IAsyncResult result)
- {
- return accept_channel_delegate.EndInvoke (result);
- }
-
- protected override IAsyncResult OnBeginWaitForChannel (
- TimeSpan timeout, AsyncCallback callback, object state)
- {
- throw new NotImplementedException ();
- }
-
- protected override bool OnEndWaitForChannel (IAsyncResult result)
- {
- throw new NotImplementedException ();
- }
-
protected override bool OnWaitForChannel (TimeSpan timeout)
{
throw new NotImplementedException ();
}
- protected override IAsyncResult OnBeginOpen (TimeSpan timeout,
- AsyncCallback callback, object state)
- {
- throw new NotImplementedException ();
- }
+ protected abstract HttpListenerManager CreateListenerManager ();
- protected override void OnEndOpen (IAsyncResult result)
- {
- throw new NotImplementedException ();
- }
-
- [MonoTODO]
- protected override IAsyncResult OnBeginClose (TimeSpan timeout,
- AsyncCallback callback, object state)
- {
- throw new NotImplementedException ();
- }
-
- [MonoTODO]
- protected override void OnEndClose (IAsyncResult result)
+ protected override void OnOpen (TimeSpan timeout)
{
- throw new NotImplementedException ();
+ httpChannelManager = CreateListenerManager ();
+ Properties.Add (httpChannelManager);
+ httpChannelManager.Open (timeout);
}
- [MonoTODO ("find out what to do here.")]
protected override void OnAbort ()
{
- }
-
- protected override void OnOpen (TimeSpan timeout)
- {
+ httpChannelManager.Stop (true);
}
protected override void OnClose (TimeSpan timeout)
{
- foreach (TChannel ch in Channels)
- ch.Close(timeout);
+ 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);
}
}
}