UdpChannelFactory.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Discovery / System / ServiceModel / Channels / UdpChannelFactory.cs / 1484997 / UdpChannelFactory.cs

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

namespace System.ServiceModel.Channels 
{
    using System; 
    using System.Collections.Generic; 
    using System.Net;
    using System.Net.NetworkInformation; 
    using System.Net.Sockets;
    using System.Runtime;
    using System.ServiceModel.Discovery;
 
    class UdpChannelFactory : ChannelFactoryBase
    { 
        MessageEncoderFactory messageEncoderFactory; 
        IUdpTransportSettings settings;
 
        internal UdpChannelFactory(IUdpTransportSettings settings, BindingContext context)
            : base(context.Binding)
        {
            Fx.Assert(settings != null, "settings can't be null"); 
            Fx.Assert(context != null, "binding context can't be null");
 
            this.settings = settings; 

            if (this.settings.SocketReceiveBufferSize < this.settings.MaxReceivedMessageSize) 
            {
                throw FxTrace.Exception.ArgumentOutOfRange("SocketReceiveBufferSize", this.settings.SocketReceiveBufferSize,
                    SR.Property1LessThanOrEqualToProperty2("MaxReceivedMessageSize", this.settings.MaxReceivedMessageSize,
                    "SocketReceiveBufferSize", this.settings.SocketReceiveBufferSize)); 
            }
 
            this.messageEncoderFactory = UdpUtility.GetEncoder(context); 

            this.BufferManager = BufferManager.CreateBufferManager(settings.MaxBufferPoolSize, (int)settings.MaxReceivedMessageSize); 

        }

        BufferManager BufferManager 
        {
            get; 
            set; 
        }
 
        public override T GetProperty()
        {
            T messageEncoderProperty = this.messageEncoderFactory.Encoder.GetProperty();
            if (messageEncoderProperty != null) 
            {
                return messageEncoderProperty; 
            } 

            if (typeof(T) == typeof(MessageVersion)) 
            {
                return (T)(object)this.messageEncoderFactory.Encoder.MessageVersion;
            }
 
            return base.GetProperty();
        } 
 

        protected override IAsyncResult OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state) 
        {
            this.OnOpen(timeout);
            return new CompletedAsyncResult(callback, state);
        } 

        protected override IDuplexChannel OnCreateChannel(EndpointAddress to, Uri via) 
        { 
            Fx.Assert(to != null, "To address should have been validated as non-null by ChannelFactoryBase");
            Fx.Assert(via != null, "Via address should have been validated as non-null by ChannelFactoryBase"); 

            if (!via.IsAbsoluteUri)
            {
                throw FxTrace.Exception.Argument("via", SR.RelativeUriNotAllowed(via)); 
            }
 
            if (!via.Scheme.Equals(UdpConstants.Scheme, StringComparison.OrdinalIgnoreCase)) 
            {
                throw FxTrace.Exception.Argument("via", SR.UriSchemeNotSupported(via.Scheme)); 
            }

            if (!UdpUtility.IsSupportedHostNameType(via.HostNameType))
            { 
                throw FxTrace.Exception.Argument("via", SR.UnsupportedUriHostNameType(via.Host, via.HostNameType));
            } 
 
            if (via.IsDefaultPort || via.Port == 0)
            { 
                throw FxTrace.Exception.ArgumentOutOfRange("via", via, SR.PortNumberRequiredOnVia(via));
            }

            UdpSocket[] sockets = null; 
            IPEndPoint remoteEndPoint = null;
            ClientUdpDuplexChannel channel; 
 
            lock (this.ThisLock)
            { 
                bool isMulticast;
                sockets = GetSockets(via, out remoteEndPoint, out isMulticast);

                EndpointAddress localAddress = new EndpointAddress(EndpointAddress.AnonymousUri); 

                channel = new ClientUdpDuplexChannel(this, sockets, remoteEndPoint, localAddress, to, via, isMulticast); 
            } 

            return channel; 
        }

        protected override void OnEndOpen(IAsyncResult result)
        { 
            CompletedAsyncResult.End(result);
        } 
 
        protected override void OnOpen(TimeSpan timeout)
        { 

        }

        //will only return > 1 socket when both of the following are true: 
        // 1) multicast
        // 2) sending on all interfaces 
        UdpSocket[] GetSockets(Uri via, out IPEndPoint remoteEndPoint, out bool isMulticast) 
        {
            UdpSocket[] results = null; 

            remoteEndPoint = null;
            IPAddress[] remoteAddressList;
            isMulticast = false; 

            UdpUtility.ThrowIfNoSocketSupport(); 
 
            if (via.HostNameType == UriHostNameType.IPv6 || via.HostNameType == UriHostNameType.IPv4)
            { 
                IPAddress address = IPAddress.Parse(via.DnsSafeHost);
                isMulticast = UdpUtility.IsMulticastAddress(address);
                if (isMulticast && !settings.EnableMulticast)
                { 
                    throw FxTrace.Exception.AsError(new InvalidOperationException(SR.UdpMulticastNotEnabled(via)));
                } 
 
                remoteAddressList = new IPAddress[] { address };
            } 
            else
            {
                remoteAddressList = DnsCache.Resolve(via.DnsSafeHost).AddressList;
            } 

            if (remoteAddressList.Length < 1) 
            { 
                // System.Net.Dns shouldn't ever allow this to happen, but...
                Fx.Assert("DnsCache returned a HostEntry with zero length address list"); 
                throw FxTrace.Exception.AsError(new EndpointNotFoundException(SR.DnsResolveFailed(via.DnsSafeHost)));
            }

            remoteEndPoint = new IPEndPoint(remoteAddressList[0], via.Port); 

            IPAddress localAddress; 
            if (via.IsLoopback) 
            {
                localAddress = (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Loopback : IPAddress.IPv6Loopback); 
            }
            else
            {
                localAddress = (remoteEndPoint.AddressFamily == AddressFamily.InterNetwork ? IPAddress.Any : IPAddress.IPv6Any); 
            }
 
            int port = 0; 

            if (isMulticast) 
            {
                List socketList = new List();
                NetworkInterface[] adapters = UdpUtility.GetMulticastInterfaces(this.settings.MulticastInterfaceId);
 
                //if listening on a specific adapter, don't disable multicast loopback on that adapter.
                bool allowMulticastLoopback = !string.IsNullOrEmpty(this.settings.MulticastInterfaceId); 
 
                for (int i = 0; i < adapters.Length; i++)
                { 
                    if (adapters[i].OperationalStatus == OperationalStatus.Up)
                    {
                        IPInterfaceProperties properties = adapters[i].GetIPProperties();
                        bool isLoopbackAdapter = adapters[i].NetworkInterfaceType == NetworkInterfaceType.Loopback; 

                        if (isLoopbackAdapter) 
                        { 
                            socketList.Add(UdpUtility.CreateListenSocket(localAddress, ref port, this.settings.SocketReceiveBufferSize, this.settings.TimeToLive,
                                UdpUtility.GetLoopbackInterfaceIndex(adapters[i], localAddress.AddressFamily == AddressFamily.InterNetwork), 
                                allowMulticastLoopback, isLoopbackAdapter));
                        }
                        else if (localAddress.AddressFamily == AddressFamily.InterNetworkV6)
                        { 
                            if (adapters[i].Supports(NetworkInterfaceComponent.IPv6))
                            { 
                                IPv6InterfaceProperties v6Properties = properties.GetIPv6Properties(); 

                                if (v6Properties != null) 
                                {
                                    socketList.Add(UdpUtility.CreateListenSocket(localAddress, ref port, this.settings.SocketReceiveBufferSize,
                                        this.settings.TimeToLive, v6Properties.Index, allowMulticastLoopback, isLoopbackAdapter));
                                } 
                            }
                        } 
                        else 
                        {
                            if (adapters[i].Supports(NetworkInterfaceComponent.IPv4)) 
                            {
                                IPv4InterfaceProperties v4Properties = properties.GetIPv4Properties();
                                if (v4Properties != null)
                                { 
                                    socketList.Add(UdpUtility.CreateListenSocket(localAddress, ref port, this.settings.SocketReceiveBufferSize,
                                        this.settings.TimeToLive, v4Properties.Index, allowMulticastLoopback, isLoopbackAdapter)); 
                                } 
                            }
                        } 
                    }

                    //CreateListenSocket sets the port, but since we aren't listening
                    //on multicast, each socket can't share the same port. 
                    port = 0;
                } 
 
                if (socketList.Count == 0)
                { 
                    throw FxTrace.Exception.AsError(new ArgumentException(SR.UdpFailedToFindMulticastAdapter(via)));
                }

                results = socketList.ToArray(); 
            }
            else 
            { 
                UdpSocket socket = UdpUtility.CreateUnicastListenSocket(localAddress, ref port, this.settings.SocketReceiveBufferSize,
                    this.settings.TimeToLive); 

                results = new UdpSocket[] { socket };
            }
 

            Fx.Assert(results != null, "GetSockets(...) return results should never be null. An exception should have been thrown but wasn't."); 
            return results; 

        } 

        sealed class ClientUdpDuplexChannel : UdpDuplexChannel
        {
            EndpointAddress to; 
            ChannelParameterCollection channelParameters;
 
            internal ClientUdpDuplexChannel(UdpChannelFactory factory, UdpSocket[] sockets, IPEndPoint remoteEndPoint, EndpointAddress localAddress, EndpointAddress to, Uri via, bool isMulticast) 
                : base(factory,
                factory.messageEncoderFactory.Encoder, 
                factory.BufferManager,
                sockets,
                factory.settings.RetransmissionSettings,
                factory.settings.MaxPendingMessageCount, 
                localAddress,
                via, 
                isMulticast, (int)factory.settings.MaxReceivedMessageSize) 
            {
                Fx.Assert(to != null, "to address can't be null for this constructor..."); 
                Fx.Assert(remoteEndPoint != null, "remoteEndPoint can't be null");

                this.RemoteEndPoint = remoteEndPoint;
                this.to = to; 

                if (factory.settings.DuplicateMessageHistoryLength > 0) 
                { 
                    this.DuplicateDetector = new DuplicateMessageDetector(factory.settings.DuplicateMessageHistoryLength);
                } 
                else
                {
                    this.DuplicateDetector = null;
                } 
            }
 
            protected override bool IgnoreSerializationException 
            {
                get 
                {
                    return this.IsMulticast;
                }
            } 

            public override EndpointAddress RemoteAddress 
            { 
                get
                { 
                    return this.to;
                }
            }
 
            public IPEndPoint RemoteEndPoint
            { 
                get; 
                private set;
            } 

            public override T GetProperty()
            {
                if (typeof(T) == typeof(ChannelParameterCollection)) 
                {
                    if (this.State == CommunicationState.Created) 
                    { 
                        lock (ThisLock)
                        { 
                            if (this.channelParameters == null)
                            {
                                this.channelParameters = new ChannelParameterCollection();
                            } 
                        }
                    } 
                    return (T)(object)this.channelParameters; 
                }
                else 
                {
                    return base.GetProperty();
                }
            } 

            protected override UdpSocket[]  GetSendSockets(Message message, out IPEndPoint remoteEndPoint, out Exception exceptionToBeThrown) 
            { 
                UdpSocket[] socketList = null;
                remoteEndPoint = this.RemoteEndPoint; 
                exceptionToBeThrown = null;

                if (this.IsMulticast)
                { 
                    //always send on all sockets...
                    socketList = this.Sockets; 
                } 
                else
                { 
                    Fx.Assert(this.Sockets.Length == 1, "Unicast Send socket list on client should always be 1 item long");
                    socketList = this.Sockets;
                }
 
                return socketList;
            } 
 
            protected override void OnOpened()
            { 
                this.ReceiveManager = new UdpSocketReceiveManager(this.Sockets,
                    UdpConstants.PendingReceiveCountPerProcessor * Environment.ProcessorCount,
                    base.BufferManager,
                    this); 

                //do the state change to CommunicationState.Opened before starting the receive loop. 
                //this avoids a ---- between transitioning state and processing messages that are 
                //already in the socket receive buffer.
                base.OnOpened(); 

                this.ReceiveManager.Open();
            }
 
            protected override void AddHeadersTo(Message message)
            { 
                Fx.Assert(message != null, "Message can't be null"); 

                if (message.Version.Addressing != AddressingVersion.None) 
                {
                    this.to.ApplyTo(message);
                }
 
                message.Properties.Via = this.Via;
 
                base.AddHeadersTo(message); 
            }
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.


                        

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