183 lines
5.7 KiB
C#
183 lines
5.7 KiB
C#
|
//----------------------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Activation
|
||
|
{
|
||
|
using System.Collections.Generic;
|
||
|
using System.Diagnostics;
|
||
|
using System.ServiceModel;
|
||
|
using System.ServiceModel.Channels;
|
||
|
using System.ServiceModel.Diagnostics;
|
||
|
|
||
|
class HostedNamedPipeTransportManager : NamedPipeTransportManager
|
||
|
{
|
||
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
||
|
volatile bool settingsApplied;
|
||
|
Action<Uri> onViaCallback;
|
||
|
SharedConnectionListener listener;
|
||
|
ConnectionDemuxer connectionDemuxer;
|
||
|
int queueId;
|
||
|
Guid token;
|
||
|
Func<Uri, int> onDuplicatedViaCallback;
|
||
|
|
||
|
// Double-checked locking pattern requires volatile for read/write synchronization
|
||
|
volatile bool demuxerCreated;
|
||
|
|
||
|
public HostedNamedPipeTransportManager(BaseUriWithWildcard baseAddress)
|
||
|
: base(baseAddress.BaseAddress)
|
||
|
{
|
||
|
this.HostNameComparisonMode = baseAddress.HostNameComparisonMode;
|
||
|
this.onViaCallback = new Action<Uri>(OnVia);
|
||
|
this.onDuplicatedViaCallback = new Func<Uri, int>(OnDuplicatedVia);
|
||
|
}
|
||
|
|
||
|
protected override bool IsCompatible(NamedPipeChannelListener channelListener)
|
||
|
{
|
||
|
if (channelListener.HostedVirtualPath == null)
|
||
|
{
|
||
|
return false;
|
||
|
}
|
||
|
|
||
|
return base.IsCompatible(channelListener);
|
||
|
}
|
||
|
|
||
|
internal void Start(int queueId, Guid token, Action messageReceivedCallback)
|
||
|
{
|
||
|
SetMessageReceivedCallback(messageReceivedCallback);
|
||
|
OnOpenInternal(queueId, token);
|
||
|
}
|
||
|
|
||
|
internal override void OnOpen()
|
||
|
{
|
||
|
// This is intentionally empty.
|
||
|
}
|
||
|
|
||
|
internal override void OnAbort()
|
||
|
{
|
||
|
}
|
||
|
|
||
|
internal void Stop(TimeSpan timeout)
|
||
|
{
|
||
|
Cleanup(false, timeout);
|
||
|
}
|
||
|
|
||
|
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;
|
||
|
settingsApplied = false;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
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(onViaCallback);
|
||
|
}
|
||
|
|
||
|
void OnOpenInternal(int queueId, Guid token)
|
||
|
{
|
||
|
lock (ThisLock)
|
||
|
{
|
||
|
this.queueId = queueId;
|
||
|
this.token = token;
|
||
|
|
||
|
BaseUriWithWildcard path = new BaseUriWithWildcard(this.ListenUri, this.HostNameComparisonMode);
|
||
|
|
||
|
listener = new SharedConnectionListener(path, queueId, token, this.onDuplicatedViaCallback);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal override void OnClose(TimeSpan timeout)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
void OnVia(Uri address)
|
||
|
{
|
||
|
Debug.Print("HostedNamedPipeTransportManager.OnVia() address: " + address + " calling EnsureServiceAvailable()");
|
||
|
ServiceHostingEnvironment.EnsureServiceAvailable(address.LocalPath);
|
||
|
}
|
||
|
|
||
|
protected override void OnSelecting(NamedPipeChannelListener channelListener)
|
||
|
{
|
||
|
if (settingsApplied)
|
||
|
{
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
lock (ThisLock)
|
||
|
{
|
||
|
if (settingsApplied)
|
||
|
{
|
||
|
// Use the setting for the first one.
|
||
|
return;
|
||
|
}
|
||
|
|
||
|
this.ApplyListenerSettings(channelListener);
|
||
|
settingsApplied = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// This method is called only for the first via of the current proxy.
|
||
|
int OnDuplicatedVia(Uri via)
|
||
|
{
|
||
|
OnVia(via);
|
||
|
|
||
|
if (!demuxerCreated)
|
||
|
{
|
||
|
lock (ThisLock)
|
||
|
{
|
||
|
if (listener == null)
|
||
|
{
|
||
|
// The listener has been stopped.
|
||
|
throw FxTrace.Exception.AsError(new CommunicationObjectAbortedException(SR.PipeListenerProxyStopped));
|
||
|
}
|
||
|
|
||
|
if (!demuxerCreated)
|
||
|
{
|
||
|
CreateConnectionDemuxer();
|
||
|
demuxerCreated = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return this.ConnectionBufferSize;
|
||
|
}
|
||
|
}
|
||
|
}
|