164 lines
5.8 KiB
C#
164 lines
5.8 KiB
C#
|
//------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Channels
|
||
|
{
|
||
|
using System.Net;
|
||
|
using System.Runtime;
|
||
|
using System.ServiceModel;
|
||
|
using System.Xml;
|
||
|
|
||
|
interface IPeerFactory : ITransportFactorySettings
|
||
|
{
|
||
|
IPAddress ListenIPAddress { get; }
|
||
|
int Port { get; }
|
||
|
XmlDictionaryReaderQuotas ReaderQuotas { get; }
|
||
|
PeerResolver Resolver { get; }
|
||
|
PeerSecurityManager SecurityManager { get; }
|
||
|
PeerNodeImplementation PrivatePeerNode { get; set; }
|
||
|
long MaxBufferPoolSize { get; }
|
||
|
}
|
||
|
|
||
|
[ObsoleteAttribute ("PeerChannel feature is obsolete and will be removed in the future.", false)]
|
||
|
sealed class PeerChannelFactory<TChannel> : TransportChannelFactory<TChannel>, IPeerFactory
|
||
|
{
|
||
|
// settings passed to PeerNode
|
||
|
IPAddress listenIPAddress;
|
||
|
int port;
|
||
|
PeerResolver resolver;
|
||
|
PeerSecurityManager securityManager;
|
||
|
XmlDictionaryReaderQuotas readerQuotas;
|
||
|
ISecurityCapabilities securityCapabilities;
|
||
|
|
||
|
// use a private mesh (PeerNode) rather than creating/retrieving one from the registry.
|
||
|
// used as a test hook to allow multiple PeerNode instances per app domain
|
||
|
PeerNodeImplementation privatePeerNode;
|
||
|
|
||
|
internal PeerChannelFactory(PeerTransportBindingElement bindingElement, BindingContext context,
|
||
|
PeerResolver peerResolver)
|
||
|
: base(bindingElement, context)
|
||
|
{
|
||
|
this.listenIPAddress = bindingElement.ListenIPAddress;
|
||
|
this.port = bindingElement.Port;
|
||
|
this.resolver = peerResolver;
|
||
|
readerQuotas = new XmlDictionaryReaderQuotas();
|
||
|
BinaryMessageEncodingBindingElement encoder = context.Binding.Elements.Find<BinaryMessageEncodingBindingElement>();
|
||
|
if (encoder != null)
|
||
|
encoder.ReaderQuotas.CopyTo(this.readerQuotas);
|
||
|
else
|
||
|
EncoderDefaults.ReaderQuotas.CopyTo(this.readerQuotas);
|
||
|
this.securityManager = PeerSecurityManager.Create(bindingElement.Security, context, this.readerQuotas);
|
||
|
this.securityCapabilities = bindingElement.GetProperty<ISecurityCapabilities>(context);
|
||
|
}
|
||
|
|
||
|
public IPAddress ListenIPAddress
|
||
|
{
|
||
|
get { return listenIPAddress; }
|
||
|
}
|
||
|
|
||
|
public int Port
|
||
|
{
|
||
|
get { return port; }
|
||
|
}
|
||
|
|
||
|
public XmlDictionaryReaderQuotas ReaderQuotas
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.readerQuotas;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public PeerResolver Resolver
|
||
|
{
|
||
|
get { return resolver; }
|
||
|
}
|
||
|
|
||
|
public override string Scheme
|
||
|
{
|
||
|
get { return PeerStrings.Scheme; }
|
||
|
}
|
||
|
|
||
|
public PeerNodeImplementation PrivatePeerNode
|
||
|
{
|
||
|
get { return privatePeerNode; }
|
||
|
set { privatePeerNode = value; }
|
||
|
}
|
||
|
|
||
|
public PeerSecurityManager SecurityManager
|
||
|
{
|
||
|
get { return this.securityManager; }
|
||
|
set { this.securityManager = value; }
|
||
|
}
|
||
|
|
||
|
public override T GetProperty<T>()
|
||
|
{
|
||
|
if (typeof(T) == typeof(PeerChannelFactory<TChannel>))
|
||
|
{
|
||
|
return (T)(object)this;
|
||
|
}
|
||
|
else if (typeof(T) == typeof(IPeerFactory))
|
||
|
{
|
||
|
return (T)(object)this;
|
||
|
}
|
||
|
else if (typeof(T) == typeof(PeerNodeImplementation))
|
||
|
{
|
||
|
return (T)(object)privatePeerNode;
|
||
|
}
|
||
|
else if (typeof(T) == typeof(ISecurityCapabilities))
|
||
|
{
|
||
|
return (T)(object)this.securityCapabilities;
|
||
|
}
|
||
|
|
||
|
return base.GetProperty<T>();
|
||
|
}
|
||
|
|
||
|
protected override void OnOpen(TimeSpan timeout)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
|
||
|
{
|
||
|
return new CompletedAsyncResult(callback, state);
|
||
|
}
|
||
|
|
||
|
protected override void OnEndOpen(IAsyncResult result)
|
||
|
{
|
||
|
CompletedAsyncResult.End(result);
|
||
|
}
|
||
|
|
||
|
protected override TChannel OnCreateChannel(EndpointAddress to, Uri via)
|
||
|
{
|
||
|
base.ValidateScheme(via);
|
||
|
|
||
|
PeerNodeImplementation peerNode = null;
|
||
|
PeerNodeImplementation.Registration registration = null;
|
||
|
|
||
|
// use the private PeerNode if it has been configured and matches the channel
|
||
|
// otherwise have the channel look for one or create a new one
|
||
|
if (privatePeerNode != null && via.Host == privatePeerNode.MeshId)
|
||
|
{
|
||
|
peerNode = privatePeerNode;
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
registration = new PeerNodeImplementation.Registration(via, this);
|
||
|
}
|
||
|
|
||
|
if (typeof(TChannel) == typeof(IOutputChannel))
|
||
|
{
|
||
|
return (TChannel)(object)new PeerOutputChannel(peerNode, registration, this, to, via, this.MessageVersion);
|
||
|
}
|
||
|
|
||
|
// typeof(TChannel) == typeof(IDuplexChannel)
|
||
|
// 'to' is both the remote address and the local address
|
||
|
PeerDuplexChannel duplexChannel = new PeerDuplexChannel(peerNode, registration, this, to, via);
|
||
|
PeerMessageDispatcher<IDuplexChannel, PeerDuplexChannel>.PeerMessageQueueAdapter queueHandler = new PeerMessageDispatcher<IDuplexChannel, PeerDuplexChannel>.PeerMessageQueueAdapter(duplexChannel);
|
||
|
PeerMessageDispatcher<IDuplexChannel, PeerDuplexChannel> dispatcher = new PeerMessageDispatcher<IDuplexChannel, PeerDuplexChannel>(queueHandler, duplexChannel.InnerNode, this, to, via);
|
||
|
duplexChannel.Dispatcher = dispatcher;
|
||
|
return (TChannel)(object)duplexChannel;
|
||
|
}
|
||
|
}
|
||
|
}
|