273 lines
9.5 KiB
C#
273 lines
9.5 KiB
C#
|
//----------------------------------------------------------------
|
||
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||
|
//----------------------------------------------------------------
|
||
|
|
||
|
namespace System.ServiceModel.Channels
|
||
|
{
|
||
|
using System;
|
||
|
using System.ComponentModel;
|
||
|
using System.Globalization;
|
||
|
using System.Runtime;
|
||
|
|
||
|
public sealed class UdpRetransmissionSettings
|
||
|
{
|
||
|
int maxUnicastRetransmitCount;
|
||
|
int maxMulticastRetransmitCount;
|
||
|
TimeSpan delayLowerBound;
|
||
|
TimeSpan delayUpperBound;
|
||
|
TimeSpan maxDelayPerRetransmission;
|
||
|
int delayLowerBoundMilliseconds;
|
||
|
int delayUpperBoundMilliseconds;
|
||
|
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,
|
||
|
SR.ArgumentOutOfMinRange(0));
|
||
|
}
|
||
|
|
||
|
if (maxMulticastRetransmitCount < 0)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("maxMulticastRetransmitCount", maxMulticastRetransmitCount,
|
||
|
SR.ArgumentOutOfMinRange(0));
|
||
|
}
|
||
|
|
||
|
|
||
|
if (delayLowerBound < TimeSpan.Zero)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("delayLowerBound", delayLowerBound, SR.ArgumentOutOfMinRange(TimeSpan.Zero));
|
||
|
}
|
||
|
|
||
|
if (delayUpperBound < TimeSpan.Zero)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("delayUpperBound", delayUpperBound, SR.ArgumentOutOfMinRange(TimeSpan.Zero));
|
||
|
}
|
||
|
|
||
|
if (maxDelayPerRetransmission < TimeSpan.Zero)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("maxDelayPerRetransmission", maxDelayPerRetransmission,
|
||
|
SR.ArgumentOutOfMinRange(TimeSpan.Zero));
|
||
|
}
|
||
|
|
||
|
this.maxUnicastRetransmitCount = maxUnicastRetransmitCount;
|
||
|
this.maxMulticastRetransmitCount = maxMulticastRetransmitCount;
|
||
|
this.delayLowerBound = delayLowerBound;
|
||
|
this.delayUpperBound = delayUpperBound;
|
||
|
this.maxDelayPerRetransmission = maxDelayPerRetransmission;
|
||
|
|
||
|
this.delayLowerBoundMilliseconds = TimeoutHelper.ToMilliseconds(this.delayLowerBound);
|
||
|
this.delayUpperBoundMilliseconds = TimeoutHelper.ToMilliseconds(this.delayUpperBound);
|
||
|
this.maxDelayMilliseconds = TimeoutHelper.ToMilliseconds(this.maxDelayPerRetransmission);
|
||
|
|
||
|
ValidateSettings();
|
||
|
}
|
||
|
|
||
|
UdpRetransmissionSettings(UdpRetransmissionSettings other)
|
||
|
: this(other.maxUnicastRetransmitCount, other.maxMulticastRetransmitCount, other.delayLowerBound, other.delayUpperBound, other.maxDelayPerRetransmission)
|
||
|
{
|
||
|
}
|
||
|
|
||
|
[DefaultValue(UdpConstants.Defaults.MaxUnicastRetransmitCount)]
|
||
|
public int MaxUnicastRetransmitCount
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.maxUnicastRetransmitCount;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
const int min = 0;
|
||
|
if (value < min)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinRange(min));
|
||
|
}
|
||
|
this.maxUnicastRetransmitCount = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
[DefaultValue(UdpConstants.Defaults.MaxMulticastRetransmitCount)]
|
||
|
public int MaxMulticastRetransmitCount
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.maxMulticastRetransmitCount;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
const int min = 0;
|
||
|
if (value < min)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinRange(min));
|
||
|
}
|
||
|
this.maxMulticastRetransmitCount = value;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public TimeSpan DelayLowerBound
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.delayLowerBound;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
if (value < TimeSpan.Zero)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinRange(TimeSpan.Zero));
|
||
|
}
|
||
|
|
||
|
this.delayLowerBound = value;
|
||
|
this.delayLowerBoundMilliseconds = TimeoutHelper.ToMilliseconds(this.delayLowerBound);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public TimeSpan DelayUpperBound
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.delayUpperBound;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
if (value < TimeSpan.Zero)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinRange(TimeSpan.Zero));
|
||
|
}
|
||
|
|
||
|
this.delayUpperBound = value;
|
||
|
this.delayUpperBoundMilliseconds = TimeoutHelper.ToMilliseconds(this.delayUpperBound);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public TimeSpan MaxDelayPerRetransmission
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.maxDelayPerRetransmission;
|
||
|
}
|
||
|
set
|
||
|
{
|
||
|
if (value < TimeSpan.Zero)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("value", value, SR.ArgumentOutOfMinRange(TimeSpan.Zero));
|
||
|
}
|
||
|
|
||
|
this.maxDelayPerRetransmission = value;
|
||
|
this.maxDelayMilliseconds = TimeoutHelper.ToMilliseconds(this.maxDelayPerRetransmission);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
public bool ShouldSerializeDelayLowerBound()
|
||
|
{
|
||
|
return !TimeSpansEqual(this.delayLowerBound, UdpConstants.Defaults.DelayLowerBoundTimeSpan);
|
||
|
}
|
||
|
|
||
|
public bool ShouldSerializeDelayUpperBound()
|
||
|
{
|
||
|
return !TimeSpansEqual(this.delayUpperBound, UdpConstants.Defaults.DelayUpperBoundTimeSpan);
|
||
|
}
|
||
|
|
||
|
public bool ShouldSerializeMaxDelayPerRetransmission()
|
||
|
{
|
||
|
return !TimeSpansEqual(this.maxDelayPerRetransmission, UdpConstants.Defaults.MaxDelayPerRetransmissionTimeSpan);
|
||
|
}
|
||
|
|
||
|
|
||
|
//called at send time to avoid repeated rounding and casting
|
||
|
internal int GetDelayLowerBound()
|
||
|
{
|
||
|
return this.delayLowerBoundMilliseconds;
|
||
|
}
|
||
|
|
||
|
//called at send time to avoid repeated rounding and casting
|
||
|
internal int GetDelayUpperBound()
|
||
|
{
|
||
|
return this.delayUpperBoundMilliseconds;
|
||
|
}
|
||
|
|
||
|
//called at send time to avoid repeated rounding and casting
|
||
|
internal int GetMaxDelayPerRetransmission()
|
||
|
{
|
||
|
return this.maxDelayMilliseconds;
|
||
|
}
|
||
|
|
||
|
internal bool Enabled
|
||
|
{
|
||
|
get
|
||
|
{
|
||
|
return this.maxUnicastRetransmitCount > 0 || this.maxMulticastRetransmitCount > 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
internal void ValidateSettings()
|
||
|
{
|
||
|
if (this.delayLowerBound > this.delayUpperBound)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("DelayLowerBound", this.delayLowerBound, SR.Property1LessThanOrEqualToProperty2("DelayLowerBound", this.delayLowerBound, "DelayUpperBound", this.delayUpperBound));
|
||
|
}
|
||
|
|
||
|
|
||
|
if (this.delayUpperBound > this.maxDelayPerRetransmission)
|
||
|
{
|
||
|
throw FxTrace.Exception.ArgumentOutOfRange("DelayUpperBound", this.delayUpperBound, 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;
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
}
|
||
|
}
|
||
|
}
|