|
|
@@ -3,6 +3,7 @@ package mtglib
|
|
3
|
3
|
import (
|
|
4
|
4
|
"bytes"
|
|
5
|
5
|
"context"
|
|
|
6
|
+ "errors"
|
|
6
|
7
|
"fmt"
|
|
7
|
8
|
"io"
|
|
8
|
9
|
"net"
|
|
|
@@ -102,7 +103,7 @@ func newConnProxyProtocol(source, target essentials.Conn) *connProxyProtocol {
|
|
102
|
103
|
// Both directions update the same timestamp so that activity in one direction
|
|
103
|
104
|
// prevents the other (idle) direction from timing out.
|
|
104
|
105
|
type idleTracker struct {
|
|
105
|
|
- lastActive atomic.Int64 // unix nanos
|
|
|
106
|
+ lastActive atomic.Pointer[time.Time]
|
|
106
|
107
|
timeout time.Duration
|
|
107
|
108
|
}
|
|
108
|
109
|
|
|
|
@@ -114,13 +115,12 @@ func newIdleTracker(timeout time.Duration) *idleTracker {
|
|
114
|
115
|
}
|
|
115
|
116
|
|
|
116
|
117
|
func (t *idleTracker) touch() {
|
|
117
|
|
- t.lastActive.Store(time.Now().UnixNano())
|
|
|
118
|
+ stamp := time.Now()
|
|
|
119
|
+ t.lastActive.Store(&stamp)
|
|
118
|
120
|
}
|
|
119
|
121
|
|
|
120
|
122
|
func (t *idleTracker) isIdle() bool {
|
|
121
|
|
- last := time.Unix(0, t.lastActive.Load())
|
|
122
|
|
-
|
|
123
|
|
- return time.Since(last) >= t.timeout
|
|
|
123
|
+ return time.Since(*t.lastActive.Load()) >= t.timeout
|
|
124
|
124
|
}
|
|
125
|
125
|
|
|
126
|
126
|
type connIdleTimeout struct {
|
|
|
@@ -130,25 +130,22 @@ type connIdleTimeout struct {
|
|
130
|
130
|
}
|
|
131
|
131
|
|
|
132
|
132
|
func (c connIdleTimeout) Read(b []byte) (int, error) {
|
|
|
133
|
+ var netErr net.Error
|
|
|
134
|
+
|
|
133
|
135
|
for {
|
|
134
|
136
|
c.SetReadDeadline(time.Now().Add(c.tracker.timeout)) //nolint: errcheck
|
|
135
|
137
|
|
|
136
|
138
|
n, err := c.Conn.Read(b)
|
|
137
|
|
- if n > 0 {
|
|
138
|
|
- c.tracker.touch()
|
|
139
|
|
-
|
|
140
|
|
- return n, err //nolint: wrapcheck
|
|
141
|
|
- }
|
|
142
|
|
-
|
|
143
|
|
- if err != nil {
|
|
144
|
|
- if netErr, ok := err.(net.Error); ok && netErr.Timeout() && !c.tracker.isIdle() { //nolint: errorlint
|
|
145
|
|
- continue
|
|
146
|
|
- }
|
|
147
|
139
|
|
|
148
|
|
- return 0, err //nolint: wrapcheck
|
|
|
140
|
+ switch {
|
|
|
141
|
+ case err == nil:
|
|
|
142
|
+ c.tracker.touch()
|
|
|
143
|
+ return n, nil
|
|
|
144
|
+ case errors.As(err, &netErr) && netErr.Timeout() && !c.tracker.isIdle():
|
|
|
145
|
+ continue
|
|
149
|
146
|
}
|
|
150
|
147
|
|
|
151
|
|
- return 0, nil
|
|
|
148
|
+ return n, err
|
|
152
|
149
|
}
|
|
153
|
150
|
}
|
|
154
|
151
|
|