Xamarin Public Jenkins (auto-signing) e79aa3c0ed Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
2016-08-03 10:59:49 +00:00

222 lines
6.8 KiB
C#

//----------------------------------------------------------------------------
// Copyright (c) Microsoft Corporation. All rights reserved.
//----------------------------------------------------------------------------
namespace System.ServiceModel.Channels
{
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Diagnostics;
using System.ServiceModel;
using System.Threading;
using System.ServiceModel.Diagnostics;
class SharedTcpTransportManager : TcpTransportManager, ITransportManagerRegistration
{
SharedConnectionListener listener;
ConnectionDemuxer connectionDemuxer;
HostNameComparisonMode hostNameComparisonMode;
Uri listenUri;
int queueId;
Guid token;
Func<Uri, int> onDuplicatedViaCallback;
bool demuxerCreated;
public SharedTcpTransportManager(Uri listenUri, TcpChannelListener channelListener)
{
this.HostNameComparisonMode = channelListener.HostNameComparisonMode;
this.listenUri = listenUri;
// For port sharing, we apply all of the settings from channel listener to the transport manager.
this.ApplyListenerSettings(channelListener);
}
protected SharedTcpTransportManager(Uri listenUri)
{
this.listenUri = listenUri;
}
protected override bool IsCompatible(TcpChannelListener channelListener)
{
if (channelListener.HostedVirtualPath == null && !channelListener.PortSharingEnabled)
{
return false;
}
return base.IsCompatible(channelListener);
}
public HostNameComparisonMode HostNameComparisonMode
{
get
{
return this.hostNameComparisonMode;
}
set
{
HostNameComparisonModeHelper.Validate(value);
lock (base.ThisLock)
{
ThrowIfOpen();
this.hostNameComparisonMode = value;
}
}
}
public Uri ListenUri
{
get
{
return this.listenUri;
}
}
internal override void OnOpen()
{
OnOpenInternal(0, Guid.Empty);
}
protected virtual Action<Uri> GetOnViaCallback()
{
return null;
}
// This method is called only for the first via of the current proxy.
int OnDuplicatedVia(Uri via)
{
Action<Uri> onVia = GetOnViaCallback();
if (onVia != null)
{
onVia(via);
}
if (!demuxerCreated)
{
lock (ThisLock)
{
if (listener == null)
{
// The listener has been stopped.
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationObjectAbortedException(
SR.GetString(SR.Sharing_ListenerProxyStopped)));
}
if (!demuxerCreated)
{
CreateConnectionDemuxer();
demuxerCreated = true;
}
}
}
return this.ConnectionBufferSize;
}
void CreateConnectionDemuxer()
{
IConnectionListener connectionListener = new BufferedConnectionListener(listener, MaxOutputDelay, ConnectionBufferSize);
if (DiagnosticUtility.ShouldUseActivity)
{
connectionListener = new TracingConnectionListener(connectionListener, this.ListenUri);
}
connectionDemuxer = new ConnectionDemuxer(connectionListener,
MaxPendingAccepts, MaxPendingConnections, ChannelInitializationTimeout,
IdleTimeout, MaxPooledConnections,
OnGetTransportFactorySettings,
OnGetSingletonMessageHandler,
OnHandleServerSessionPreamble,
OnDemuxerError);
connectionDemuxer.StartDemuxing(this.GetOnViaCallback());
}
internal void OnOpenInternal(int queueId, Guid token)
{
lock (ThisLock)
{
this.queueId = queueId;
this.token = token;
BaseUriWithWildcard path = new BaseUriWithWildcard(this.ListenUri, this.HostNameComparisonMode);
if (this.onDuplicatedViaCallback == null)
{
this.onDuplicatedViaCallback = new Func<Uri, int>(OnDuplicatedVia);
}
listener = new SharedConnectionListener(path, queueId, token, this.onDuplicatedViaCallback);
// Delay the creation of the demuxer on the first request.
}
}
protected void CleanUp(bool aborting, TimeSpan timeout)
{
lock (ThisLock)
{
if (listener != null)
{
if (!aborting)
{
listener.Stop(timeout);
}
else
{
listener.Abort();
}
// The listener will be closed by the demuxer.
listener = null;
}
if (connectionDemuxer != null)
{
connectionDemuxer.Dispose();
}
demuxerCreated = false;
}
}
void Unregister()
{
TcpChannelListener.StaticTransportManagerTable.UnregisterUri(this.ListenUri, this.HostNameComparisonMode);
}
internal override void OnAbort()
{
CleanUp(true, TimeSpan.Zero);
Unregister();
base.OnAbort();
}
internal override void OnClose(TimeSpan timeout)
{
CleanUp(false, timeout);
Unregister();
}
protected virtual void OnSelecting(TcpChannelListener channelListener)
{
}
IList<TransportManager> ITransportManagerRegistration.Select(TransportChannelListener channelListener)
{
if (!channelListener.IsScopeIdCompatible(this.hostNameComparisonMode, this.listenUri))
{
return null;
}
OnSelecting((TcpChannelListener)channelListener);
IList<TransportManager> result = null;
if (this.IsCompatible((TcpChannelListener)channelListener))
{
result = new List<TransportManager>();
result.Add(this);
}
return result;
}
}
}