ServiceChannel.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ WCF / WCF / 3.5.30729.1 / untmp / Orcas / SP / ndp / cdf / src / WCF / ServiceModel / System / ServiceModel / Channels / ServiceChannel.cs / 1 / ServiceChannel.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Channels 
{
    using System.ServiceModel; 
    using System.ServiceModel.Dispatcher; 
    using System.Collections;
    using System.Collections.Generic; 
    using System.Diagnostics;
    using System.ServiceModel.Diagnostics;
    using System.IdentityModel.Claims;
    using System.IdentityModel.Policy; 
    using System.ServiceModel.Security.Tokens;
    using System.Net.Security; 
    using System.ServiceModel.Security; 
    using System.Threading;
    using System.Globalization; 
    using System.Xml;
    using System.Security;

    // This class is sealed because the constructor could call Abort, which is virtual 
    internal sealed class ServiceChannel : CommunicationObject, IChannel, IClientChannel, IDuplexContextChannel, IOutputChannel, IRequestChannel,IServiceChannel
    { 
        int activityCount = 0; 
        bool allowInitializationUI = true;
        bool allowOutputBatching = false; 
        bool autoClose = true;
        CallOnceManager autoDisplayUIManager;
        CallOnceManager autoOpenManager;
        readonly IChannelBinder binder; 
        readonly ChannelDispatcher channelDispatcher;
        ClientRuntime clientRuntime; 
        readonly bool closeBinder = true; 
        bool closeFactory;
        bool didInteractiveInitialization; 
        bool doneReceiving;
        EndpointDispatcher endpointDispatcher;
        bool explicitlyOpened;
        ExtensionCollection extensions; 
        readonly ServiceChannelFactory factory;
        readonly bool hasSession; 
        readonly SessionIdleManager idleManager; 
        InstanceContext instanceContext;
        ServiceThrottle instanceContextServiceThrottle; 
        bool isPending;
        readonly bool isReplyChannel;
        EndpointAddress localAddress;
        readonly MessageVersion messageVersion; 
        readonly bool openBinder = false;
        TimeSpan operationTimeout; 
        object proxy; 
        ServiceThrottle serviceThrottle;
        string terminatingOperationName; 
        InstanceContext wmiInstanceContext;
        bool wasChannelAutoClosed;

        EventHandler unknownMessageReceived; 

        ServiceChannel(IChannelBinder binder, MessageVersion messageVersion, IDefaultCommunicationTimeouts timeouts) 
        { 
            if (binder == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("binder");
            }

            this.messageVersion = messageVersion; 
            this.binder = binder;
            this.isReplyChannel = this.binder.Channel is IReplyChannel; 
 
            IChannel innerChannel = binder.Channel;
            this.hasSession = (innerChannel is ISessionChannel) || 
                        (innerChannel is ISessionChannel) ||
                        (innerChannel is ISessionChannel);

            this.binder.Channel.Faulted += OnInnerChannelFaulted; 
            this.IncrementActivity();
            this.openBinder = (binder.Channel.State == CommunicationState.Created); 
 
            this.operationTimeout = timeouts.SendTimeout;
        } 

        internal ServiceChannel(ServiceChannelFactory factory, IChannelBinder binder)
            : this(binder, factory.MessageVersion, factory)
        { 
            this.factory = factory;
            this.clientRuntime = factory.ClientRuntime; 
 
            DispatchRuntime dispatch = factory.ClientRuntime.DispatchRuntime;
            if (dispatch != null) 
            {
                this.autoClose = dispatch.AutomaticInputSessionShutdown;
            }
 
            factory.ChannelCreated(this);
        } 
 
        internal ServiceChannel(IChannelBinder binder,
                                EndpointDispatcher endpointDispatcher, 
                                ChannelDispatcher channelDispatcher,
                                SessionIdleManager idleManager)
            : this(binder, channelDispatcher.MessageVersion, channelDispatcher.DefaultCommunicationTimeouts)
        { 
            if (endpointDispatcher == null)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("endpointDispatcher"); 
            }
 
            this.channelDispatcher = channelDispatcher;
            this.endpointDispatcher = endpointDispatcher;
            this.clientRuntime = endpointDispatcher.DispatchRuntime.CallbackClientRuntime;
            this.autoClose = endpointDispatcher.DispatchRuntime.AutomaticInputSessionShutdown; 
            this.isPending = true;
 
            IDefaultCommunicationTimeouts timeouts = channelDispatcher.DefaultCommunicationTimeouts; 
            this.idleManager = idleManager;
 
            if (!binder.HasSession)
                this.closeBinder = false;

            if (this.idleManager != null) 
            {
                bool didIdleAbort; 
                this.idleManager.RegisterChannel(this, out didIdleAbort); 
                if (didIdleAbort)
                { 
                    this.Abort();
                }
            }
        } 

        CallOnceManager AutoOpenManager 
        { 
            get
            { 
                if (!this.explicitlyOpened && (this.autoOpenManager == null))
                {
                    this.EnsureAutoOpenManagers();
                } 
                return this.autoOpenManager;
            } 
        } 

        CallOnceManager AutoDisplayUIManager 
        {
            get
            {
                if (!this.explicitlyOpened && (this.autoDisplayUIManager == null)) 
                {
                    this.EnsureAutoOpenManagers(); 
                } 
                return this.autoDisplayUIManager;
            } 
        }

        internal bool CloseFactory
        { 
            get { return this.closeFactory; }
            set { this.closeFactory = value; } 
        } 

        protected override TimeSpan DefaultCloseTimeout 
        {
            get { return this.CloseTimeout; }
        }
 
        protected override TimeSpan DefaultOpenTimeout
        { 
            get { return this.OpenTimeout; } 
        }
 
        internal DispatchRuntime DispatchRuntime
        {
            get
            { 
                if (this.endpointDispatcher != null)
                { 
                    return this.endpointDispatcher.DispatchRuntime; 
                }
                if (this.clientRuntime != null) 
                {
                    return this.clientRuntime.DispatchRuntime;
                }
                return null; 
            }
        } 
 
        internal MessageVersion MessageVersion
        { 
            get { return this.messageVersion; }
        }

        internal IChannelBinder Binder 
        {
            get { return this.binder; } 
        } 

        internal TimeSpan CloseTimeout 
        {
            get
            {
                if (this.IsClient) 
                {
                    return factory.InternalCloseTimeout; 
                } 
                else
                { 
                    return this.ChannelDispatcher.InternalCloseTimeout;
                }
            }
        } 

        internal ChannelDispatcher ChannelDispatcher 
        { 
            get { return this.channelDispatcher; }
        } 

        internal EndpointDispatcher EndpointDispatcher
        {
            get { return this.endpointDispatcher; } 
            set
            { 
                lock (this.ThisLock) 
                {
                    this.endpointDispatcher = value; 
                    this.clientRuntime = value.DispatchRuntime.CallbackClientRuntime;
                }
            }
        } 

        internal ServiceChannelFactory Factory 
        { 
            get { return this.factory; }
        } 

        internal IChannel InnerChannel
        {
            get { return this.binder.Channel; } 
        }
 
        internal bool IsPending 
        {
            get { return this.isPending; } 
            set { this.isPending = value; }
        }

        internal bool HasSession 
        {
            get { return hasSession; } 
        } 

        internal bool IsClient 
        {
            get { return this.factory != null; }
        }
 
        internal bool IsReplyChannel
        { 
            get { return this.isReplyChannel; } 
        }
 
        public Uri ListenUri
        {
            get
            { 
                return this.binder.ListenUri;
            } 
        } 

        public EndpointAddress LocalAddress 
        {
            get
            {
                if (this.localAddress == null) 
                {
                    if (this.endpointDispatcher != null) 
                    { 
                        this.localAddress = this.endpointDispatcher.EndpointAddress;
                    } 
                    else
                    {
                        this.localAddress = this.binder.LocalAddress;
                    } 
                }
                return this.localAddress; 
            } 
        }
 
        internal TimeSpan OpenTimeout
        {
            get
            { 
                if (this.IsClient)
                { 
                    return factory.InternalOpenTimeout; 
                }
                else 
                {
                    return this.ChannelDispatcher.InternalOpenTimeout;
                }
            } 
        }
 
        public TimeSpan OperationTimeout 
        {
            get { return this.operationTimeout; } 
            set
            {
                if (value < TimeSpan.Zero)
                { 
                    string message = SR.GetString(SR.SFxTimeoutOutOfRange0);
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, message)); 
                } 
                if (TimeoutHelper.IsTooLarge(value))
                { 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("value", value, SR.GetString(SR.SFxTimeoutOutOfRangeTooBig)));
                }

 
                this.operationTimeout = value;
            } 
        } 

        internal object Proxy 
        {
            get
            {
                object proxy = this.proxy; 
                if (proxy != null)
                    return proxy; 
                else 
                    return this;
            } 
            set
            {
                this.proxy = value;
                base.EventSender = value;   // need to use "proxy" as open/close event source 
            }
        } 
 
        internal ClientRuntime ClientRuntime
        { 
            get { return this.clientRuntime; }
        }

        public EndpointAddress RemoteAddress 
        {
            get 
            { 
                IOutputChannel outputChannel = this.InnerChannel as IOutputChannel;
                if (outputChannel != null) 
                    return outputChannel.RemoteAddress;

                IRequestChannel requestChannel = this.InnerChannel as IRequestChannel;
                if (requestChannel != null) 
                    return requestChannel.RemoteAddress;
 
                return null; 
            }
        } 

        ProxyOperationRuntime UnhandledProxyOperation
        {
            get { return this.ClientRuntime.GetRuntime().UnhandledProxyOperation; } 
        }
 
        public Uri Via 
        {
            get 
            {
                IOutputChannel outputChannel = this.InnerChannel as IOutputChannel;
                if (outputChannel != null)
                    return outputChannel.Via; 

                IRequestChannel requestChannel = this.InnerChannel as IRequestChannel; 
                if (requestChannel != null) 
                    return requestChannel.Via;
 
                return null;
            }
        }
 
        internal InstanceContext InstanceContext
        { 
            get { return this.instanceContext; } 
            set { this.instanceContext = value; }
        } 

        internal ServiceThrottle InstanceContextServiceThrottle
        {
            get { return this.instanceContextServiceThrottle; } 
            set { this.instanceContextServiceThrottle = value; }
        } 
 
        internal ServiceThrottle ServiceThrottle
        { 
            get { return this.serviceThrottle; }
            set
            {
                this.ThrowIfDisposed(); 
                this.serviceThrottle = value;
            } 
        } 

        internal InstanceContext WmiInstanceContext 
        {
            get { return this.wmiInstanceContext; }
            set { this.wmiInstanceContext = value; }
        } 

        void BindDuplexCallbacks() 
        { 
            IDuplexChannel duplexChannel = this.InnerChannel as IDuplexChannel;
            if ((duplexChannel != null) && (this.factory != null) && (this.instanceContext != null)) 
            {
                if (this.binder is DuplexChannelBinder)
                    ((DuplexChannelBinder)this.binder).EnsurePumping();
            } 
        }
 
        internal bool CanCastTo(Type t) 
        {
            if (t.IsAssignableFrom(typeof(IClientChannel))) 
                return true;

            if (t.IsAssignableFrom(typeof(IDuplexContextChannel)))
                return this.InnerChannel is IDuplexChannel; 

            if (t.IsAssignableFrom(typeof(IServiceChannel))) 
                return true; 

            return false; 
        }

        internal void CompletedIOOperation()
        { 
            if (this.idleManager != null)
            { 
                this.idleManager.CompletedActivity(); 
            }
        } 

        void EnsureAutoOpenManagers()
        {
            lock (this.ThisLock) 
            {
                if (!this.explicitlyOpened) 
                { 
                    if (this.autoOpenManager == null)
                    { 
                        this.autoOpenManager = new CallOnceManager(this, CallOpenOnce.Instance);
                    }
                    if (this.autoDisplayUIManager == null)
                    { 
                        this.autoDisplayUIManager = new CallOnceManager(this, CallDisplayUIOnce.Instance);
                    } 
                } 
            }
        } 

        void EnsureDisplayUI()
        {
            CallOnceManager manager = this.AutoDisplayUIManager; 
            if (manager != null)
            { 
                manager.CallOnce(TimeSpan.MaxValue, null); 
            }
            this.ThrowIfInitializationUINotCalled(); 
        }

        IAsyncResult BeginEnsureDisplayUI(AsyncCallback callback, object state)
        { 
            CallOnceManager manager = this.AutoDisplayUIManager;
            if (manager != null) 
            { 
                return manager.BeginCallOnce(TimeSpan.MaxValue, null, callback, state);
            } 
            else
            {
                return new CallOnceCompletedAsyncResult(callback, state);
            } 
        }
 
        void EndEnsureDisplayUI(IAsyncResult result) 
        {
            CallOnceManager manager = this.AutoDisplayUIManager; 
            if (manager != null)
            {
                manager.EndCallOnce(result);
            } 
            else
            { 
                CallOnceCompletedAsyncResult.End(result); 
            }
            this.ThrowIfInitializationUINotCalled(); 
        }

        void EnsureOpened(TimeSpan timeout)
        { 
            CallOnceManager manager = this.AutoOpenManager;
            if (manager != null) 
            { 
                manager.CallOnce(timeout, this.autoDisplayUIManager);
            } 

            this.ThrowIfOpening();
            this.ThrowIfDisposedOrNotOpen();
        } 

        IAsyncResult BeginEnsureOpened(TimeSpan timeout, AsyncCallback callback, object state) 
        { 
            CallOnceManager manager = this.AutoOpenManager;
            if (manager != null) 
            {
                return manager.BeginCallOnce(timeout, this.autoDisplayUIManager, callback, state);
            }
            else 
            {
                this.ThrowIfOpening(); 
                this.ThrowIfDisposedOrNotOpen(); 

                return new CallOnceCompletedAsyncResult(callback, state); 
            }
        }

        void EndEnsureOpened(IAsyncResult result) 
        {
            CallOnceManager manager = this.AutoOpenManager; 
            if (manager != null) 
            {
                manager.EndCallOnce(result); 
            }
            else
            {
                CallOnceCompletedAsyncResult.End(result); 
            }
        } 
 
        public T GetProperty() where T : class
        { 
            IChannel innerChannel = this.InnerChannel;
            if (innerChannel != null)
                return innerChannel.GetProperty();
            return null; 
        }
 
        void PrepareCall(ProxyOperationRuntime operation, bool oneway, ref ProxyRpc rpc) 
        {
            OperationContext context = OperationContext.Current; 
            // Doing a request reply callback when dispatching in-order deadlocks.
            // We never receive the reply until we finish processing the current message.
            if (!oneway)
            { 
                DispatchRuntime dispatchBehavior = this.ClientRuntime.DispatchRuntime;
                if ((dispatchBehavior != null) && (dispatchBehavior.ConcurrencyMode == ConcurrencyMode.Single)) 
                { 
                    if ((context != null) && (!context.IsUserContext) && (context.InternalServiceChannel == this))
                    { 
                        if (dispatchBehavior.IsOnServer)
                        {
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCallbackRequestReplyInOrder1,typeof(ServiceBehaviorAttribute).Name)));
                        } 
                        else
                        { 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCallbackRequestReplyInOrder1, typeof(CallbackBehaviorAttribute).Name))); 
                        }
                    } 
                }
            }

            if ((this.State == CommunicationState.Created) && !operation.IsInitiating) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxNonInitiatingOperation1, operation.Name))); 
            } 

            if (this.terminatingOperationName != null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxTerminatingOperationAlreadyCalled1, this.terminatingOperationName)));
            }
 
            if (this.wasChannelAutoClosed)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ProtocolException(SR.GetString(SR.SFxClientOutputSessionAutoClosed))); 
            }
 
            operation.BeforeRequest(ref rpc);
            AddMessageProperties(rpc.Request, context);
            if (!oneway && !this.ClientRuntime.ManualAddressing && rpc.Request.Version.Addressing != AddressingVersion.None)
            { 
                RequestReplyCorrelator.PrepareRequest(rpc.Request);
 
                MessageHeaders headers = rpc.Request.Headers; 
                EndpointAddress localAddress = this.LocalAddress;
                EndpointAddress replyTo = headers.ReplyTo; 

                if (replyTo == null)
                {
                    headers.ReplyTo = localAddress ?? EndpointAddress.AnonymousAddress; 
                }
 
                if (this.IsClient && (localAddress != null) && !localAddress.IsAnonymous) 
                {
                    Uri localUri = localAddress.Uri; 

                    if ((replyTo != null) && !replyTo.IsAnonymous && (localUri != replyTo.Uri))
                    {
                        string text = SR.GetString(SR.SFxRequestHasInvalidReplyToOnClient, replyTo.Uri, localUri); 
                        Exception error = new InvalidOperationException(text);
                        throw TraceUtility.ThrowHelperError(error, rpc.Request); 
                    } 

                    EndpointAddress faultTo = headers.FaultTo; 
                    if ((faultTo != null) && !faultTo.IsAnonymous && (localUri != faultTo.Uri))
                    {
                        string text = SR.GetString(SR.SFxRequestHasInvalidFaultToOnClient, faultTo.Uri, localUri);
                        Exception error = new InvalidOperationException(text); 
                        throw TraceUtility.ThrowHelperError(error, rpc.Request);
                    } 
 
                    if (this.messageVersion.Addressing == AddressingVersion.WSAddressingAugust2004)
                    { 
                        EndpointAddress from = headers.From;
                        if ((from != null) && !from.IsAnonymous && (localUri != from.Uri))
                        {
                            string text = SR.GetString(SR.SFxRequestHasInvalidFromOnClient, from.Uri, localUri); 
                            Exception error = new InvalidOperationException(text);
                            throw TraceUtility.ThrowHelperError(error, rpc.Request); 
                        } 
                    }
                } 
            }

            if (rpc.Activity != null)
            { 
                TraceUtility.SetActivity(rpc.Request, rpc.Activity);
                if (TraceUtility.ShouldPropagateActivity) 
                { 
                    TraceUtility.AddActivityHeader(rpc.Request);
                } 
            }
            else if (TraceUtility.PropagateUserActivity)
            {
                TraceUtility.AddAmbientActivityToMessage(rpc.Request); 
            }
 
            operation.Parent.BeforeSendRequest(ref rpc); 

            if (MessageLogger.LogMessagesAtServiceLevel) 
            {
                MessageLogger.LogMessage(ref rpc.Request, (oneway ? MessageLoggingSource.ServiceLevelSendDatagram : MessageLoggingSource.ServiceLevelSendRequest) | MessageLoggingSource.LastChance);
            }
        } 

        internal IAsyncResult BeginCall(string action, bool oneway, ProxyOperationRuntime operation, object[] ins, AsyncCallback callback, object asyncState) 
        { 
            return this.BeginCall(action, oneway, operation, ins, this.operationTimeout, callback, asyncState);
        } 

        internal IAsyncResult BeginCall(string action, bool oneway, ProxyOperationRuntime operation, object[] ins, TimeSpan timeout, AsyncCallback callback, object asyncState)
        {
            this.ThrowIfDisallowedInitializationUI(); 
            this.ThrowIfIdleAborted(operation);
 
            ServiceModelActivity serviceModelActivity = null; 

            if (DiagnosticUtility.ShouldUseActivity) 
            {
                serviceModelActivity = ServiceModelActivity.CreateActivity(true);
                callback = TraceUtility.WrapExecuteUserCodeAsyncCallback(callback);
            } 

            SendAsyncResult result; 
 
            using (Activity boundOperation = ServiceModelActivity.BoundOperation(serviceModelActivity, true))
            { 
                if (DiagnosticUtility.ShouldUseActivity)
                {
                    ServiceModelActivity.Start(serviceModelActivity, SR.GetString(SR.ActivityProcessAction, action), ActivityType.ProcessAction);
                } 

                result = new SendAsyncResult(this, operation, action, ins, oneway, timeout, callback, asyncState); 
                if (DiagnosticUtility.ShouldUseActivity) 
                {
                    result.Rpc.Activity = serviceModelActivity; 
                }

                result.Begin();
            } 

            return result; 
        } 

        internal object Call(string action, bool oneway, ProxyOperationRuntime operation, object[] ins, object[] outs) 
        {
            return this.Call(action, oneway, operation, ins, outs, this.operationTimeout);
        }
 
        internal object Call(string action, bool oneway, ProxyOperationRuntime operation, object[] ins, object[] outs, TimeSpan timeout)
        { 
            this.ThrowIfDisallowedInitializationUI(); 
            this.ThrowIfIdleAborted(operation);
 
            ProxyRpc rpc = new ProxyRpc(this, operation, action, ins, timeout);

            using (rpc.Activity = DiagnosticUtility.ShouldUseActivity ? ServiceModelActivity.CreateBoundedActivity() : null)
            { 
                if (DiagnosticUtility.ShouldUseActivity)
                { 
                    ServiceModelActivity.Start(rpc.Activity, SR.GetString(SR.ActivityProcessAction, action), ActivityType.ProcessAction); 
                }
 
                this.PrepareCall(operation, oneway, ref rpc);

                if (!this.explicitlyOpened)
                { 
                    this.EnsureDisplayUI();
                    this.EnsureOpened(rpc.TimeoutHelper.RemainingTime()); 
                } 
                else
                { 
                    this.ThrowIfOpening();
                    this.ThrowIfDisposedOrNotOpen();
                }
 
                try
                { 
                    ConcurrencyBehavior.UnlockInstanceBeforeCallout(OperationContext.Current); 

                    if (oneway) 
                    {
                        this.binder.Send(rpc.Request, rpc.TimeoutHelper.RemainingTime());
                    }
                    else 
                    {
                        rpc.Reply = this.binder.Request(rpc.Request, rpc.TimeoutHelper.RemainingTime()); 
 
                        if (rpc.Reply == null)
                        { 
                            this.ThrowIfFaulted();
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SFxServerDidNotReply)));
                        }
                    } 
                }
                finally 
                { 
                    this.CompletedIOOperation();
                    CallOnceManager.SignalNextIfNonNull(this.autoOpenManager); 
                    ConcurrencyBehavior.LockInstanceAfterCallout(OperationContext.Current);
                }

                rpc.OutputParameters = outs; 
                this.HandleReply(operation, ref rpc);
            } 
            return rpc.ReturnValue; 
        }
 
        internal object EndCall(string action, object[] outs, IAsyncResult result)
        {
            SendAsyncResult sendResult = result as SendAsyncResult;
            if (sendResult == null) 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SFxInvalidCallbackIAsyncResult)));
 
            using (ServiceModelActivity rpcActivity = sendResult.Rpc.Activity) 
            {
                using (ServiceModelActivity.BoundOperation(rpcActivity, true)) 
                {
                    if (sendResult.Rpc.Activity != null && DiagnosticUtility.ShouldUseActivity)
                    {
                        sendResult.Rpc.Activity.Resume(); 
                    }
                    if (sendResult.Rpc.Channel != this) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.AsyncEndCalledOnWrongChannel)); 

                    if (action != MessageHeaders.WildcardAction && action != sendResult.Rpc.Action) 
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("result", SR.GetString(SR.AsyncEndCalledWithAnIAsyncResult));

                    SendAsyncResult.End(sendResult);
 
                    sendResult.Rpc.OutputParameters = outs;
                    this.HandleReply(sendResult.Rpc.Operation, ref sendResult.Rpc); 
 
                    if (sendResult.Rpc.Activity != null)
                    { 
                        sendResult.Rpc.Activity = null;
                    }
                    return sendResult.Rpc.ReturnValue;
                } 
            }
        } 
 
        internal void DecrementActivity()
        { 
            int updatedActivityCount = Interlocked.Decrement(ref this.activityCount);

            if (!((updatedActivityCount >= 0)))
            { 
                DiagnosticUtility.DebugAssert("ServiceChannel.DecrementActivity: (updatedActivityCount >= 0)");
 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperInternal(true); 
            }
 
            if (updatedActivityCount == 0 && this.autoClose)
            {
                try
                { 
                    if (this.State == CommunicationState.Opened)
                    { 
                        if (this.IsClient) 
                        {
                            ISessionChannel duplexSessionChannel = this.InnerChannel as ISessionChannel; 
                            if (duplexSessionChannel != null)
                            {
                                duplexSessionChannel.Session.CloseOutputSession(this.CloseTimeout);
                                this.wasChannelAutoClosed = true; 
                            }
                        } 
                        else 
                        {
                            this.Close(this.CloseTimeout); 
                        }
                    }
                }
                catch (CommunicationException e) 
                {
                    if (DiagnosticUtility.ShouldTraceInformation) 
                    { 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                    } 
                }
                catch (TimeoutException e)
                {
                    if (DiagnosticUtility.ShouldTraceInformation) 
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                    } 
                }
                catch (ObjectDisposedException e) 
                {
                    if (DiagnosticUtility.ShouldTraceInformation)
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                    }
                } 
                catch (InvalidOperationException e) 
                {
                    if (DiagnosticUtility.ShouldTraceInformation) 
                    {
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                    }
                } 
            }
        } 
 
        internal void FireUnknownMessageReceived(Message message)
        { 
            EventHandler handler = this.unknownMessageReceived;
            if (handler != null)
                handler(this.proxy, new UnknownMessageReceivedEventArgs(message));
        } 

        TimeoutException GetOpenTimeoutException(TimeSpan timeout) 
        { 
            EndpointAddress address = this.RemoteAddress ?? this.LocalAddress;
            if (address != null) 
            {
                return new TimeoutException(SR.GetString(SR.TimeoutServiceChannelConcurrentOpen2, address, timeout));
            }
            else 
            {
                return new TimeoutException(SR.GetString(SR.TimeoutServiceChannelConcurrentOpen1, timeout)); 
            } 
        }
 
        internal void HandleReceiveComplete(RequestContext context)
        {
            if (context == null && HasSession)
            { 
                bool first;
                lock (this.ThisLock) 
                { 
                    first = !this.doneReceiving;
                    this.doneReceiving = true; 
                }

                if (first)
                { 
                    DispatchRuntime dispatchBehavior = this.ClientRuntime.DispatchRuntime;
                    if (dispatchBehavior != null) 
                        dispatchBehavior.GetRuntime().InputSessionDoneReceiving(this); 

                    this.DecrementActivity(); 
                }
            }
        }
 
        void HandleReply(ProxyOperationRuntime operation, ref ProxyRpc rpc)
        { 
            try 
            {
                if (rpc.Reply != null) 
                {
                    if (MessageLogger.LogMessagesAtServiceLevel)
                    {
                        MessageLogger.LogMessage(ref rpc.Reply, MessageLoggingSource.ServiceLevelReceiveReply | MessageLoggingSource.LastChance); 
                    }
                    operation.Parent.AfterReceiveReply(ref rpc); 
 
                     if ((operation.ReplyAction != MessageHeaders.WildcardAction) && !rpc.Reply.IsFault && rpc.Reply.Headers.Action != null)
                     { 
                         if (String.CompareOrdinal(operation.ReplyAction, rpc.Reply.Headers.Action) != 0)
                         {
                             Exception error = new ProtocolException(SR.GetString(SR.SFxReplyActionMismatch3,
                                                                                  operation.Name, 
                                                                                  rpc.Reply.Headers.Action,
                                                                                  operation.ReplyAction)); 
                             this.TerminateIfNecessary(ref rpc); 
                             throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
                         } 
                     }

                    if (operation.DeserializeReply && rpc.Reply.IsFault && messageVersion.Envelope != EnvelopeVersion.None)
                    { 
                        MessageFault fault = MessageFault.CreateFault(rpc.Reply, this.clientRuntime.MaxFaultSize);
                        string action = rpc.Reply.Headers.Action; 
                        if (action == rpc.Reply.Version.Addressing.DefaultFaultAction) 
                        {
                            action = null; 
                        }
                        ThrowIfFaultUnderstood(rpc.Reply, fault, action, rpc.Reply.Version, rpc.Channel.GetProperty());

                        FaultException fe = rpc.Operation.FaultFormatter.Deserialize(fault, action); 
                        this.TerminateIfNecessary(ref rpc);
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(fe); 
                    } 

                    operation.AfterReply(ref rpc); 
                }
            }
            finally
            { 
                if (operation.SerializeRequest)
                { 
                    rpc.Request.Close(); 
                }
 
                OperationContext operationContext = OperationContext.Current;
                bool consumed = ((rpc.Reply != null) && (rpc.Reply.State != MessageState.Created));

                if ((operationContext != null) && operationContext.IsUserContext) 
                {
                    operationContext.SetClientReply(rpc.Reply, consumed); 
                } 
                else if (consumed)
                { 
                    rpc.Reply.Close();
                }
            }
 
            this.TerminateIfNecessary(ref rpc);
        } 
 
        void TerminateIfNecessary(ref ProxyRpc rpc)
        { 
            if (rpc.Operation.IsTerminating)
            {
                this.terminatingOperationName = rpc.Operation.Name;
                TerminatingOperationBehavior.AfterReply(ref rpc); 
            }
        } 
 
        void ThrowIfFaultUnderstood(Message reply, MessageFault fault, string action, MessageVersion version, FaultConverter faultConverter)
        { 
            Exception exception;
            if (faultConverter != null && faultConverter.TryCreateException(reply, fault, out exception))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(exception); 
            }
 
            bool checkSender; 
            bool checkReceiver;
            FaultCode code; 

            if (version.Envelope == EnvelopeVersion.Soap11)
            {
                checkSender = true; 
                checkReceiver = true;
                code = fault.Code; 
            } 
            else
            { 
                checkSender = fault.Code.IsSenderFault;
                checkReceiver = fault.Code.IsReceiverFault;
                code = fault.Code.SubCode;
            } 

            if (code == null) 
            { 
                return;
            } 

            if (code.Namespace == null)
            {
                return; 
            }
 
            if (checkSender) 
            {
                if (string.Compare(code.Namespace, FaultCodeConstants.Namespaces.NetDispatch, StringComparison.Ordinal) == 0) 
                {
                    if (string.Compare(code.Name, FaultCodeConstants.Codes.SessionTerminated, StringComparison.Ordinal) == 0)
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ChannelTerminatedException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text)); 
                    }
 
                    if (string.Compare(code.Name, FaultCodeConstants.Codes.TransactionAborted, StringComparison.Ordinal) == 0) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ProtocolException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text)); 
                    }
                }

                // throw SecurityAccessDeniedException explicitly 
                if (string.Compare(code.Namespace, SecurityVersion.Default.HeaderNamespace.Value, StringComparison.Ordinal) == 0)
                { 
                    if (string.Compare(code.Name, SecurityVersion.Default.FailedAuthenticationFaultCode.Value, StringComparison.Ordinal) == 0) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new SecurityAccessDeniedException(fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text)); 
                    }
                }
            }
 
            if (checkReceiver)
            { 
                if (string.Compare(code.Namespace, FaultCodeConstants.Namespaces.NetDispatch, StringComparison.Ordinal) == 0) 
                {
                    if (string.Compare(code.Name, FaultCodeConstants.Codes.InternalServiceFault, StringComparison.Ordinal) == 0) 
                    {
                        if (this.HasSession)
                        {
                            this.Fault(); 
                        }
                        if (fault.HasDetail) 
                        { 
                            ExceptionDetail detail = fault.GetDetail();
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new FaultException(detail, fault.Reason, fault.Code, action)); 
                        }
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new FaultException(fault, action));
                    }
                    if (string.Compare(code.Name, FaultCodeConstants.Codes.DeserializationFailed, StringComparison.Ordinal) == 0) 
                    {
                        throw DiagnosticUtility.ExceptionUtility.ThrowHelperWarning(new ProtocolException( 
                            fault.Reason.GetMatchingTranslation(CultureInfo.CurrentCulture).Text)); 
                    }
                } 
            }
        }

        void ThrowIfIdleAborted(ProxyOperationRuntime operation) 
        {
            if (this.idleManager != null && this.idleManager.DidIdleAbort) 
            { 
                string text = SR.GetString(SR.SFxServiceChannelIdleAborted, operation.Name);
                Exception error = new CommunicationObjectAbortedException(text); 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
            }
        }
 
        void ThrowIfInitializationUINotCalled()
        { 
            if (!this.didInteractiveInitialization && (this.ClientRuntime.InteractiveChannelInitializers.Count > 0)) 
            {
                IInteractiveChannelInitializer example = this.ClientRuntime.InteractiveChannelInitializers[0]; 
                string text = SR.GetString(SR.SFxInitializationUINotCalled, example.GetType().ToString());
                Exception error = new InvalidOperationException(text);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error);
            } 
        }
 
        void ThrowIfDisallowedInitializationUI() 
        {
            if (!this.allowInitializationUI) 
            {
                this.ThrowIfDisallowedInitializationUICore();
            }
        } 

        void ThrowIfDisallowedInitializationUICore() 
        { 
            if (this.ClientRuntime.InteractiveChannelInitializers.Count > 0)
            { 
                IInteractiveChannelInitializer example = this.ClientRuntime.InteractiveChannelInitializers[0];
                string text = SR.GetString(SR.SFxInitializationUIDisallowed, example.GetType().ToString());
                Exception error = new InvalidOperationException(text);
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(error); 
            }
        } 
 
        void ThrowIfOpening()
        { 
            if (this.State == CommunicationState.Opening)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.SFxCannotCallAutoOpenWhenExplicitOpenCalled)));
            } 
        }
 
        internal void IncrementActivity() 
        {
            Interlocked.Increment(ref this.activityCount); 
        }

        void OnInnerChannelFaulted(object sender, EventArgs e)
        { 
            this.Fault();
 
            if (this.HasSession) 
            {
                DispatchRuntime dispatchRuntime = this.ClientRuntime.DispatchRuntime; 
                if (dispatchRuntime != null)
                {
                    dispatchRuntime.GetRuntime().InputSessionFaulted(this);
                } 
            }
 
            if (this.autoClose && !this.IsClient) 
            {
                this.Abort(); 
            }
        }

        void AddMessageProperties(Message message, OperationContext context) 
        {
            if (this.allowOutputBatching) 
            { 
                message.Properties.AllowOutputBatching = true;
            } 

            if (context != null && context.InternalServiceChannel == this)
            {
                if (!context.OutgoingMessageVersion.IsMatch(message.Headers.MessageVersion)) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException( 
                        SR.GetString(SR.SFxVersionMismatchInOperationContextAndMessage2, context.OutgoingMessageVersion, message.Headers.MessageVersion) 
                        ));
                } 

                if (context.HasOutgoingMessageHeaders)
                {
                    message.Headers.CopyHeadersFrom(context.OutgoingMessageHeaders); 
                }
 
                if (context.HasOutgoingMessageProperties) 
                {
                    message.Properties.CopyProperties(context.OutgoingMessageProperties); 
                }
            }
        }
 
        #region IChannel Members
        public void Send(Message message) 
        { 
            this.Send(message, this.OperationTimeout);
        } 

        public void Send(Message message, TimeSpan timeout)
        {
            ProxyOperationRuntime operation = UnhandledProxyOperation; 
            this.Call(message.Headers.Action, true, operation, new object[] { message }, EmptyArray.Instance, timeout);
        } 
 
        public IAsyncResult BeginSend(Message message, AsyncCallback callback, object state)
        { 
            return this.BeginSend(message, this.OperationTimeout, callback, state);
        }

        public IAsyncResult BeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state) 
        {
            ProxyOperationRuntime operation = UnhandledProxyOperation; 
            return this.BeginCall(message.Headers.Action, true, operation, new object[] { message }, timeout, callback, state); 
        }
 
        public void EndSend(IAsyncResult result)
        {
            this.EndCall(MessageHeaders.WildcardAction, EmptyArray.Instance, result);
        } 

        public Message Request(Message message) 
        { 
            return this.Request(message, this.OperationTimeout);
        } 

        public Message Request(Message message, TimeSpan timeout)
        {
            ProxyOperationRuntime operation = UnhandledProxyOperation; 
            return (Message)this.Call(message.Headers.Action, false, operation, new object[] { message }, EmptyArray.Instance, timeout);
        } 
 
        public IAsyncResult BeginRequest(Message message, AsyncCallback callback, object state)
        { 
            return this.BeginRequest(message, this.OperationTimeout, callback, state);
        }

        public IAsyncResult BeginRequest(Message message, TimeSpan timeout, AsyncCallback callback, object state) 
        {
            ProxyOperationRuntime operation = this.UnhandledProxyOperation; 
            return this.BeginCall(message.Headers.Action, false, operation, new object[] { message }, timeout, callback, state); 
        }
 
        public Message EndRequest(IAsyncResult result)
        {
            return (Message)this.EndCall(MessageHeaders.WildcardAction, EmptyArray.Instance, result);
        } 

        protected override void OnAbort() 
        { 
            if (this.idleManager != null)
            { 
                this.idleManager.CancelTimer();
            }

            this.binder.Abort(); 

            if (this.factory != null) 
                this.factory.ChannelDisposed(this); 

            if (this.closeFactory) 
            {
                if (this.factory != null)
                    this.factory.Abort();
            } 

            ServiceThrottle serviceThrottle = this.serviceThrottle; 
            if (serviceThrottle != null) 
                serviceThrottle.DeactivateChannel();
 
            //rollback the attached transaction if one is present
            if ((this.instanceContext != null) && this.HasSession)
            {
                if (instanceContext.HasTransaction) 
                {
                    instanceContext.Transaction.CompletePendingTransaction(instanceContext.Transaction.Attached, new Exception()); // error!=null forces Tx rollback 
                } 
            }
        } 

        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        {
            if (this.idleManager != null) 
            {
                this.idleManager.CancelTimer(); 
            } 

            if (this.factory != null) 
            {
                this.factory.ChannelDisposed(this);
            }
 
            if (this.InstanceContext != null && this.InstanceContext.HasTransaction)
            { 
                this.InstanceContext.CompleteAttachedTransaction(); 
            }
 
            if (this.closeBinder)
            {
                if (this.closeFactory)
                { 
                    return new ChainedAsyncResult(timeout, callback, state,
                        new ChainedBeginHandler(this.InnerChannel.BeginClose), new ChainedEndHandler(this.InnerChannel.EndClose), 
                        new ChainedBeginHandler(this.factory.BeginClose), new ChainedEndHandler(this.factory.EndClose)); 
                }
                else 
                {
                    return this.InnerChannel.BeginClose(timeout, callback, state);
                }
            } 
            else
            { 
                if (this.closeFactory) 
                    return factory.BeginClose(timeout, callback, state);
                else 
                    return new CompletedAsyncResult(callback, state);
            }
        }
 
        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            this.ThrowIfDisallowedInitializationUI(); 
            this.ThrowIfInitializationUINotCalled();
 
            if (this.autoOpenManager == null)
            {
                this.explicitlyOpened = true;
            } 

            if (this.HasSession && !this.IsClient) 
            { 
                ServiceHostingEnvironment.IncrementBusyCount();
            } 

            this.TraceChannelOpen();

            if (this.openBinder) 
            {
                return this.InnerChannel.BeginOpen(timeout, callback, state); 
            } 
            else
            { 
                return new CompletedAsyncResult(callback, state);
            }
        }
 
        protected override void OnClose(TimeSpan timeout)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 

            if (this.idleManager != null) 
            {
                this.idleManager.CancelTimer();
            }
 
            if (this.factory != null)
            { 
                this.factory.ChannelDisposed(this); 
            }
 
            if (this.InstanceContext != null && this.InstanceContext.HasTransaction)
            {
                this.InstanceContext.CompleteAttachedTransaction();
            } 

            if (this.closeBinder) 
                this.InnerChannel.Close(timeoutHelper.RemainingTime()); 

            if (this.closeFactory) 
                this.factory.Close(timeoutHelper.RemainingTime());

            if (this.InstanceContext != null)
            { 
                this.InstanceContext.OutgoingChannels.Remove((IChannel)this.proxy);
            } 
 
            if (this.WmiInstanceContext != null)
            { 
                this.WmiInstanceContext.WmiChannels.Remove((IChannel)this.proxy);
            }

            ServiceThrottle serviceThrottle = this.serviceThrottle; 
            if (serviceThrottle != null)
            { 
                serviceThrottle.DeactivateChannel(); 
            }
 
            if (this.HasSession && !this.IsClient)
            {
                ServiceHostingEnvironment.DecrementBusyCount();
            } 
        }
 
        protected override void OnEndClose(IAsyncResult result) 
        {
            if (this.closeBinder) 
            {
                if (this.closeFactory)
                    ChainedAsyncResult.End(result);
                else 
                    this.InnerChannel.EndClose(result);
            } 
            else 
            {
                if (this.closeFactory) 
                    factory.EndClose(result);
                else
                    CompletedAsyncResult.End(result);
            } 

            if (this.InstanceContext != null) 
            { 
                this.InstanceContext.OutgoingChannels.Remove((IChannel)this.proxy);
            } 

            if (this.WmiInstanceContext != null)
            {
                this.WmiInstanceContext.WmiChannels.Remove((IChannel)this.proxy); 
            }
 
            ServiceThrottle serviceThrottle = this.serviceThrottle; 
            if (serviceThrottle != null)
            { 
                serviceThrottle.DeactivateChannel();
            }

            if (this.HasSession && !this.IsClient) 
            {
                ServiceHostingEnvironment.DecrementBusyCount(); 
            } 
        }
 
        protected override void OnEndOpen(IAsyncResult result)
        {
            if (this.openBinder)
                InnerChannel.EndOpen(result); 
            else
                CompletedAsyncResult.End(result); 
            this.BindDuplexCallbacks(); 
            this.CompletedIOOperation();
        } 

        protected override void OnOpen(TimeSpan timeout)
        {
            this.ThrowIfDisallowedInitializationUI(); 
            this.ThrowIfInitializationUINotCalled();
 
            if (this.autoOpenManager == null) 
            {
                this.explicitlyOpened = true; 
            }

            if (this.HasSession && !this.IsClient)
            { 
                ServiceHostingEnvironment.IncrementBusyCount();
            } 
 
            this.TraceChannelOpen();
 
            if (this.openBinder)
            {
                this.InnerChannel.Open(timeout);
            } 

            this.BindDuplexCallbacks(); 
            this.CompletedIOOperation(); 
        }
 
        #endregion

        #region IClientChannel Members
 
        bool IDuplexContextChannel.AutomaticInputSessionShutdown
        { 
            get { return this.autoClose; } 
            set { this.autoClose = value; }
        } 

        bool IClientChannel.AllowInitializationUI
        {
            get { return this.allowInitializationUI; } 
            set
            { 
                this.ThrowIfDisposedOrImmutable(); 
                this.allowInitializationUI = value;
            } 
        }

        bool IContextChannel.AllowOutputBatching
        { 
            get { return this.allowOutputBatching; }
            set { this.allowOutputBatching = value; } 
        } 

        bool IClientChannel.DidInteractiveInitialization 
        {
            get { return this.didInteractiveInitialization; }
        }
 
        IAsyncResult IDuplexContextChannel.BeginCloseOutputSession(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            return GetDuplexSessionOrThrow().BeginCloseOutputSession(timeout, callback, state); 
        }
 
        void IDuplexContextChannel.EndCloseOutputSession(IAsyncResult result)
        {
            GetDuplexSessionOrThrow().EndCloseOutputSession(result);
        } 

        void IDuplexContextChannel.CloseOutputSession(TimeSpan timeout) 
        { 
            GetDuplexSessionOrThrow().CloseOutputSession(timeout);
        } 

        IDuplexSession GetDuplexSessionOrThrow()
        {
            if (this.InnerChannel == null) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.channelIsNotAvailable0))); 
            } 

            ISessionChannel duplexSessionChannel = this.InnerChannel as ISessionChannel; 
            if (duplexSessionChannel == null)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.channelDoesNotHaveADuplexSession0)));
            } 

            return duplexSessionChannel.Session; 
        } 

        IExtensionCollection IExtensibleObject.Extensions 
        {
            get
            {
                lock (this.ThisLock) 
                {
                    if (this.extensions == null) 
                        this.extensions = new ExtensionCollection((IContextChannel)this.Proxy, this.ThisLock); 
                    return this.extensions;
                } 
            }
        }

        InstanceContext IDuplexContextChannel.CallbackInstance 
        {
            get { return this.instanceContext; } 
            set 
            {
                lock (this.ThisLock) 
                {
                    if (this.instanceContext != null)
                    {
                        this.instanceContext.OutgoingChannels.Remove((IChannel)this.proxy); 
                    }
 
                    this.instanceContext = value; 

                    if (this.instanceContext != null) 
                    {
                        this.instanceContext.OutgoingChannels.Add((IChannel)this.proxy);
                    }
                } 
            }
        } 
 
        IInputSession IContextChannel.InputSession
        { 
            get
            {
                if (this.InnerChannel != null)
                { 
                    ISessionChannel inputSession = this.InnerChannel as ISessionChannel;
                    if (inputSession != null) 
                        return inputSession.Session; 

                    ISessionChannel duplexSession = this.InnerChannel as ISessionChannel; 
                    if (duplexSession != null)
                        return duplexSession.Session;
                }
 
                return null;
            } 
        } 

        IOutputSession IContextChannel.OutputSession 
        {
            get
            {
                if (this.InnerChannel != null) 
                {
                    ISessionChannel outputSession = this.InnerChannel as ISessionChannel; 
                    if (outputSession != null) 
                        return outputSession.Session;
 
                    ISessionChannel duplexSession = this.InnerChannel as ISessionChannel;
                    if (duplexSession != null)
                        return duplexSession.Session;
                } 

                return null; 
            } 
        }
 
        string IContextChannel.SessionId
        {
            get
            { 
                if (this.InnerChannel != null)
                { 
                    ISessionChannel inputSession = this.InnerChannel as ISessionChannel; 
                    if (inputSession != null)
                        return inputSession.Session.Id; 

                    ISessionChannel outputSession = this.InnerChannel as ISessionChannel;
                    if (outputSession != null)
                        return outputSession.Session.Id; 

                    ISessionChannel duplexSession = this.InnerChannel as ISessionChannel; 
                    if (duplexSession != null) 
                        return duplexSession.Session.Id;
                } 

                return null;
            }
        } 

        event EventHandler IClientChannel.UnknownMessageReceived 
        { 
            add
            { 
                lock (this.ThisLock)
                {
                    this.unknownMessageReceived += value;
                } 
            }
            remove 
            { 
                lock (this.ThisLock)
                { 
                    this.unknownMessageReceived -= value;
                }
            }
        } 

        public void DisplayInitializationUI() 
        { 
            this.ThrowIfDisallowedInitializationUI();
 
            if (this.autoDisplayUIManager == null)
            {
                this.explicitlyOpened = true;
            } 

            this.ClientRuntime.GetRuntime().DisplayInitializationUI(this); 
            this.didInteractiveInitialization = true; 
        }
 
        public IAsyncResult BeginDisplayInitializationUI(AsyncCallback callback, object state)
        {
            this.ThrowIfDisallowedInitializationUI();
 
            if (this.autoDisplayUIManager == null)
            { 
                this.explicitlyOpened = true; 
            }
 
            return this.ClientRuntime.GetRuntime().BeginDisplayInitializationUI(this, callback, state);
        }

        public void EndDisplayInitializationUI(IAsyncResult result) 
        {
            this.ClientRuntime.GetRuntime().EndDisplayInitializationUI(result); 
            this.didInteractiveInitialization = true; 
        }
 
        void IDisposable.Dispose()
        {
            this.Close();
        } 

        #endregion 
 
        void TraceChannelOpen()
        { 
            if (DiagnosticUtility.ShouldTraceInformation)
            {
                Dictionary values = new Dictionary(4);
                bool traceNeeded = false; 
                DispatchRuntime behavior = this.DispatchRuntime;
                if (behavior != null) 
                { 
                    if (behavior.Type != null)
                    { 
                        values["ServiceType"] = behavior.Type.AssemblyQualifiedName;
                    }
                    values["ContractNamespace"] = this.clientRuntime.ContractNamespace;
                    values["ContractName"] = this.clientRuntime.ContractName; 
                    traceNeeded = true;
                } 
                if ((this.endpointDispatcher != null) && (this.endpointDispatcher.ListenUri != null)) 
                {
                    values["Uri"] = this.endpointDispatcher.ListenUri.ToString(); 
                    traceNeeded = true;
                }
                if (traceNeeded)
                { 
                    TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.ServiceChannelLifetime,
                        new DictionaryTraceRecord(values), this, null); 
                } 
            }
        } 

        // Invariants for signalling the CallOnce manager.
        //
        // 1) If a Call, BeginCall, or EndCall on the channel throws, 
        //    the manager will SignalNext itself.
        // 2) If a Waiter times out, it will SignalNext its manager 
        //    once it is both timed out and signalled. 
        // 3) Once Call or EndCall returns successfully, it guarantees
        //    that SignalNext will be called once the // next stage 
        //    has sufficiently completed.

        class SendAsyncResult : TraceAsyncResult
        { 
            readonly bool isOneWay;
            readonly ProxyOperationRuntime operation; 
            internal ProxyRpc Rpc; 
            OperationContext operationContext;
 
            static AsyncCallback ensureInteractiveInitCallback = DiagnosticUtility.ThunkAsyncCallback(EnsureInteractiveInitCallback);
            static AsyncCallback ensureOpenCallback = DiagnosticUtility.ThunkAsyncCallback(EnsureOpenCallback);
            static AsyncCallback sendCallback = DiagnosticUtility.ThunkAsyncCallback(SendCallback);
 
            internal SendAsyncResult(ServiceChannel channel, ProxyOperationRuntime operation,
                                     string action, object[] inputParameters, bool isOneWay, TimeSpan timeout, 
                                     AsyncCallback userCallback, object userState) 
                : base(userCallback, userState)
            { 
                this.Rpc = new ProxyRpc(channel, operation, action, inputParameters, timeout);
                this.isOneWay = isOneWay;
                this.operation = operation;
                this.operationContext = OperationContext.Current; 
            }
 
            internal void Begin() 
            {
                this.Rpc.Channel.PrepareCall(this.operation, this.isOneWay, ref this.Rpc); 

                if (this.Rpc.Channel.explicitlyOpened)
                {
                    this.Rpc.Channel.ThrowIfOpening(); 
                    this.Rpc.Channel.ThrowIfDisposedOrNotOpen();
                    this.StartSend(true); 
                } 
                else
                { 
                    this.StartEnsureInteractiveInit();
                }
            }
 
            void StartEnsureInteractiveInit()
            { 
                IAsyncResult result = this.Rpc.Channel.BeginEnsureDisplayUI(ensureInteractiveInitCallback, this); 

                if (result.CompletedSynchronously) 
                {
                    this.FinishEnsureInteractiveInit(result, true);
                }
            } 

            static void EnsureInteractiveInitCallback(IAsyncResult result) 
            { 
                if (!result.CompletedSynchronously)
                { 
                    ((SendAsyncResult)result.AsyncState).FinishEnsureInteractiveInit(result, false);
                }
            }
 
            void FinishEnsureInteractiveInit(IAsyncResult result, bool completedSynchronously)
            { 
                Exception exception = null; 

                try 
                {
                    this.Rpc.Channel.EndEnsureDisplayUI(result);
                }
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e) || completedSynchronously) 
                    { 
                        throw;
                    } 
                    exception = e;
                }

                if (exception != null) 
                {
                    this.CallComplete(completedSynchronously, exception); 
                } 
                else
                { 
                    this.StartEnsureOpen(completedSynchronously);
                }
            }
 
            void StartEnsureOpen(bool completedSynchronously)
            { 
                TimeSpan timeout = this.Rpc.TimeoutHelper.RemainingTime(); 
                IAsyncResult result = null;
                Exception exception = null; 

                try
                {
                    result = this.Rpc.Channel.BeginEnsureOpened(timeout, ensureOpenCallback, this); 
                }
                catch (Exception e) 
                { 
                    if (DiagnosticUtility.IsFatal(e) || completedSynchronously)
                    { 
                        throw;
                    }
                    exception = e;
                } 

                if (exception != null) 
                { 
                    this.CallComplete(completedSynchronously, exception);
                } 
                else if (result.CompletedSynchronously)
                {
                    this.FinishEnsureOpen(result, true);
                } 
            }
 
            static void EnsureOpenCallback(IAsyncResult result) 
            {
                if (!result.CompletedSynchronously) 
                {
                    ((SendAsyncResult)result.AsyncState).FinishEnsureOpen(result, false);
                }
            } 

            void FinishEnsureOpen(IAsyncResult result, bool completedSynchronously) 
            { 
                Exception exception = null;
                using (ServiceModelActivity.BoundOperation(this.Rpc.Activity)) 
                {
                    try
                    {
                        this.Rpc.Channel.EndEnsureOpened(result); 
                    }
                    catch (Exception e) 
                    { 
                        if (DiagnosticUtility.IsFatal(e) || completedSynchronously)
                        { 
                            throw;
                        }
                        exception = e;
                    } 

                    if (exception != null) 
                    { 
                        this.CallComplete(completedSynchronously, exception);
                    } 
                    else
                    {
                        this.StartSend(completedSynchronously);
                    } 
                }
            } 
 
            void StartSend(bool completedSynchronously)
            { 
                TimeSpan timeout = this.Rpc.TimeoutHelper.RemainingTime();
                IAsyncResult result = null;
                Exception exception = null;
 
                try
                { 
                    ConcurrencyBehavior.UnlockInstanceBeforeCallout(this.operationContext); 

                    if (this.isOneWay) 
                    {
                        result = this.Rpc.Channel.binder.BeginSend(this.Rpc.Request, timeout, sendCallback, this);
                    }
                    else 
                    {
                        result = this.Rpc.Channel.binder.BeginRequest(this.Rpc.Request, timeout, sendCallback, this); 
                    } 
                }
                catch (Exception e) 
                {
                    if (DiagnosticUtility.IsFatal(e))
                    {
                        throw; 
                    }
                    if (completedSynchronously) 
                    { 
                        ConcurrencyBehavior.LockInstanceAfterCallout(this.operationContext);
                        throw; 
                    }
                    exception = e;
                }
                finally 
                {
                    CallOnceManager.SignalNextIfNonNull(this.Rpc.Channel.autoOpenManager); 
                } 

                if (exception != null) 
                {
                    this.CallComplete(completedSynchronously, exception);
                }
                else if (result.CompletedSynchronously) 
                {
                    this.FinishSend(result, completedSynchronously); 
                } 
            }
 
            static void SendCallback(IAsyncResult result)
            {
                if (!result.CompletedSynchronously)
                { 
                    ((SendAsyncResult)result.AsyncState).FinishSend(result, false);
                } 
            } 

            void FinishSend(IAsyncResult result, bool completedSynchronously) 
            {
                Exception exception = null;

                try 
                {
                    if (this.isOneWay) 
                    { 
                        this.Rpc.Channel.binder.EndSend(result);
                    } 
                    else
                    {
                        this.Rpc.Reply = this.Rpc.Channel.binder.EndRequest(result);
 
                        if (this.Rpc.Reply == null)
                        { 
                            this.Rpc.Channel.ThrowIfFaulted(); 
                            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new CommunicationException(SR.GetString(SR.SFxServerDidNotReply)));
                        } 
                    }
                }
                catch (Exception e)
                { 
                    if (DiagnosticUtility.IsFatal(e))
                    { 
                        throw; 
                    }
                    if (completedSynchronously) 
                    {
                        ConcurrencyBehavior.LockInstanceAfterCallout(this.operationContext);
                        throw;
                    } 
                    exception = e;
                } 
 
                this.CallComplete(completedSynchronously, exception);
            } 

            void CallComplete(bool completedSynchronously, Exception exception)
            {
                this.Rpc.Channel.CompletedIOOperation(); 
                this.Complete(completedSynchronously, exception);
            } 
 
            public static void End(SendAsyncResult result)
            { 
                try
                {
                    AsyncResult.End(result);
                } 
                finally
                { 
                    ConcurrencyBehavior.LockInstanceAfterCallout(result.operationContext); 
                }
            } 
        }

        interface ICallOnce
        { 
            void Call(ServiceChannel channel, TimeSpan timeout);
            IAsyncResult BeginCall(ServiceChannel channel, TimeSpan timeout, AsyncCallback callback, object state); 
            void EndCall(ServiceChannel channel, IAsyncResult result); 
        }
 
        class CallDisplayUIOnce : ICallOnce
        {
            static CallDisplayUIOnce instance;
 
            internal static CallDisplayUIOnce Instance
            { 
                get 
                {
                    if (CallDisplayUIOnce.instance == null) 
                    {
                        CallDisplayUIOnce.instance = new CallDisplayUIOnce();
                    }
                    return CallDisplayUIOnce.instance; 
                }
            } 
 
            [Conditional("DEBUG")]
            void ValidateTimeoutIsMaxValue(TimeSpan timeout) 
            {
                if (timeout != TimeSpan.MaxValue)
                {
                    DiagnosticUtility.DebugAssert("non-MaxValue timeout for displaying interactive initialization UI"); 
                }
            } 
 
            void ICallOnce.Call(ServiceChannel channel, TimeSpan timeout)
            { 
                this.ValidateTimeoutIsMaxValue(timeout);
                channel.DisplayInitializationUI();
            }
 
            IAsyncResult ICallOnce.BeginCall(ServiceChannel channel, TimeSpan timeout, AsyncCallback callback, object state)
            { 
                this.ValidateTimeoutIsMaxValue(timeout); 
                return channel.BeginDisplayInitializationUI(callback, state);
            } 

            void ICallOnce.EndCall(ServiceChannel channel, IAsyncResult result)
            {
                channel.EndDisplayInitializationUI(result); 
            }
        } 
 
        class CallOpenOnce : ICallOnce
        { 
            static CallOpenOnce instance;

            internal static CallOpenOnce Instance
            { 
                get
                { 
                    if (CallOpenOnce.instance == null) 
                    {
                        CallOpenOnce.instance = new CallOpenOnce(); 
                    }
                    return CallOpenOnce.instance;
                }
            } 

            void ICallOnce.Call(ServiceChannel channel, TimeSpan timeout) 
            { 
                channel.Open(timeout);
            } 

            IAsyncResult ICallOnce.BeginCall(ServiceChannel channel, TimeSpan timeout, AsyncCallback callback, object state)
            {
                return channel.BeginOpen(timeout, callback, state); 
            }
 
            void ICallOnce.EndCall(ServiceChannel channel, IAsyncResult result) 
            {
                channel.EndOpen(result); 
            }
        }

        class CallOnceManager 
        {
            readonly ICallOnce callOnce; 
            readonly ServiceChannel channel; 
            bool isFirst = true;
            Queue queue; 

            static WaitCallback signalWaiter = new WaitCallback(CallOnceManager.SignalWaiter);

            internal CallOnceManager(ServiceChannel channel, ICallOnce callOnce) 
            {
                this.callOnce = callOnce; 
                this.channel = channel; 
                this.queue = new Queue();
            } 

            object ThisLock
            {
                get { return this; } 
            }
 
            internal void CallOnce(TimeSpan timeout, CallOnceManager cascade) 
            {
                SyncWaiter waiter = null; 
                bool first = false;

                if (this.queue != null)
                { 
                    lock (this.ThisLock)
                    { 
                        if (this.queue != null) 
                        {
                            if (this.isFirst) 
                            {
                                first = true;
                                this.isFirst = false;
                            } 
                            else
                            { 
                                waiter = new SyncWaiter(this); 
                                this.queue.Enqueue(waiter);
                            } 
                        }
                    }
                }
 
                CallOnceManager.SignalNextIfNonNull(cascade);
 
                if (first) 
                {
                    bool throwing = true; 
                    try
                    {
                        this.callOnce.Call(this.channel, timeout);
                        throwing = false; 
                    }
                    finally 
                    { 
                        if (throwing)
                        { 
                            this.SignalNext();
                        }
                    }
                } 
                else if (waiter != null)
                { 
                    waiter.Wait(timeout); 
                }
            } 

            internal IAsyncResult BeginCallOnce(TimeSpan timeout, CallOnceManager cascade,
                                                AsyncCallback callback, object state)
            { 
                AsyncWaiter waiter = null;
                bool first = false; 
 
                if (this.queue != null)
                { 
                    lock (this.ThisLock)
                    {
                        if (this.queue != null)
                        { 
                            if (this.isFirst)
                            { 
                                first = true; 
                                this.isFirst = false;
                            } 
                            else
                            {
                                waiter = new AsyncWaiter(this, timeout, callback, state);
                                this.queue.Enqueue(waiter); 
                            }
                        } 
                    } 
                }
 
                CallOnceManager.SignalNextIfNonNull(cascade);

                if (first)
                { 
                    bool throwing = true;
                    try 
                    { 
                        IAsyncResult result = this.callOnce.BeginCall(this.channel, timeout, callback, state);
                        throwing = false; 
                        return result;
                    }
                    finally
                    { 
                        if (throwing)
                        { 
                            this.SignalNext(); 
                        }
                    } 
                }
                else if (waiter != null)
                {
                    return waiter; 
                }
                else 
                { 
                    return new CallOnceCompletedAsyncResult(callback, state);
                } 
            }

            internal void EndCallOnce(IAsyncResult result)
            { 
                if (result is CallOnceCompletedAsyncResult)
                { 
                    CallOnceCompletedAsyncResult.End(result); 
                }
                else if (result is AsyncWaiter) 
                {
                    AsyncWaiter.End(result);
                }
                else 
                {
                    bool throwing = true; 
                    try 
                    {
                        this.callOnce.EndCall(this.channel, result); 
                        throwing = false;
                    }
                    finally
                    { 
                        if (throwing)
                        { 
                            this.SignalNext(); 
                        }
                    } 
                }
            }

            static internal void SignalNextIfNonNull(CallOnceManager manager) 
            {
                if (manager != null) 
                { 
                    manager.SignalNext();
                } 
            }

            internal void SignalNext()
            { 
                if (this.queue == null)
                { 
                    return; 
                }
 
                IWaiter waiter = null;

                lock (this.ThisLock)
                { 
                    if (this.queue != null)
                    { 
                        if (this.queue.Count > 0) 
                        {
                            waiter = this.queue.Dequeue(); 
                        }
                        else
                        {
                            this.queue = null; 
                        }
                    } 
                } 

                if (waiter != null) 
                {
                    IOThreadScheduler.ScheduleCallback(CallOnceManager.signalWaiter, waiter);
                }
            } 

            static void SignalWaiter(object state) 
            { 
                ((IWaiter)state).Signal();
            } 

            interface IWaiter
            {
                void Signal(); 
            }
 
            class SyncWaiter : IWaiter 
            {
                ManualResetEvent wait = new ManualResetEvent(false); 
                CallOnceManager manager;
                bool isTimedOut = false;
                bool isSignaled = false;
                int waitCount = 0; 

                internal SyncWaiter(CallOnceManager manager) 
                { 
                    this.manager = manager;
                } 

                bool ShouldSignalNext
                {
                    get { return this.isTimedOut && this.isSignaled; } 
                }
 
                void IWaiter.Signal() 
                {
                    wait.Set(); 
                    this.CloseWaitHandle();

                    bool signalNext;
                    lock (this.manager.ThisLock) 
                    {
                        this.isSignaled = true; 
                        signalNext = this.ShouldSignalNext; 
                    }
                    if (signalNext) 
                    {
                        this.manager.SignalNext();
                    }
                } 

                internal bool Wait(TimeSpan timeout) 
                { 
                    try
                    { 
                        if (!TimeoutHelper.WaitOne(this.wait, timeout, false))
                        {
                            bool signalNext;
                            lock (this.manager.ThisLock) 
                            {
                                this.isTimedOut = true; 
                                signalNext = this.ShouldSignalNext; 
                            }
                            if (signalNext) 
                            {
                                this.manager.SignalNext();
                            }
                        } 
                    }
                    finally 
                    { 
                        this.CloseWaitHandle();
                    } 

                    return !this.isTimedOut;
                }
 
                void CloseWaitHandle()
                { 
                    if (Interlocked.Increment(ref this.waitCount) == 2) 
                    {
                        this.wait.Close(); 
                    }
                }
            }
 
            class AsyncWaiter : AsyncResult, IWaiter
            { 
                static WaitCallback timerCallback = new WaitCallback(AsyncWaiter.TimerCallback); 

                CallOnceManager manager; 
                TimeSpan timeout;
                IOThreadTimer timer;

                internal AsyncWaiter(CallOnceManager manager, TimeSpan timeout, 
                                     AsyncCallback callback, object state)
                    : base(callback, state) 
                { 
                    this.manager = manager;
                    this.timeout = timeout; 

                    if (timeout != TimeSpan.MaxValue)
                    {
                        this.timer = new IOThreadTimer(timerCallback, this, false); 
                        this.timer.Set(timeout);
                    } 
                } 

                internal static void End(IAsyncResult result) 
                {
                    AsyncResult.End(result);
                }
 
                void IWaiter.Signal()
                { 
                    if ((this.timer == null) || this.timer.Cancel()) 
                    {
                        this.Complete(false); 
                        this.manager.channel.Closed -= this.OnClosed;
                    }
                    else
                    { 
                        this.manager.SignalNext();
                    } 
                } 

                void OnClosed(object sender, EventArgs e) 
                {
                    if ((this.timer == null) || this.timer.Cancel())
                    {
                        this.Complete(false, this.manager.channel.CreateClosedException()); 
                    }
                } 
 
                static void TimerCallback(object state)
                { 
                    AsyncWaiter _this = (AsyncWaiter)state;
                    _this.Complete(false, _this.manager.channel.GetOpenTimeoutException(_this.timeout));
                }
            } 
        }
 
        class CallOnceCompletedAsyncResult : AsyncResult 
        {
            internal CallOnceCompletedAsyncResult(AsyncCallback callback, object state) 
                : base(callback, state)
            {
                this.Complete(true);
            } 

            static internal void End(IAsyncResult result) 
            { 
                AsyncResult.End(result);
            } 
        }

        internal class SessionIdleManager
        { 
            readonly IChannelBinder binder;
            ServiceChannel channel; 
            readonly long idleTicks; 
            long lastActivity;
            readonly IOThreadTimer timer; 
            static WaitCallback timerCallback;
            bool didIdleAbort;
            bool isTimerCancelled;
            object thisLock; 

            SessionIdleManager(IChannelBinder binder, TimeSpan idle) 
            { 
                this.binder = binder;
                this.timer = new IOThreadTimer(GetTimerCallback(), this, false); 
                this.idleTicks = Ticks.FromTimeSpan(idle);
                this.timer.SetAt(Ticks.Now + this.idleTicks);
                this.thisLock = new Object();
            } 

            internal static SessionIdleManager CreateIfNeeded(IChannelBinder binder, TimeSpan idle) 
            { 
                if (binder.HasSession && (idle != TimeSpan.MaxValue))
                { 
                    return new SessionIdleManager(binder, idle);
                }
                else
                { 
                    return null;
                } 
            } 

            internal bool DidIdleAbort 
            {
                get
                {
                    lock (thisLock) 
                    {
                        return this.didIdleAbort; 
                    } 
                }
            } 

            internal void CancelTimer()
            {
                lock (thisLock) 
                {
                    this.isTimerCancelled = true; 
                    this.timer.Cancel(); 
                }
            } 

            internal void CompletedActivity()
            {
                Interlocked.Exchange(ref this.lastActivity, Ticks.Now); 
            }
 
            internal void RegisterChannel(ServiceChannel channel, out bool didIdleAbort) 
            {
                lock (thisLock) 
                {
                    this.channel = channel;
                    didIdleAbort = this.didIdleAbort;
                } 
            }
 
            static WaitCallback GetTimerCallback() 
            {
                if (SessionIdleManager.timerCallback == null) 
                {
                    SessionIdleManager.timerCallback = SessionIdleManager.TimerCallback;
                }
                return SessionIdleManager.timerCallback; 
            }
 
            static void TimerCallback(object state) 
            {
                ((SessionIdleManager)state).TimerCallback(); 
            }

            void TimerCallback()
            { 
                // This reads lastActivity atomically without changing its value.
                // (it only sets if it is zero, and then it sets it to zero). 
                long last = Interlocked.CompareExchange(ref this.lastActivity, 0, 0); 
                long abortTime = last + this.idleTicks;
 
                lock (thisLock)
                {
                    if (Ticks.Now > abortTime)
                    { 
                        this.didIdleAbort = true;
                        if (this.channel != null) 
                        { 
                            this.channel.Abort();
                        } 
                        else
                        {
                            this.binder.Abort();
                        } 
                    }
                    else 
                    { 

                        if (!this.isTimerCancelled && binder.Channel.State != CommunicationState.Faulted && binder.Channel.State != CommunicationState.Closed) 
                        {
                            this.timer.SetAt(abortTime);
                        }
                    } 
                }
            } 
        } 
    }
} 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.


                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK