diff --git a/crypto/BouncyCastle.Android.csproj b/crypto/BouncyCastle.Android.csproj
index 08d105ada..7bec5daa9 100644
--- a/crypto/BouncyCastle.Android.csproj
+++ b/crypto/BouncyCastle.Android.csproj
@@ -1152,6 +1152,7 @@
<Compile Include="src\crypto\tls\Ssl3Mac.cs" />
<Compile Include="src\crypto\tls\SupplementalDataEntry.cs" />
<Compile Include="src\crypto\tls\SupplementalDataType.cs" />
+ <Compile Include="src\crypto\tls\Timeout.cs" />
<Compile Include="src\crypto\tls\TlsAeadCipher.cs" />
<Compile Include="src\crypto\tls\TlsAgreementCredentials.cs" />
<Compile Include="src\crypto\tls\TlsAuthentication.cs" />
diff --git a/crypto/BouncyCastle.csproj b/crypto/BouncyCastle.csproj
index 95a38e29b..27a473d43 100644
--- a/crypto/BouncyCastle.csproj
+++ b/crypto/BouncyCastle.csproj
@@ -1146,6 +1146,7 @@
<Compile Include="src\crypto\tls\Ssl3Mac.cs" />
<Compile Include="src\crypto\tls\SupplementalDataEntry.cs" />
<Compile Include="src\crypto\tls\SupplementalDataType.cs" />
+ <Compile Include="src\crypto\tls\Timeout.cs" />
<Compile Include="src\crypto\tls\TlsAeadCipher.cs" />
<Compile Include="src\crypto\tls\TlsAgreementCredentials.cs" />
<Compile Include="src\crypto\tls\TlsAuthentication.cs" />
diff --git a/crypto/BouncyCastle.iOS.csproj b/crypto/BouncyCastle.iOS.csproj
index 83f03b4ce..15b72d4a9 100644
--- a/crypto/BouncyCastle.iOS.csproj
+++ b/crypto/BouncyCastle.iOS.csproj
@@ -1147,6 +1147,7 @@
<Compile Include="src\crypto\tls\Ssl3Mac.cs" />
<Compile Include="src\crypto\tls\SupplementalDataEntry.cs" />
<Compile Include="src\crypto\tls\SupplementalDataType.cs" />
+ <Compile Include="src\crypto\tls\Timeout.cs" />
<Compile Include="src\crypto\tls\TlsAeadCipher.cs" />
<Compile Include="src\crypto\tls\TlsAgreementCredentials.cs" />
<Compile Include="src\crypto\tls\TlsAuthentication.cs" />
diff --git a/crypto/crypto.csproj b/crypto/crypto.csproj
index c40c55117..29e9cb718 100644
--- a/crypto/crypto.csproj
+++ b/crypto/crypto.csproj
@@ -5619,6 +5619,11 @@
BuildAction = "Compile"
/>
<File
+ RelPath = "src\crypto\tls\Timeout.cs"
+ SubType = "Code"
+ BuildAction = "Compile"
+ />
+ <File
RelPath = "src\crypto\tls\TlsAeadCipher.cs"
SubType = "Code"
BuildAction = "Compile"
diff --git a/crypto/src/crypto/tls/Timeout.cs b/crypto/src/crypto/tls/Timeout.cs
new file mode 100644
index 000000000..924073c4f
--- /dev/null
+++ b/crypto/src/crypto/tls/Timeout.cs
@@ -0,0 +1,121 @@
+using System;
+
+using Org.BouncyCastle.Utilities.Date;
+
+namespace Org.BouncyCastle.Crypto.Tls
+{
+ internal class Timeout
+ {
+ private long durationMillis;
+ private long startMillis;
+
+ internal Timeout(long durationMillis)
+ : this(durationMillis, DateTimeUtilities.CurrentUnixMs())
+ {
+ }
+
+ internal Timeout(long durationMillis, long currentTimeMillis)
+ {
+ this.durationMillis = System.Math.Max(0, durationMillis);
+ this.startMillis = System.Math.Max(0, currentTimeMillis);
+ }
+
+ //internal long RemainingMillis()
+ //{
+ // return RemainingMillis(DateTimeUtilities.CurrentUnixMs());
+ //}
+
+ internal long RemainingMillis(long currentTimeMillis)
+ {
+ lock (this)
+ {
+ // If clock jumped backwards, reset start time
+ if (startMillis > currentTimeMillis)
+ {
+ startMillis = currentTimeMillis;
+ return durationMillis;
+ }
+
+ long elapsed = currentTimeMillis - startMillis;
+ long remaining = durationMillis - elapsed;
+
+ // Once timeout reached, lock it in
+ if (remaining <= 0)
+ {
+ return durationMillis = 0L;
+ }
+
+ return remaining;
+ }
+ }
+
+ //internal static int ConstrainWaitMillis(int waitMillis, Timeout timeout)
+ //{
+ // return ConstrainWaitMillis(waitMillis, timeout, DateTimeUtilities.CurrentUnixMs());
+ //}
+
+ internal static int ConstrainWaitMillis(int waitMillis, Timeout timeout, long currentTimeMillis)
+ {
+ if (waitMillis < 0)
+ return -1;
+
+ int timeoutMillis = GetWaitMillis(timeout, currentTimeMillis);
+ if (timeoutMillis < 0)
+ return -1;
+
+ if (waitMillis == 0)
+ return timeoutMillis;
+
+ if (timeoutMillis == 0)
+ return waitMillis;
+
+ return System.Math.Min(waitMillis, timeoutMillis);
+ }
+
+ internal static Timeout ForWaitMillis(int waitMillis)
+ {
+ return ForWaitMillis(waitMillis, DateTimeUtilities.CurrentUnixMs());
+ }
+
+ internal static Timeout ForWaitMillis(int waitMillis, long currentTimeMillis)
+ {
+ if (waitMillis < 0)
+ throw new ArgumentException("cannot be negative", "waitMillis");
+
+ if (waitMillis > 0)
+ return new Timeout(waitMillis, currentTimeMillis);
+
+ return null;
+ }
+
+ //internal static int GetWaitMillis(Timeout timeout)
+ //{
+ // return GetWaitMillis(timeout, DateTimeUtilities.CurrentUnixMs());
+ //}
+
+ internal static int GetWaitMillis(Timeout timeout, long currentTimeMillis)
+ {
+ if (null == timeout)
+ return 0;
+
+ long remainingMillis = timeout.RemainingMillis(currentTimeMillis);
+ if (remainingMillis < 1L)
+ return -1;
+
+ if (remainingMillis > int.MaxValue)
+ return int.MaxValue;
+
+ return (int)remainingMillis;
+ }
+
+ //internal static bool HasExpired(Timeout timeout)
+ //{
+ // return HasExpired(timeout, DateTimeUtilities.CurrentUnixMs());
+ //}
+
+ internal static bool HasExpired(Timeout timeout, long currentTimeMillis)
+ {
+ return null != timeout && timeout.RemainingMillis(currentTimeMillis) < 1L;
+ }
+ }
+}
|