OneWayChannelFactory.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 / OneWayChannelFactory.cs / 2 / OneWayChannelFactory.cs

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

namespace System.ServiceModel.Channels 
{
    using System.Collections.Generic; 
    using System.Diagnostics; 
    using System.IO;
    using System.Text; 
    using System.Threading;
    using System.Runtime.Serialization;
    using System.ServiceModel.Diagnostics;
    using System.Xml; 

    class PacketRoutableHeader : DictionaryHeader 
    { 
        PacketRoutableHeader()
            : base() 
        {
        }

        public static void AddHeadersTo(Message message, MessageHeader header) 
        {
            int index = message.Headers.FindHeader(DotNetOneWayStrings.HeaderName, DotNetOneWayStrings.Namespace); 
            if (index == -1) 
            {
                if (header == null) 
                {
                    header = PacketRoutableHeader.Create();
                }
                message.Headers.Add(header); 
            }
        } 
 
        public static void ValidateMessage(Message message)
        { 
            if (!TryValidateMessage(message))
            {
                throw TraceUtility.ThrowHelperError(
                    new ProtocolException(SR.GetString(SR.OneWayHeaderNotFound)), message); 
            }
        } 
 
        public static bool TryValidateMessage(Message message)
        { 
            int index = message.Headers.FindHeader(
                DotNetOneWayStrings.HeaderName, DotNetOneWayStrings.Namespace);

            return (index != -1); 
        }
 
        public static PacketRoutableHeader Create() 
        {
            return new PacketRoutableHeader(); 
        }

        public override XmlDictionaryString DictionaryName
        { 
            get { return XD.DotNetOneWayDictionary.HeaderName; }
        } 
 
        public override XmlDictionaryString DictionaryNamespace
        { 
            get { return XD.DotNetOneWayDictionary.Namespace; }
        }

        protected override void OnWriteHeaderContents(XmlDictionaryWriter writer, MessageVersion messageVersion) 
        {
            // no contents necessary 
        } 
    }
 
    /// 
    /// OneWayChannelFactory built on top of IRequestChannel
    /// 
    class RequestOneWayChannelFactory : LayeredChannelFactory 
    {
        PacketRoutableHeader packetRoutableHeader; 
 
        public RequestOneWayChannelFactory(OneWayBindingElement bindingElement, BindingContext context)
            : base(context.Binding, context.BuildInnerChannelFactory()) 
        {
            if (bindingElement.PacketRoutable)
            {
                this.packetRoutableHeader = PacketRoutableHeader.Create(); 
            }
        } 
 
        protected override IOutputChannel OnCreateChannel(EndpointAddress to, Uri via)
        { 
            IRequestChannel innerChannel =
                ((IChannelFactory)this.InnerChannelFactory).CreateChannel(to, via);

            return new RequestOutputChannel(this, innerChannel, this.packetRoutableHeader); 
        }
 
        class RequestOutputChannel : OutputChannel 
        {
            IRequestChannel innerChannel; 
            MessageHeader packetRoutableHeader;

            public RequestOutputChannel(ChannelManagerBase factory,
                IRequestChannel innerChannel, MessageHeader packetRoutableHeader) 
                : base(factory)
            { 
                this.innerChannel = innerChannel; 
                this.packetRoutableHeader = packetRoutableHeader;
            } 

            #region Inner Channel delegation
            public override EndpointAddress RemoteAddress
            { 
                get { return this.innerChannel.RemoteAddress; }
            } 
 
            public override Uri Via
            { 
                get { return this.innerChannel.Via; }
            }

            protected override void OnAbort() 
            {
                this.innerChannel.Abort(); 
            } 

            protected override void OnOpen(TimeSpan timeout) 
            {
                this.innerChannel.Open(timeout);
            }
 
            protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)
            { 
                return this.innerChannel.BeginOpen(timeout, callback, state); 
            }
 
            protected override void OnEndOpen(IAsyncResult result)
            {
                this.innerChannel.EndOpen(result);
            } 

            protected override void OnClose(TimeSpan timeout) 
            { 
                this.innerChannel.Close(timeout);
            } 

            protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
            {
                return this.innerChannel.BeginClose(timeout, callback, state); 
            }
 
            protected override void OnEndClose(IAsyncResult result) 
            {
                this.innerChannel.EndClose(result); 
            }
            #endregion

            // add our oneWay header to every message (if it's not already there) 
            protected override void AddHeadersTo(Message message)
            { 
                base.AddHeadersTo(message); 

                if (this.packetRoutableHeader != null) 
                {
                    PacketRoutableHeader.AddHeadersTo(message, this.packetRoutableHeader);
                }
            } 

            protected override void OnSend(Message message, TimeSpan timeout) 
            { 
                Message response = this.innerChannel.Request(message, timeout);
                using (response) 
                {
                    ValidateResponse(response);
                }
            } 

            protected override IAsyncResult OnBeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state) 
            { 
                return this.innerChannel.BeginRequest(message, timeout, callback, state);
            } 

            protected override void OnEndSend(IAsyncResult result)
            {
                Message response = this.innerChannel.EndRequest(result); 
                using (response)
                { 
                    ValidateResponse(response); 
                }
            } 

            void ValidateResponse(Message response)
            {
                if (response != null) 
                {
                    if (response.Version == MessageVersion.None && response is NullMessage) 
                    { 
                        response.Close();
                        return; 
                    }

                    Exception innerException = null;
 
                    if (response.IsFault)
                    { 
                        try 
                        {
                            MessageFault messageFault = MessageFault.CreateFault(response, TransportDefaults.MaxFaultSize); 
                            innerException = new FaultException(messageFault);
                        }
                        catch (Exception e)
                        { 
                            if (DiagnosticUtility.IsFatal(e))
                            { 
                                throw; 
                            }
 
                            if (e is CommunicationException ||
                                e is TimeoutException ||
                                e is XmlException ||
                                e is IOException) 
                            {
                                innerException = e; // expected exception generating fault 
                            } 
                            else
                            { 
                                throw;
                            }
                        }
                    } 

                    throw TraceUtility.ThrowHelperError( 
                        new ProtocolException(SR.GetString(SR.OneWayUnexpectedResponse), innerException), 
                        response);
                } 
            }
        }
    }
 
    /// 
    /// OneWayChannelFactory built on top of IDuplexSessionChannel 
    ///  
    class DuplexSessionOneWayChannelFactory : LayeredChannelFactory
    { 
        ChannelPool channelPool;
        ChannelPoolSettings channelPoolSettings;
        bool packetRoutable;
 
        public DuplexSessionOneWayChannelFactory(OneWayBindingElement bindingElement, BindingContext context)
            : base(context.Binding, context.BuildInnerChannelFactory()) 
        { 
            this.packetRoutable = bindingElement.PacketRoutable;
 
            ISecurityCapabilities innerSecurityCapabilities = this.InnerChannelFactory.GetProperty();

            // can't pool across outer channels if the inner channels support client auth
            if (innerSecurityCapabilities != null && innerSecurityCapabilities.SupportsClientAuthentication) 
            {
                this.channelPoolSettings = bindingElement.ChannelPoolSettings.Clone(); 
            } 
            else
            { 
                this.channelPool = new ChannelPool(bindingElement.ChannelPoolSettings);
            }
        }
 
        internal ChannelPool GetChannelPool(out bool cleanupChannelPool)
        { 
            if (this.channelPool != null) 
            {
                cleanupChannelPool = false; 
                return this.channelPool;
            }
            else
            { 
                cleanupChannelPool = true;
                DiagnosticUtility.DebugAssert(this.channelPoolSettings != null, "Need either settings or a pool"); 
                return new ChannelPool(this.channelPoolSettings); 
            }
        } 

        protected override void OnAbort()
        {
            if (this.channelPool != null) 
            {
                this.channelPool.Close(TimeSpan.Zero); 
            } 
            base.OnAbort();
        } 

        protected override void OnClose(TimeSpan timeout)
        {
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout); 
            if (this.channelPool != null)
            { 
                this.channelPool.Close(timeoutHelper.RemainingTime()); 
            }
            base.OnClose(timeoutHelper.RemainingTime()); 
        }

        protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
        { 
            TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
            if (this.channelPool != null) 
            { 
                this.channelPool.Close(timeoutHelper.RemainingTime());
            } 
            return base.OnBeginClose(timeoutHelper.RemainingTime(), callback, state);
        }

        protected override IOutputChannel OnCreateChannel(EndpointAddress address, Uri via) 
        {
            return new DuplexSessionOutputChannel(this, address, via); 
        } 

        class DuplexSessionOutputChannel : OutputChannel 
        {
            ChannelPool channelPool;
            EndpointAddress remoteAddress;
            IChannelFactory innerFactory; 
            AsyncCallback onReceive;
            bool packetRoutable; 
            bool cleanupChannelPool; 
            Uri via;
 
            public DuplexSessionOutputChannel(DuplexSessionOneWayChannelFactory factory,
                EndpointAddress remoteAddress, Uri via)
                : base(factory)
            { 
                this.channelPool = factory.GetChannelPool(out cleanupChannelPool);
                this.packetRoutable = factory.packetRoutable; 
                this.innerFactory = (IChannelFactory)factory.InnerChannelFactory; 
                this.remoteAddress = remoteAddress;
                this.via = via; 
            }

            public override EndpointAddress RemoteAddress
            { 
                get { return this.remoteAddress; }
            } 
 
            public override Uri Via
            { 
                get { return this.via; }
            }

            #region Channel Lifetime 
            protected override void OnOpen(TimeSpan timeout)
            { 
            } 

            protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 
            {
                return new CompletedAsyncResult(callback, state);
            }
 
            protected override void OnEndOpen(IAsyncResult result)
            { 
                CompletedAsyncResult.End(result); 
            }
 
            protected override void OnAbort()
            {
                if (cleanupChannelPool)
                { 
                    this.channelPool.Close(TimeSpan.Zero);
                } 
            } 

            protected override void OnClose(TimeSpan timeout) 
            {
                if (cleanupChannelPool)
                {
                    this.channelPool.Close(timeout); 
                }
            } 
 
            protected override IAsyncResult OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)
            { 
                if (cleanupChannelPool)
                {
                    this.channelPool.Close(timeout);
                } 
                return new CompletedAsyncResult(callback, state);
            } 
 
            protected override void OnEndClose(IAsyncResult result)
            { 
                CompletedAsyncResult.End(result);
            }
            #endregion
 
            protected override IAsyncResult OnBeginSend(Message message, TimeSpan timeout, AsyncCallback callback, object state)
            { 
                return new SendAsyncResult(this, message, timeout, callback, state); 
            }
 
            protected override void OnEndSend(IAsyncResult result)
            {
                SendAsyncResult.End(result);
            } 

            protected override void OnSend(Message message, TimeSpan timeout) 
            { 
                TimeoutHelper timeoutHelper = new TimeoutHelper(timeout);
                ChannelPoolKey key = null; 
                bool isConnectionFromPool = true;
                IDuplexSessionChannel innerChannel =
                    GetChannelFromPool(ref timeoutHelper, out key, out isConnectionFromPool);
 
                bool success = false;
                try 
                { 
                    if (!isConnectionFromPool)
                    { 
                        StampInitialMessage(message);
                        innerChannel.Open(timeoutHelper.RemainingTime());
                        StartBackgroundReceive(innerChannel);
                    } 

                    innerChannel.Send(message, timeoutHelper.RemainingTime()); 
                    success = true; 
                }
                finally 
                {
                    if (!success)
                    {
                        CleanupChannel(innerChannel, false, key, isConnectionFromPool, ref timeoutHelper); 
                    }
                } 
 
                CleanupChannel(innerChannel, true, key, isConnectionFromPool, ref timeoutHelper);
            } 

            // kick off an async receive so that we notice when the server is trying to shutdown
            void StartBackgroundReceive(IDuplexSessionChannel channel)
            { 
                if (this.onReceive == null)
                { 
                    this.onReceive = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnReceive)); 
                }
 
                channel.BeginReceive(TimeSpan.MaxValue, this.onReceive, channel);
            }

            void OnReceive(IAsyncResult result) 
            {
                IDuplexSessionChannel channel = (IDuplexSessionChannel)result.AsyncState; 
                bool success = false; 
                try
                { 
                    Message message = channel.EndReceive(result);
                    if (message == null)
                    {
                        channel.Close(this.channelPool.IdleTimeout); 
                        success = true;
                    } 
                    else 
                    {
                        message.Close(); 
                    }
                }
                catch (CommunicationException e)
                { 
                    if (DiagnosticUtility.ShouldTraceInformation)
                    { 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information); 
                    }
                } 
                catch (TimeoutException e)
                {
                    if (DiagnosticUtility.ShouldTraceInformation)
                    { 
                        DiagnosticUtility.ExceptionUtility.TraceHandledException(e, TraceEventType.Information);
                    } 
                } 
                finally
                { 
                    if (!success)
                    {
                        channel.Abort();
                    } 
                }
            } 
 
            void StampInitialMessage(Message message)
            { 
                if (this.packetRoutable)
                {
                    PacketRoutableHeader.AddHeadersTo(message, null);
                } 
            }
 
            void CleanupChannel(IDuplexSessionChannel channel, bool connectionStillGood, ChannelPoolKey key, bool isConnectionFromPool, ref TimeoutHelper timeoutHelper) 
            {
                if (isConnectionFromPool) 
                {
                    this.channelPool.ReturnConnection(key, channel, connectionStillGood, timeoutHelper.RemainingTime());
                }
                else 
                {
                    if (connectionStillGood) 
                    { 
                        this.channelPool.AddConnection(key, channel, timeoutHelper.RemainingTime());
                    } 
                    else
                    {
                        channel.Abort();
                    } 
                }
            } 
 
            IDuplexSessionChannel GetChannelFromPool(ref TimeoutHelper timeoutHelper, out ChannelPoolKey key,
                out bool isConnectionFromPool) 
            {
                isConnectionFromPool = true;
                while (true)
                { 
                    IDuplexSessionChannel pooledChannel
                        = this.channelPool.TakeConnection(this.RemoteAddress, this.Via, timeoutHelper.RemainingTime(), out key); 
 
                    if (pooledChannel == null)
                    { 
                        isConnectionFromPool = false;
                        return this.innerFactory.CreateChannel(RemoteAddress, Via);
                    }
 
                    // only return good connections
                    if (pooledChannel.State == CommunicationState.Opened) 
                    { 
                        return pooledChannel;
                    } 

                    // Abort stale connections from the pool
                    this.channelPool.ReturnConnection(key, pooledChannel, false, timeoutHelper.RemainingTime());
                } 
            }
 
            class SendAsyncResult : AsyncResult 
            {
                DuplexSessionOutputChannel parent; 
                IDuplexSessionChannel innerChannel;
                Message message;
                TimeoutHelper timeoutHelper;
                static AsyncCallback onOpen; 
                static AsyncCallback onInnerSend = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnInnerSend));
                ChannelPoolKey key; 
                bool isConnectionFromPool; 

                public SendAsyncResult(DuplexSessionOutputChannel parent, Message message, TimeSpan timeout, 
                    AsyncCallback callback, object state)
                    : base(callback, state)
                {
                    this.parent = parent; 
                    this.message = message;
                    this.timeoutHelper = new TimeoutHelper(timeout); 
                    this.innerChannel = 
                        parent.GetChannelFromPool(ref this.timeoutHelper, out this.key, out this.isConnectionFromPool);
 
                    bool success = false;
                    bool completeSelf = true;
                    try
                    { 
                        if (!this.isConnectionFromPool)
                        { 
                            completeSelf = OpenNewChannel(); 
                        }
 
                        if (completeSelf)
                        {
                            completeSelf = SendMessage();
                        } 
                        success = true;
                    } 
                    finally 
                    {
                        if (!success) 
                        {
                            Cleanup(false);
                        }
                    } 

                    if (completeSelf) 
                    { 
                        Cleanup(true);
                        base.Complete(true); 
                    }
                }

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

                void Cleanup(bool connectionStillGood) 
                {
                    parent.CleanupChannel(this.innerChannel, connectionStillGood, this.key,
                        this.isConnectionFromPool, ref this.timeoutHelper);
                } 

                bool OpenNewChannel() 
                { 
                    if (onOpen == null)
                    { 
                        onOpen = DiagnosticUtility.ThunkAsyncCallback(new AsyncCallback(OnOpen));
                    }

                    this.parent.StampInitialMessage(this.message); 
                    IAsyncResult result = this.innerChannel.BeginOpen(timeoutHelper.RemainingTime(), onOpen, this);
                    if (!result.CompletedSynchronously) 
                    { 
                        return false;
                    } 

                    this.CompleteOpen(result);
                    return true;
                } 

                void CompleteOpen(IAsyncResult result) 
                { 
                    this.innerChannel.EndOpen(result);
                    this.parent.StartBackgroundReceive(this.innerChannel); 
                }

                bool SendMessage()
                { 
                    IAsyncResult result = innerChannel.BeginSend(this.message, onInnerSend, this);
                    if (!result.CompletedSynchronously) 
                    { 
                        return false;
                    } 

                    innerChannel.EndSend(result);
                    return true;
                } 

                static void OnOpen(IAsyncResult result) 
                { 
                    if (result.CompletedSynchronously)
                    { 
                        return;
                    }

                    SendAsyncResult thisPtr = (SendAsyncResult)result.AsyncState; 

                    Exception completionException = null; 
                    bool completeSelf = false; 
                    try
                    { 
                        thisPtr.CompleteOpen(result);
                        completeSelf = thisPtr.SendMessage();
                    }
#pragma warning suppress 56500 // [....], transferring exception to another thread 
                    catch (Exception e)
                    { 
                        if (DiagnosticUtility.IsFatal(e)) 
                        {
                            throw; 
                        }

                        completeSelf = true;
                        completionException = e; 
                    }
 
                    if (completeSelf) 
                    {
                        thisPtr.Cleanup(completionException == null); 
                        thisPtr.Complete(false, completionException);
                    }
                }
 
                static void OnInnerSend(IAsyncResult result)
                { 
                    if (result.CompletedSynchronously) 
                    {
                        return; 
                    }

                    SendAsyncResult thisPtr = (SendAsyncResult)result.AsyncState;
 
                    Exception completionException = null;
                    try 
                    { 
                        thisPtr.innerChannel.EndSend(result);
                    } 
#pragma warning suppress 56500 // [....], transferring exception to another thread
                    catch (Exception e)
                    {
                        if (DiagnosticUtility.IsFatal(e)) 
                        {
                            throw; 
                        } 

                        completionException = e; 
                    }

                    thisPtr.Cleanup(completionException == null);
                    thisPtr.Complete(false, completionException); 
                }
            } 
        } 
    }
} 

// 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