@@ -10,6 +10,7 @@ const (
1010 defaultHandshakeTimeout = 100 * time .Millisecond
1111 defaultResendTimeout = 100 * time .Millisecond
1212 finSendTimeout = 1000 * time .Millisecond
13+ defaultResendMultiplier = 5
1314 DefaultSendTimeout = math .MaxInt64
1415 DefaultRecvTimeout = math .MaxInt64
1516)
@@ -19,6 +20,10 @@ type TimeoutManager struct {
1920 // by the server or the client.
2021 isServer bool
2122
23+ // useStaticTimeout is used to indicate whether the resendTimeout
24+ // has been manually set, and if so, should not be updated dynamically.
25+ useStaticTimeout bool
26+
2227 // resendTimeout defines the current resend timeout used by the
2328 // timeout manager.
2429 // The resend timeout is the duration that will be waited before
@@ -29,6 +34,12 @@ type TimeoutManager struct {
2934 resendTimeout time.Duration
3035 resendTimeoutMu sync.RWMutex
3136
37+ // resendMultiplier defines the multiplier used when multiplying the
38+ // duration it took for the other party to respond when setting the
39+ // resendTimeout dynamically during the handshake.
40+ resendMultiplier int
41+ resendMultiplierMu sync.RWMutex
42+
3243 // latestSentSYNTime is used to keep track of the time when the latest
3344 // SYN message was sent. This is used to dynamically set the resend
3445 // timeout, based on how long it took for the other party to respond to
@@ -62,11 +73,74 @@ func NewTimeOutManager(isServer bool) *TimeoutManager {
6273 isServer : isServer ,
6374 resendTimeout : defaultResendTimeout ,
6475 handshakeTimeout : defaultHandshakeTimeout ,
76+ useStaticTimeout : false ,
77+ resendMultiplier : defaultResendMultiplier ,
6578 recvTimeout : DefaultRecvTimeout ,
6679 sendTimeout : DefaultSendTimeout ,
6780 }
6881}
6982
83+ // Sent is should be called when a message is sent by the connection.
84+ func (m * TimeoutManager ) Sent (msg Message ) {
85+ // TODO: In the future, we may want to use this to keep track of the
86+ // time it took for the other party to respond to other types of
87+ // messages than the handshake, and dynamically keep updating the resend
88+ // timeout to ensure that it reflects the current response time.
89+ switch msg .(type ) { // nolint:gocritic
90+ case * PacketSYN :
91+ // Note that we may send multiple SYN messages before receiving
92+ // a response. Therefore, this field might be updated multiple
93+ // times.
94+ m .latestSentSYNTime = time .Now ()
95+ }
96+ }
97+
98+ // Received is should be called when a message is received by the connection.
99+ func (m * TimeoutManager ) Received (msg Message ) {
100+ // TODO: In the future, we may want to use this to keep track of the
101+ // time it took for the other party to respond to other types of
102+ // messages than the handshake, and dynamically keep updating the resend
103+ // timeout to ensure that it reflects the current response time.
104+ switch msg .(type ) {
105+ case * PacketSYN :
106+ if ! m .isServer {
107+ m .updateResendTimeout (time .Since (m .latestSentSYNTime ))
108+ }
109+
110+ case * PacketSYNACK :
111+ if m .isServer {
112+ m .updateResendTimeout (time .Since (m .latestSentSYNTime ))
113+ }
114+ }
115+ }
116+
117+ // updateResendTimeout updates the resend timeout based on the given response
118+ // time. The resend timeout will be only be updated if the given response time
119+ // is greater than the default resend timeout, after being multiplied by the
120+ // resendMultiplier.
121+ // If a static timeout has been manually set, then this function will do be a
122+ // no-op.
123+ func (m * TimeoutManager ) updateResendTimeout (responseTime time.Duration ) {
124+ if m .useStaticTimeout {
125+ log .Tracef ("Not increasing resendTimeout as it has been set " +
126+ "manually" )
127+
128+ return
129+ }
130+
131+ multipliedTimeout := time .Duration (m .resendMultiplier ) * responseTime
132+
133+ if multipliedTimeout > defaultResendTimeout {
134+ log .Tracef ("Updating resendTimeout to %v" , multipliedTimeout )
135+
136+ m .resendTimeout = multipliedTimeout
137+ } else {
138+ log .Tracef ("Not updating resendTimeout to %v as it is not " +
139+ "greater than the minimum resendTimeout which is %v" ,
140+ multipliedTimeout , m .resendTimeout )
141+ }
142+ }
143+
70144// GetResendTimeout returns the current resend timeout.
71145func (m * TimeoutManager ) GetResendTimeout () time.Duration {
72146 m .resendTimeoutMu .RLock ()
@@ -107,14 +181,24 @@ func (m *TimeoutManager) GetRecvTimeout() time.Duration {
107181 return m .recvTimeout
108182}
109183
110- // SetResendTimeout sets the resend timeout to the given value, and also
184+ // SetStaticResendTimeout sets the resend timeout to the given value, and also
111185// marks the timeout manager as using a static resend timeout, which will mean
112186// that the resend timeout will not be updated dynamically.
113- func (m * TimeoutManager ) SetResendTimeout (resendTimeout time.Duration ) {
187+ func (m * TimeoutManager ) SetStaticResendTimeout (resendTimeout time.Duration ) {
114188 m .resendTimeoutMu .Lock ()
115189 defer m .resendTimeoutMu .Unlock ()
116190
117191 m .resendTimeout = resendTimeout
192+ m .useStaticTimeout = true
193+ }
194+
195+ // SetResendMultiplier sets the resend multiplier used when dynamically
196+ // setting the resend timeout.
197+ func (m * TimeoutManager ) SetResendMultiplier (resendMultiplier int ) {
198+ m .resendMultiplierMu .Lock ()
199+ defer m .resendMultiplierMu .Unlock ()
200+
201+ m .resendMultiplier = resendMultiplier
118202}
119203
120204// SetHandshakeTimeout sets the handshake timeout.
0 commit comments