//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.ServiceModel.Channels { using System; using System.Diagnostics; using System.Runtime; using System.ServiceModel; using System.ServiceModel.Dispatcher; using System.ServiceModel.Security; abstract class ServerReliableChannelBinder : ReliableChannelBinder, IServerReliableChannelBinder where TChannel : class, IChannel { static string addressedPropertyName = "MessageAddressedByBinderProperty"; IChannelListener listener; static AsyncCallback onAcceptChannelComplete = Fx.ThunkCallback(new AsyncCallback(OnAcceptChannelCompleteStatic)); EndpointAddress cachedLocalAddress; TChannel pendingChannel; InterruptibleWaitObject pendingChannelEvent = new InterruptibleWaitObject(false, false); EndpointAddress remoteAddress; protected ServerReliableChannelBinder(ChannelBuilder builder, EndpointAddress remoteAddress, MessageFilter filter, int priority, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(null, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { this.listener = builder.BuildChannelListener(filter, priority); this.remoteAddress = remoteAddress; } protected ServerReliableChannelBinder(TChannel channel, EndpointAddress cachedLocalAddress, EndpointAddress remoteAddress, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(channel, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { this.cachedLocalAddress = cachedLocalAddress; this.remoteAddress = remoteAddress; } protected override bool CanGetChannelForReceive { get { return true; } } public override EndpointAddress LocalAddress { get { if (this.cachedLocalAddress != null) { return this.cachedLocalAddress; } else { return this.GetInnerChannelLocalAddress(); } } } protected override bool MustCloseChannel { get { return this.MustOpenChannel || this.HasSession; } } protected override bool MustOpenChannel { get { return this.listener != null; } } public override EndpointAddress RemoteAddress { get { return this.remoteAddress; } } void AddAddressedProperty(Message message) { message.Properties.Add(addressedPropertyName, new object()); } protected override void AddOutputHeaders(Message message) { if (this.GetAddressedProperty(message) == null) { this.RemoteAddress.ApplyTo(message); this.AddAddressedProperty(message); } } public bool AddressResponse(Message request, Message response) { if (this.GetAddressedProperty(response) != null) { throw Fx.AssertAndThrow("The binder can't address a response twice"); } try { RequestReplyCorrelator.PrepareReply(response, request); } catch (MessageHeaderException exception) { // ---- it - we don't need to correlate the reply if the MessageId header is bad if (DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information); } bool sendResponse = true; try { sendResponse = RequestReplyCorrelator.AddressReply(response, request); } catch (MessageHeaderException exception) { // ---- it - we don't need to address the reply if the addressing headers are bad if (DiagnosticUtility.ShouldTraceInformation) DiagnosticUtility.TraceHandledException(exception, TraceEventType.Information); } if (sendResponse) this.AddAddressedProperty(response); return sendResponse; } protected override IAsyncResult BeginTryGetChannel(TimeSpan timeout, AsyncCallback callback, object state) { return this.pendingChannelEvent.BeginTryWait(timeout, callback, state); } public IAsyncResult BeginWaitForRequest(TimeSpan timeout, AsyncCallback callback, object state) { if (this.DefaultMaskingMode != MaskingMode.None) { throw Fx.AssertAndThrow("This method was implemented only for the case where we do not mask exceptions."); } if (this.ValidateInputOperation(timeout)) { return new WaitForRequestAsyncResult(this, timeout, callback, state); } else { return new CompletedAsyncResult(callback, state); } } bool CompleteAcceptChannel(IAsyncResult result) { TChannel channel = this.listener.EndAcceptChannel(result); if (channel == null) { return false; } if (!this.UseNewChannel(channel)) { channel.Abort(); } return true; } public static IServerReliableChannelBinder CreateBinder(ChannelBuilder builder, EndpointAddress remoteAddress, MessageFilter filter, int priority, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) { Type type = typeof(TChannel); if (type == typeof(IDuplexChannel)) { return new DuplexServerReliableChannelBinder(builder, remoteAddress, filter, priority, MaskingMode.None, defaultCloseTimeout, defaultSendTimeout); } else if (type == typeof(IDuplexSessionChannel)) { return new DuplexSessionServerReliableChannelBinder(builder, remoteAddress, filter, priority, MaskingMode.None, faultMode, defaultCloseTimeout, defaultSendTimeout); } else if (type == typeof(IReplyChannel)) { return new ReplyServerReliableChannelBinder(builder, remoteAddress, filter, priority, MaskingMode.None, defaultCloseTimeout, defaultSendTimeout); } else if (type == typeof(IReplySessionChannel)) { return new ReplySessionServerReliableChannelBinder(builder, remoteAddress, filter, priority, MaskingMode.None, faultMode, defaultCloseTimeout, defaultSendTimeout); } else { throw Fx.AssertAndThrow("ServerReliableChannelBinder supports creation of IDuplexChannel, IDuplexSessionChannel, IReplyChannel, and IReplySessionChannel only."); } } public static IServerReliableChannelBinder CreateBinder(TChannel channel, EndpointAddress cachedLocalAddress, EndpointAddress remoteAddress, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) { Type type = typeof(TChannel); if (type == typeof(IDuplexChannel)) { return new DuplexServerReliableChannelBinder((IDuplexChannel)channel, cachedLocalAddress, remoteAddress, MaskingMode.All, defaultCloseTimeout, defaultSendTimeout); } else if (type == typeof(IDuplexSessionChannel)) { return new DuplexSessionServerReliableChannelBinder((IDuplexSessionChannel)channel, cachedLocalAddress, remoteAddress, MaskingMode.All, faultMode, defaultCloseTimeout, defaultSendTimeout); } else if (type == typeof(IReplyChannel)) { return new ReplyServerReliableChannelBinder((IReplyChannel)channel, cachedLocalAddress, remoteAddress, MaskingMode.All, defaultCloseTimeout, defaultSendTimeout); } else if (type == typeof(IReplySessionChannel)) { return new ReplySessionServerReliableChannelBinder((IReplySessionChannel)channel, cachedLocalAddress, remoteAddress, MaskingMode.All, faultMode, defaultCloseTimeout, defaultSendTimeout); } else { throw Fx.AssertAndThrow("ServerReliableChannelBinder supports creation of IDuplexChannel, IDuplexSessionChannel, IReplyChannel, and IReplySessionChannel only."); } } protected override bool EndTryGetChannel(IAsyncResult result) { if (!this.pendingChannelEvent.EndTryWait(result)) return false; TChannel abortChannel = null; lock (this.ThisLock) { if (this.State != CommunicationState.Faulted && this.State != CommunicationState.Closing && this.State != CommunicationState.Closed) { if (!this.Synchronizer.SetChannel(this.pendingChannel)) { abortChannel = this.pendingChannel; } this.pendingChannel = null; this.pendingChannelEvent.Reset(); } } if (abortChannel != null) { abortChannel.Abort(); } return true; } public bool EndWaitForRequest(IAsyncResult result) { WaitForRequestAsyncResult waitForRequestResult = result as WaitForRequestAsyncResult; if (waitForRequestResult != null) { return waitForRequestResult.End(); } else { CompletedAsyncResult.End(result); return true; } } object GetAddressedProperty(Message message) { object property; message.Properties.TryGetValue(addressedPropertyName, out property); return property; } protected abstract EndpointAddress GetInnerChannelLocalAddress(); bool IsListenerExceptionNullOrHandleable(Exception e) { if (e == null) { return true; } if (this.listener.State == CommunicationState.Faulted) { return false; } return this.IsHandleable(e); } protected override void OnAbort() { if (this.listener != null) { this.listener.Abort(); } } void OnAcceptChannelComplete(IAsyncResult result) { Exception expectedException = null; Exception unexpectedException = null; bool gotChannel = false; try { gotChannel = this.CompleteAcceptChannel(result); } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } if (this.IsHandleable(e)) { expectedException = e; } else { unexpectedException = e; } } if (gotChannel) { this.StartAccepting(); } else if (unexpectedException != null) { this.Fault(unexpectedException); } else if ((expectedException != null) && (this.listener.State == CommunicationState.Opened)) { this.StartAccepting(); } else if (this.listener.State == CommunicationState.Faulted) { this.Fault(expectedException); } } static void OnAcceptChannelCompleteStatic(IAsyncResult result) { if (!result.CompletedSynchronously) { ServerReliableChannelBinder binder = (ServerReliableChannelBinder)result.AsyncState; binder.OnAcceptChannelComplete(result); } } protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state) { if (this.listener != null) { return this.listener.BeginClose(timeout, callback, state); } else { return new CompletedAsyncResult(callback, state); } } protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) { if (this.listener != null) { return this.listener.BeginOpen(timeout, callback, state); } else { return new CompletedAsyncResult(callback, state); } } protected abstract IAsyncResult OnBeginWaitForRequest(TChannel channel, TimeSpan timeout, AsyncCallback callback, object state); protected override void OnClose(TimeSpan timeout) { if (this.listener != null) { this.listener.Close(timeout); } } protected override void OnShutdown() { TChannel channel = null; lock (this.ThisLock) { channel = this.pendingChannel; this.pendingChannel = null; this.pendingChannelEvent.Set(); } if (channel != null) channel.Abort(); } protected abstract bool OnWaitForRequest(TChannel channel, TimeSpan timeout); protected override void OnEndClose(IAsyncResult result) { if (this.listener != null) { this.listener.EndClose(result); } else { CompletedAsyncResult.End(result); } } protected override void OnEndOpen(IAsyncResult result) { if (this.listener != null) { this.listener.EndOpen(result); this.StartAccepting(); } else { CompletedAsyncResult.End(result); } } protected abstract bool OnEndWaitForRequest(TChannel channel, IAsyncResult result); protected override void OnOpen(TimeSpan timeout) { if (this.listener != null) { this.listener.Open(timeout); this.StartAccepting(); } } void StartAccepting() { Exception expectedException = null; Exception unexpectedException = null; while (this.listener.State == CommunicationState.Opened) { expectedException = null; unexpectedException = null; try { IAsyncResult result = this.listener.BeginAcceptChannel(TimeSpan.MaxValue, onAcceptChannelComplete, this); if (!result.CompletedSynchronously) { return; } else if (!this.CompleteAcceptChannel(result)) { break; } } catch (Exception e) { if (Fx.IsFatal(e)) { throw; } if (this.IsHandleable(e)) { expectedException = e; continue; } else { unexpectedException = e; break; } } } if (unexpectedException != null) { this.Fault(unexpectedException); } else if (this.listener.State == CommunicationState.Faulted) { this.Fault(expectedException); } } protected override bool TryGetChannel(TimeSpan timeout) { if (!this.pendingChannelEvent.Wait(timeout)) return false; TChannel abortChannel = null; lock (this.ThisLock) { if (this.State != CommunicationState.Faulted && this.State != CommunicationState.Closing && this.State != CommunicationState.Closed) { if (!this.Synchronizer.SetChannel(this.pendingChannel)) { abortChannel = this.pendingChannel; } this.pendingChannel = null; this.pendingChannelEvent.Reset(); } } if (abortChannel != null) { abortChannel.Abort(); } return true; } public bool UseNewChannel(IChannel channel) { TChannel oldPendingChannel = null; TChannel oldBinderChannel = null; lock (this.ThisLock) { if (!this.Synchronizer.TolerateFaults || this.State == CommunicationState.Faulted || this.State == CommunicationState.Closing || this.State == CommunicationState.Closed) { return false; } else { oldPendingChannel = this.pendingChannel; this.pendingChannel = (TChannel)channel; oldBinderChannel = this.Synchronizer.AbortCurentChannel(); } } if (oldPendingChannel != null) { oldPendingChannel.Abort(); } this.pendingChannelEvent.Set(); if (oldBinderChannel != null) { oldBinderChannel.Abort(); } return true; } public bool WaitForRequest(TimeSpan timeout) { if (this.DefaultMaskingMode != MaskingMode.None) { throw Fx.AssertAndThrow("This method was implemented only for the case where we do not mask exceptions."); } if (!this.ValidateInputOperation(timeout)) { return true; } TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); while (true) { bool autoAborted = false; try { TChannel channel; bool success = !this.Synchronizer.TryGetChannelForInput(true, timeoutHelper.RemainingTime(), out channel); if (channel == null) { return success; } try { return this.OnWaitForRequest(channel, timeoutHelper.RemainingTime()); } finally { autoAborted = this.Synchronizer.Aborting; this.Synchronizer.ReturnChannel(); } } catch (Exception e) { if (Fx.IsFatal(e)) throw; if (!this.HandleException(e, this.DefaultMaskingMode, autoAborted)) { throw; } else { continue; } } } } abstract class DuplexServerReliableChannelBinder : ServerReliableChannelBinder where TDuplexChannel : class, IDuplexChannel { protected DuplexServerReliableChannelBinder(ChannelBuilder builder, EndpointAddress remoteAddress, MessageFilter filter, int priority, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(builder, remoteAddress, filter, priority, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { } protected DuplexServerReliableChannelBinder(TDuplexChannel channel, EndpointAddress cachedLocalAddress, EndpointAddress remoteAddress, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(channel, cachedLocalAddress, remoteAddress, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { } public override bool CanSendAsynchronously { get { return true; } } protected override EndpointAddress GetInnerChannelLocalAddress() { IDuplexChannel channel = this.Synchronizer.CurrentChannel; EndpointAddress localAddress = (channel == null) ? null : channel.LocalAddress; return localAddress; } protected override IAsyncResult OnBeginSend(TDuplexChannel channel, Message message, TimeSpan timeout, AsyncCallback callback, object state) { return channel.BeginSend(message, timeout, callback, state); } protected override IAsyncResult OnBeginTryReceive(TDuplexChannel channel, TimeSpan timeout, AsyncCallback callback, object state) { return channel.BeginTryReceive(timeout, callback, state); } protected override IAsyncResult OnBeginWaitForRequest(TDuplexChannel channel, TimeSpan timeout, AsyncCallback callback, object state) { return channel.BeginWaitForMessage(timeout, callback, state); } protected override void OnEndSend(TDuplexChannel channel, IAsyncResult result) { channel.EndSend(result); } protected override bool OnEndTryReceive(TDuplexChannel channel, IAsyncResult result, out RequestContext requestContext) { Message message; bool success = channel.EndTryReceive(result, out message); if (success) { this.OnMessageReceived(message); } requestContext = this.WrapMessage(message); return success; } protected override bool OnEndWaitForRequest(TDuplexChannel channel, IAsyncResult result) { return channel.EndWaitForMessage(result); } protected abstract void OnMessageReceived(Message message); protected override void OnSend(TDuplexChannel channel, Message message, TimeSpan timeout) { channel.Send(message, timeout); } protected override bool OnTryReceive(TDuplexChannel channel, TimeSpan timeout, out RequestContext requestContext) { Message message; bool success = channel.TryReceive(timeout, out message); if (success) { this.OnMessageReceived(message); } requestContext = this.WrapMessage(message); return success; } protected override bool OnWaitForRequest(TDuplexChannel channel, TimeSpan timeout) { return channel.WaitForMessage(timeout); } } sealed class DuplexServerReliableChannelBinder : DuplexServerReliableChannelBinder { public DuplexServerReliableChannelBinder(ChannelBuilder builder, EndpointAddress remoteAddress, MessageFilter filter, int priority, MaskingMode maskingMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(builder, remoteAddress, filter, priority, maskingMode, TolerateFaultsMode.Never, defaultCloseTimeout, defaultSendTimeout) { } public DuplexServerReliableChannelBinder(IDuplexChannel channel, EndpointAddress cachedLocalAddress, EndpointAddress remoteAddress, MaskingMode maskingMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(channel, cachedLocalAddress, remoteAddress, maskingMode, TolerateFaultsMode.Never, defaultCloseTimeout, defaultSendTimeout) { } public override bool HasSession { get { return false; } } public override ISession GetInnerSession() { return null; } protected override bool HasSecuritySession(IDuplexChannel channel) { return false; } protected override void OnMessageReceived(Message message) { } } sealed class DuplexSessionServerReliableChannelBinder : DuplexServerReliableChannelBinder { public DuplexSessionServerReliableChannelBinder(ChannelBuilder builder, EndpointAddress remoteAddress, MessageFilter filter, int priority, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(builder, remoteAddress, filter, priority, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { } public DuplexSessionServerReliableChannelBinder(IDuplexSessionChannel channel, EndpointAddress cachedLocalAddress, EndpointAddress remoteAddress, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(channel, cachedLocalAddress, remoteAddress, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { } public override bool HasSession { get { return true; } } protected override IAsyncResult BeginCloseChannel(IDuplexSessionChannel channel, TimeSpan timeout, AsyncCallback callback, object state) { return ReliableChannelBinderHelper.BeginCloseDuplexSessionChannel(this, channel, timeout, callback, state); } protected override void CloseChannel(IDuplexSessionChannel channel, TimeSpan timeout) { ReliableChannelBinderHelper.CloseDuplexSessionChannel(this, channel, timeout); } protected override void EndCloseChannel(IDuplexSessionChannel channel, IAsyncResult result) { ReliableChannelBinderHelper.EndCloseDuplexSessionChannel(channel, result); } public override ISession GetInnerSession() { return this.Synchronizer.CurrentChannel.Session; } protected override bool HasSecuritySession(IDuplexSessionChannel channel) { return channel.Session is ISecuritySession; } protected override void OnMessageReceived(Message message) { if (message == null) this.Synchronizer.OnReadEof(); } } abstract class ReplyServerReliableChannelBinder : ServerReliableChannelBinder where TReplyChannel : class, IReplyChannel { public ReplyServerReliableChannelBinder(ChannelBuilder builder, EndpointAddress remoteAddress, MessageFilter filter, int priority, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(builder, remoteAddress, filter, priority, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { } public ReplyServerReliableChannelBinder(TReplyChannel channel, EndpointAddress cachedLocalAddress, EndpointAddress remoteAddress, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(channel, cachedLocalAddress, remoteAddress, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { } public override bool CanSendAsynchronously { get { return false; } } protected override EndpointAddress GetInnerChannelLocalAddress() { IReplyChannel channel = this.Synchronizer.CurrentChannel; EndpointAddress localAddress = (channel == null) ? null : channel.LocalAddress; return localAddress; } protected override IAsyncResult OnBeginTryReceive(TReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state) { return channel.BeginTryReceiveRequest(timeout, callback, state); } protected override IAsyncResult OnBeginWaitForRequest(TReplyChannel channel, TimeSpan timeout, AsyncCallback callback, object state) { return channel.BeginWaitForRequest(timeout, callback, state); } protected override bool OnEndTryReceive(TReplyChannel channel, IAsyncResult result, out RequestContext requestContext) { bool success = channel.EndTryReceiveRequest(result, out requestContext); if (success && (requestContext == null)) { this.OnReadNullMessage(); } requestContext = this.WrapRequestContext(requestContext); return success; } protected override bool OnEndWaitForRequest(TReplyChannel channel, IAsyncResult result) { return channel.EndWaitForRequest(result); } protected virtual void OnReadNullMessage() { } protected override bool OnTryReceive(TReplyChannel channel, TimeSpan timeout, out RequestContext requestContext) { bool success = channel.TryReceiveRequest(timeout, out requestContext); if (success && (requestContext == null)) { this.OnReadNullMessage(); } requestContext = this.WrapRequestContext(requestContext); return success; } protected override bool OnWaitForRequest(TReplyChannel channel, TimeSpan timeout) { return channel.WaitForRequest(timeout); } } sealed class ReplyServerReliableChannelBinder : ReplyServerReliableChannelBinder { public ReplyServerReliableChannelBinder(ChannelBuilder builder, EndpointAddress remoteAddress, MessageFilter filter, int priority, MaskingMode maskingMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(builder, remoteAddress, filter, priority, maskingMode, TolerateFaultsMode.Never, defaultCloseTimeout, defaultSendTimeout) { } public ReplyServerReliableChannelBinder(IReplyChannel channel, EndpointAddress cachedLocalAddress, EndpointAddress remoteAddress, MaskingMode maskingMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(channel, cachedLocalAddress, remoteAddress, maskingMode, TolerateFaultsMode.Never, defaultCloseTimeout, defaultSendTimeout) { } public override bool HasSession { get { return false; } } public override ISession GetInnerSession() { return null; } protected override bool HasSecuritySession(IReplyChannel channel) { return false; } } sealed class ReplySessionServerReliableChannelBinder : ReplyServerReliableChannelBinder { public ReplySessionServerReliableChannelBinder(ChannelBuilder builder, EndpointAddress remoteAddress, MessageFilter filter, int priority, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(builder, remoteAddress, filter, priority, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { } public ReplySessionServerReliableChannelBinder(IReplySessionChannel channel, EndpointAddress cachedLocalAddress, EndpointAddress remoteAddress, MaskingMode maskingMode, TolerateFaultsMode faultMode, TimeSpan defaultCloseTimeout, TimeSpan defaultSendTimeout) : base(channel, cachedLocalAddress, remoteAddress, maskingMode, faultMode, defaultCloseTimeout, defaultSendTimeout) { } public override bool HasSession { get { return true; } } protected override IAsyncResult BeginCloseChannel(IReplySessionChannel channel, TimeSpan timeout, AsyncCallback callback, object state) { return ReliableChannelBinderHelper.BeginCloseReplySessionChannel(this, channel, timeout, callback, state); } protected override void CloseChannel(IReplySessionChannel channel, TimeSpan timeout) { ReliableChannelBinderHelper.CloseReplySessionChannel(this, channel, timeout); } protected override void EndCloseChannel(IReplySessionChannel channel, IAsyncResult result) { ReliableChannelBinderHelper.EndCloseReplySessionChannel(channel, result); } public override ISession GetInnerSession() { return this.Synchronizer.CurrentChannel.Session; } protected override bool HasSecuritySession(IReplySessionChannel channel) { return channel.Session is ISecuritySession; } protected override void OnReadNullMessage() { this.Synchronizer.OnReadEof(); } } sealed class WaitForRequestAsyncResult : InputAsyncResult> { public WaitForRequestAsyncResult(ServerReliableChannelBinder binder, TimeSpan timeout, AsyncCallback callback, object state) : base(binder, true, timeout, binder.DefaultMaskingMode, callback, state) { if (this.Start()) this.Complete(true); } protected override IAsyncResult BeginInput( ServerReliableChannelBinder binder, TChannel channel, TimeSpan timeout, AsyncCallback callback, object state) { return binder.OnBeginWaitForRequest(channel, timeout, callback, state); } protected override bool EndInput(ServerReliableChannelBinder binder, TChannel channel, IAsyncResult result, out bool complete) { complete = true; return binder.OnEndWaitForRequest(channel, result); } } } }