|
@@ -9,7 +9,7 @@ import (
|
9
|
9
|
"io"
|
10
|
10
|
"net"
|
11
|
11
|
"strings"
|
12
|
|
- "sync"
|
|
12
|
+ "sync/atomic"
|
13
|
13
|
"time"
|
14
|
14
|
)
|
15
|
15
|
|
|
@@ -209,7 +209,11 @@ func parseProxyLineV2(line []byte) (ip net.IP, err error) {
|
209
|
209
|
type WrappedConn struct {
|
210
|
210
|
net.Conn
|
211
|
211
|
ProxiedIP net.IP
|
212
|
|
- Config ListenerConfig
|
|
212
|
+ TLS bool
|
|
213
|
+ Tor bool
|
|
214
|
+ STSOnly bool
|
|
215
|
+ WebSocket bool
|
|
216
|
+ HideSTS bool
|
213
|
217
|
// Secure indicates whether we believe the connection between us and the client
|
214
|
218
|
// was secure against interception and modification (including all proxies):
|
215
|
219
|
Secure bool
|
|
@@ -218,35 +222,30 @@ type WrappedConn struct {
|
218
|
222
|
// ReloadableListener is a wrapper for net.Listener that allows reloading
|
219
|
223
|
// of config data for postprocessing connections (TLS, PROXY protocol, etc.)
|
220
|
224
|
type ReloadableListener struct {
|
221
|
|
- // TODO: make this lock-free
|
222
|
|
- sync.Mutex
|
223
|
225
|
realListener net.Listener
|
224
|
|
- config ListenerConfig
|
225
|
|
- isClosed bool
|
|
226
|
+ // nil means the listener is closed:
|
|
227
|
+ config atomic.Pointer[ListenerConfig]
|
226
|
228
|
}
|
227
|
229
|
|
228
|
230
|
func NewReloadableListener(realListener net.Listener, config ListenerConfig) *ReloadableListener {
|
229
|
|
- return &ReloadableListener{
|
|
231
|
+ result := &ReloadableListener{
|
230
|
232
|
realListener: realListener,
|
231
|
|
- config: config,
|
232
|
233
|
}
|
|
234
|
+ result.config.Store(&config) // heap escape
|
|
235
|
+ return result
|
233
|
236
|
}
|
234
|
237
|
|
235
|
238
|
func (rl *ReloadableListener) Reload(config ListenerConfig) {
|
236
|
|
- rl.Lock()
|
237
|
|
- rl.config = config
|
238
|
|
- rl.Unlock()
|
|
239
|
+ rl.config.Store(&config)
|
239
|
240
|
}
|
240
|
241
|
|
241
|
242
|
func (rl *ReloadableListener) Accept() (conn net.Conn, err error) {
|
242
|
243
|
conn, err = rl.realListener.Accept()
|
243
|
244
|
|
244
|
|
- rl.Lock()
|
245
|
|
- config := rl.config
|
246
|
|
- isClosed := rl.isClosed
|
247
|
|
- rl.Unlock()
|
|
245
|
+ config := rl.config.Load()
|
248
|
246
|
|
249
|
|
- if isClosed {
|
|
247
|
+ if config == nil {
|
|
248
|
+ // Close() was called
|
250
|
249
|
if err == nil {
|
251
|
250
|
conn.Close()
|
252
|
251
|
}
|
|
@@ -279,14 +278,17 @@ func (rl *ReloadableListener) Accept() (conn net.Conn, err error) {
|
279
|
278
|
return &WrappedConn{
|
280
|
279
|
Conn: conn,
|
281
|
280
|
ProxiedIP: proxiedIP,
|
282
|
|
- Config: config,
|
|
281
|
+ TLS: config.TLSConfig != nil,
|
|
282
|
+ Tor: config.Tor,
|
|
283
|
+ STSOnly: config.STSOnly,
|
|
284
|
+ WebSocket: config.WebSocket,
|
|
285
|
+ HideSTS: config.HideSTS,
|
|
286
|
+ // Secure will be set later by client code
|
283
|
287
|
}, nil
|
284
|
288
|
}
|
285
|
289
|
|
286
|
290
|
func (rl *ReloadableListener) Close() error {
|
287
|
|
- rl.Lock()
|
288
|
|
- rl.isClosed = true
|
289
|
|
- rl.Unlock()
|
|
291
|
+ rl.config.Store(nil)
|
290
|
292
|
|
291
|
293
|
return rl.realListener.Close()
|
292
|
294
|
}
|