File: FrameworkFork\System.ServiceModel\System\ServiceModel\Channels\UdpRetransmissionSettings.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
namespace System.ServiceModel.Channels
{
    using System;
    using System.ComponentModel;
    using System.Globalization;
    using System.Runtime;
 
    public sealed class UdpRetransmissionSettings
    {
        private int _maxUnicastRetransmitCount;
        private int _maxMulticastRetransmitCount;
        private TimeSpan _delayLowerBound;
        private TimeSpan _delayUpperBound;
        private TimeSpan _maxDelayPerRetransmission;
        private int _delayLowerBoundMilliseconds;
        private int _delayUpperBoundMilliseconds;
        private int _maxDelayMilliseconds;
 
        //this constructor disables retransmission
        public UdpRetransmissionSettings()
            : this(0, 0)
        {
        }
 
        public UdpRetransmissionSettings(int maxUnicastRetransmitCount, int maxMulticastRetransmitCount)
            : this(maxUnicastRetransmitCount, maxMulticastRetransmitCount,
            UdpConstants.Defaults.DelayLowerBoundTimeSpan, UdpConstants.Defaults.DelayUpperBoundTimeSpan, UdpConstants.Defaults.MaxDelayPerRetransmissionTimeSpan)
        {
        }
 
        public UdpRetransmissionSettings(int maxUnicastRetransmitCount, int maxMulticastRetransmitCount, TimeSpan delayLowerBound, TimeSpan delayUpperBound, TimeSpan maxDelayPerRetransmission)
        {
            if (maxUnicastRetransmitCount < 0)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("maxUnicastRetransmitCount", maxUnicastRetransmitCount,
                    string.Format(SRServiceModel.ArgumentOutOfMinRange, 0));
            }
 
            if (maxMulticastRetransmitCount < 0)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("maxMulticastRetransmitCount", maxMulticastRetransmitCount,
                    string.Format(SRServiceModel.ArgumentOutOfMinRange, 0));
            }
 
 
            if (delayLowerBound < TimeSpan.Zero)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("delayLowerBound", delayLowerBound, string.Format(SRServiceModel.ArgumentOutOfMinRange, TimeSpan.Zero));
            }
 
            if (delayUpperBound < TimeSpan.Zero)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("delayUpperBound", delayUpperBound, string.Format(SRServiceModel.ArgumentOutOfMinRange, TimeSpan.Zero));
            }
 
            if (maxDelayPerRetransmission < TimeSpan.Zero)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("maxDelayPerRetransmission", maxDelayPerRetransmission,
                     string.Format(SRServiceModel.ArgumentOutOfMinRange, TimeSpan.Zero));
            }
 
            _maxUnicastRetransmitCount = maxUnicastRetransmitCount;
            _maxMulticastRetransmitCount = maxMulticastRetransmitCount;
            _delayLowerBound = delayLowerBound;
            _delayUpperBound = delayUpperBound;
            _maxDelayPerRetransmission = maxDelayPerRetransmission;
 
            _delayLowerBoundMilliseconds = TimeoutHelper.ToMilliseconds(_delayLowerBound);
            _delayUpperBoundMilliseconds = TimeoutHelper.ToMilliseconds(_delayUpperBound);
            _maxDelayMilliseconds = TimeoutHelper.ToMilliseconds(_maxDelayPerRetransmission);
 
            ValidateSettings();
        }
 
        private UdpRetransmissionSettings(UdpRetransmissionSettings other)
            : this(other._maxUnicastRetransmitCount, other._maxMulticastRetransmitCount, other._delayLowerBound, other._delayUpperBound, other._maxDelayPerRetransmission)
        {
        }
 
        [DefaultValue(UdpConstants.Defaults.MaxUnicastRetransmitCount)]
        public int MaxUnicastRetransmitCount
        {
            get
            {
                return _maxUnicastRetransmitCount;
            }
            set
            {
                const int min = 0;
                if (value < min)
                {
                    throw FxTrace.Exception.ArgumentOutOfRange("value", value, string.Format(SRServiceModel.ArgumentOutOfMinRange, min));
                }
                _maxUnicastRetransmitCount = value;
            }
        }
 
        [DefaultValue(UdpConstants.Defaults.MaxMulticastRetransmitCount)]
        public int MaxMulticastRetransmitCount
        {
            get
            {
                return _maxMulticastRetransmitCount;
            }
            set
            {
                const int min = 0;
                if (value < min)
                {
                    throw FxTrace.Exception.ArgumentOutOfRange("value", value, string.Format(SRServiceModel.ArgumentOutOfMinRange, min));
                }
                _maxMulticastRetransmitCount = value;
            }
        }
 
        public TimeSpan DelayLowerBound
        {
            get
            {
                return _delayLowerBound;
            }
            set
            {
                if (value < TimeSpan.Zero)
                {
                    throw FxTrace.Exception.ArgumentOutOfRange("value", value, string.Format(SRServiceModel.ArgumentOutOfMinRange, TimeSpan.Zero));
                }
 
                _delayLowerBound = value;
                _delayLowerBoundMilliseconds = TimeoutHelper.ToMilliseconds(_delayLowerBound);
            }
        }
 
        public TimeSpan DelayUpperBound
        {
            get
            {
                return _delayUpperBound;
            }
            set
            {
                if (value < TimeSpan.Zero)
                {
                    throw FxTrace.Exception.ArgumentOutOfRange("value", value, string.Format(SRServiceModel.ArgumentOutOfMinRange, TimeSpan.Zero));
                }
 
                _delayUpperBound = value;
                _delayUpperBoundMilliseconds = TimeoutHelper.ToMilliseconds(_delayUpperBound);
            }
        }
 
        public TimeSpan MaxDelayPerRetransmission
        {
            get
            {
                return _maxDelayPerRetransmission;
            }
            set
            {
                if (value < TimeSpan.Zero)
                {
                    throw FxTrace.Exception.ArgumentOutOfRange("value", value, string.Format(SRServiceModel.ArgumentOutOfMinRange, TimeSpan.Zero));
                }
 
                _maxDelayPerRetransmission = value;
                _maxDelayMilliseconds = TimeoutHelper.ToMilliseconds(_maxDelayPerRetransmission);
            }
        }
 
        public bool ShouldSerializeDelayLowerBound()
        {
            return !TimeSpansEqual(_delayLowerBound, UdpConstants.Defaults.DelayLowerBoundTimeSpan);
        }
 
        public bool ShouldSerializeDelayUpperBound()
        {
            return !TimeSpansEqual(_delayUpperBound, UdpConstants.Defaults.DelayUpperBoundTimeSpan);
        }
 
        public bool ShouldSerializeMaxDelayPerRetransmission()
        {
            return !TimeSpansEqual(_maxDelayPerRetransmission, UdpConstants.Defaults.MaxDelayPerRetransmissionTimeSpan);
        }
 
 
        //called at send time to avoid repeated rounding and casting
        internal int GetDelayLowerBound()
        {
            return _delayLowerBoundMilliseconds;
        }
 
        //called at send time to avoid repeated rounding and casting
        internal int GetDelayUpperBound()
        {
            return _delayUpperBoundMilliseconds;
        }
 
        //called at send time to avoid repeated rounding and casting
        internal int GetMaxDelayPerRetransmission()
        {
            return _maxDelayMilliseconds;
        }
 
        internal bool Enabled
        {
            get
            {
                return _maxUnicastRetransmitCount > 0 || _maxMulticastRetransmitCount > 0;
            }
        }
 
        internal void ValidateSettings()
        {
            if (_delayLowerBound > _delayUpperBound)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("DelayLowerBound", _delayLowerBound, "TODO: "); // SR.Property1LessThanOrEqualToProperty2("DelayLowerBound", this.delayLowerBound, "DelayUpperBound", this.delayUpperBound));
            }
 
 
            if (_delayUpperBound > _maxDelayPerRetransmission)
            {
                throw FxTrace.Exception.ArgumentOutOfRange("DelayUpperBound", _delayUpperBound, "TODO: "); //  SR.Property1LessThanOrEqualToProperty2("DelayUpperBound", this.delayUpperBound, "MaxDelayPerRetransmission", this.maxDelayPerRetransmission));
            }
        }
 
        internal UdpRetransmissionSettings Clone()
        {
            return new UdpRetransmissionSettings(this);
        }
 
        internal bool IsMatch(UdpRetransmissionSettings udpRetransmissionSettings)
        {
            if (this.DelayLowerBound != udpRetransmissionSettings.DelayLowerBound)
            {
                return false;
            }
 
            if (this.DelayUpperBound != udpRetransmissionSettings.DelayUpperBound)
            {
                return false;
            }
 
            if (this.MaxDelayPerRetransmission != udpRetransmissionSettings.MaxDelayPerRetransmission)
            {
                return false;
            }
 
            if (this.MaxMulticastRetransmitCount != udpRetransmissionSettings.MaxMulticastRetransmitCount)
            {
                return false;
            }
 
            if (this.MaxUnicastRetransmitCount != udpRetransmissionSettings.MaxUnicastRetransmitCount)
            {
                return false;
            }
 
            return true;
        }
 
        private bool TimeSpansEqual(TimeSpan ts1, TimeSpan ts2)
        {
            long diff = Math.Abs(ts1.Ticks - ts2.Ticks);
            long max = Math.Max(Math.Abs(ts1.Ticks), Math.Abs(ts2.Ticks));
            return diff < TimeSpan.FromMilliseconds(1).Ticks || (max > 0 && diff / (double)max < 1e-3);
        }
    }
}