summary refs log tree commit diff
path: root/crypto/src/tls/Timeout.cs
blob: e47fc5d9a830e3a16c53d295d71dd8102d6fe4ca (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using System;

using Org.BouncyCastle.Utilities.Date;

namespace Org.BouncyCastle.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;
        }
    }
}