internal UdpChannelListener(UdpTransportBindingElement udpTransportBindingElement, BindingContext context)
            : base(context.Binding)
        {
            Fx.Assert(udpTransportBindingElement != null, "udpTransportBindingElement can't be null");
            Fx.Assert(context != null, "BindingContext parameter can't be null");

            this.udpTransportBindingElement = udpTransportBindingElement;
            this.cleanedUp = 0;

            this.duplicateDetector = null;

            if (udpTransportBindingElement.DuplicateMessageHistoryLength > 0)
            {
                this.duplicateDetector = new DuplicateMessageDetector(udpTransportBindingElement.DuplicateMessageHistoryLength);
            }

            this.onChannelClosed = new EventHandler(OnChannelClosed);

            // We should only throw this exception if the user specified realistic MaxReceivedMessageSize less than or equal to max message size over UDP.
            // If the user specified something bigger like Long.MaxValue, we shouldn't stop them.
            if (this.udpTransportBindingElement.MaxReceivedMessageSize <= UdpConstants.MaxMessageSizeOverIPv4 &&
                this.udpTransportBindingElement.SocketReceiveBufferSize < this.udpTransportBindingElement.MaxReceivedMessageSize)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("SocketReceiveBufferSize", this.udpTransportBindingElement.SocketReceiveBufferSize,
                                                           SR.Property1LessThanOrEqualToProperty2("MaxReceivedMessageSize", this.udpTransportBindingElement.MaxReceivedMessageSize,
                                                                                                  "SocketReceiveBufferSize", this.udpTransportBindingElement.SocketReceiveBufferSize));
            }


            int maxBufferSize = (int)Math.Min(udpTransportBindingElement.MaxReceivedMessageSize, UdpConstants.MaxMessageSizeOverIPv4);

            this.bufferManager = BufferManager.CreateBufferManager(udpTransportBindingElement.MaxBufferPoolSize, maxBufferSize);

            this.messageEncoderFactory = UdpUtility.GetEncoder(context);

            UdpUtility.ValidateDuplicateDetectionAndRetransmittionSupport(this.messageEncoderFactory, this.udpTransportBindingElement.RetransmissionSettings.Enabled, this.udpTransportBindingElement.DuplicateMessageHistoryLength > 0);

            InitUri(context);

            //Note: because we are binding the sockets in InitSockets, we can start receiving data immediately.
            //If there is a delay between the Building of the listener and the call to Open, stale data could build up
            //inside the Winsock buffer.  We have decided that making sure the port is updated correctly in the listen uri
            //(e.g. in the ListenUriMode.Unique case) before leaving the build step is more important than the
            //potential for stale data.
            InitSockets(context.ListenUriMode == ListenUriMode.Unique);

            Fx.Assert(!this.listenUri.IsDefaultPort, "Listen Uri's port should never be the default port: " + this.listenUri);
        }
Exemple #2
0
        public static Message DecodeMessage(DuplicateMessageDetector duplicateDetector, MessageEncoder encoder, BufferManager bufferManager, ArraySegment <byte> data, IPEndPoint remoteEndPoint, int interfaceIndex, bool ignoreSerializationException, out string messageHash)
        {
            Fx.Assert(data != null, "data can't be null");
            Fx.Assert(remoteEndPoint != null, "remoteEndPoint can't be null");
            Fx.Assert(encoder != null, "encoder can't be null");
            Fx.Assert(bufferManager != null, "bufferManager can't be null");

            Message message = null;

            messageHash = null;

            if (duplicateDetector == null || !duplicateDetector.IsDuplicate(data, out messageHash))
            {
                try
                {
                    message = encoder.ReadMessage(data, bufferManager);
                }
                catch (XmlException error)
                {
                    // Don't throw serialization exceptions when the channel supports Multicast
                    if (!ignoreSerializationException)
                    {
                        throw;
                    }

                    FxTrace.Exception.AsWarning(error);
                }

                if (message != null)
                {
                    message.Properties.Add(RemoteEndpointMessageProperty.Name,
                                           new RemoteEndpointMessageProperty(remoteEndPoint.Address.ToString(), remoteEndPoint.Port));

                    NetworkInterfaceMessageProperty networkInterfaceMessageProperty = new NetworkInterfaceMessageProperty(interfaceIndex);
                    networkInterfaceMessageProperty.AddTo(message);
                }
            }

            return(message);
        }
        protected override void OnClosing()
        {
            if (this.channelInstance != null)
            {
                lock (ThisLock)
                {
                    if (this.channelInstance != null)
                    {
                        if (this.channelInstance.TransferReceiveManagerOwnership(this.socketReceiveManager,
                                                                                 this.duplicateDetector))
                        {
                            //don't clean these objects up, they now belong to the channel instance
                            this.socketReceiveManager = null;
                            this.duplicateDetector    = null;
                            this.bufferManager        = null;
                        }
                    }

                    this.channelInstance = null;
                }
            }

            base.OnClosing();
        }
Exemple #4
0
        // Since ChannelListener and channel lifetimes can be different, we need a
        // way to transfer the socketReceiveManager and DuplicateMessageDetection
        // objects to the channel if the listener gets closed.  If this method succeeds, then
        // this also indicates that the bufferManager is no longer owned by the channel listener,
        // so we have to clean that up also.
        internal bool TransferReceiveManagerOwnership(UdpSocketReceiveManager socketReceiveManager, DuplicateMessageDetector duplicateDetector)
        {
            bool success = false;

            if (this.State == CommunicationState.Opened)
            {
                lock (ThisLock)
                {
                    if (this.State == CommunicationState.Opened)
                    {
                        Fx.Assert(this.ReceiveManager == null, "ReceiveManager is already set to a non-null value");
                        Fx.Assert(this.DuplicateDetector == null, "DuplicateDetector is already set to a non-null value");

                        this.ReceiveManager    = socketReceiveManager;
                        this.OwnsBufferManager = true;
                        this.ReceiveManager.SetReceiveHandler(this);
                        this.DuplicateDetector = duplicateDetector;
                        success = true;
                    }
                }
            }

            return(success);
        }
        public static Message DecodeMessage(DuplicateMessageDetector duplicateDetector, MessageEncoder encoder, BufferManager bufferManager, ArraySegment<byte> data, IPEndPoint remoteEndPoint, int interfaceIndex, bool ignoreSerializationException, out string messageHash)
        {
            Fx.Assert(data != null, "data can't be null");
            Fx.Assert(remoteEndPoint != null, "remoteEndPoint can't be null");
            Fx.Assert(encoder != null, "encoder can't be null");
            Fx.Assert(bufferManager != null, "bufferManager can't be null");
            
            Message message = null;

            messageHash = null;

            if (duplicateDetector == null  || !duplicateDetector.IsDuplicate(data, out messageHash))
            {
                try
                {
                    message = encoder.ReadMessage(data, bufferManager);
                }
                catch (XmlException error)
                {
                    // Don't throw serialization exceptions when the channel supports Multicast
                    if (!ignoreSerializationException)
                    {
                        throw;
                    }

                    FxTrace.Exception.AsWarning(error);
                }

                if (message != null)
                {
                    message.Properties.Add(RemoteEndpointMessageProperty.Name,
                        new RemoteEndpointMessageProperty(remoteEndPoint.Address.ToString(), remoteEndPoint.Port));

                    NetworkInterfaceMessageProperty networkInterfaceMessageProperty = new NetworkInterfaceMessageProperty(interfaceIndex);
                    networkInterfaceMessageProperty.AddTo(message);
                }
            }

            return message;
        }