mirror of
https://github.com/ergochat/ergo.git
synced 2024-12-25 20:22:38 +01:00
make ReloadableListener lock-free
Also stop attaching the *tls.Config to the wrapped connection, since this forces it to be retained beyond its natural lifetime.
This commit is contained in:
parent
bceae9b739
commit
3ceff6a8b1
@ -295,7 +295,7 @@ func (server *Server) RunClient(conn IRCConn) {
|
||||
var banMsg string
|
||||
realIP := utils.AddrToIP(wConn.RemoteAddr())
|
||||
var proxiedIP net.IP
|
||||
if wConn.Config.Tor {
|
||||
if wConn.Tor {
|
||||
// cover up details of the tor proxying infrastructure (not a user privacy concern,
|
||||
// but a hardening measure):
|
||||
proxiedIP = utils.IPv4LoopbackAddress
|
||||
@ -329,7 +329,7 @@ func (server *Server) RunClient(conn IRCConn) {
|
||||
lastActive: now,
|
||||
channels: make(ChannelSet),
|
||||
ctime: now,
|
||||
isSTSOnly: wConn.Config.STSOnly,
|
||||
isSTSOnly: wConn.STSOnly,
|
||||
languages: server.Languages().Default(),
|
||||
loginThrottle: connection_limits.GenericThrottle{
|
||||
Duration: config.Accounts.LoginThrottling.Duration,
|
||||
@ -358,8 +358,8 @@ func (server *Server) RunClient(conn IRCConn) {
|
||||
lastActive: now,
|
||||
realIP: realIP,
|
||||
proxiedIP: proxiedIP,
|
||||
isTor: wConn.Config.Tor,
|
||||
hideSTS: wConn.Config.Tor || wConn.Config.HideSTS,
|
||||
isTor: wConn.Tor,
|
||||
hideSTS: wConn.Tor || wConn.HideSTS,
|
||||
}
|
||||
client.sessions = []*Session{session}
|
||||
|
||||
@ -369,7 +369,7 @@ func (server *Server) RunClient(conn IRCConn) {
|
||||
client.SetMode(modes.TLS, true)
|
||||
}
|
||||
|
||||
if wConn.Config.TLSConfig != nil {
|
||||
if wConn.TLS {
|
||||
// error is not useful to us here anyways so we can ignore it
|
||||
session.certfp, session.peerCerts, _ = utils.GetCertFP(wConn.Conn, RegisterTimeout)
|
||||
}
|
||||
|
@ -204,10 +204,10 @@ func confirmProxyData(conn *utils.WrappedConn, remoteAddr, xForwardedFor, xForwa
|
||||
}
|
||||
}
|
||||
|
||||
if conn.Config.TLSConfig != nil || conn.Config.Tor {
|
||||
if conn.TLS || conn.Tor {
|
||||
// we terminated our own encryption:
|
||||
conn.Secure = true
|
||||
} else if !conn.Config.WebSocket {
|
||||
} else if !conn.WebSocket {
|
||||
// plaintext normal connection: loopback and secureNets are secure
|
||||
realIP := utils.AddrToIP(conn.RemoteAddr())
|
||||
conn.Secure = realIP.IsLoopback() || utils.IPInNets(realIP, config.Server.secureNets)
|
||||
|
@ -9,7 +9,7 @@ import (
|
||||
"io"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
)
|
||||
|
||||
@ -209,7 +209,11 @@ func parseProxyLineV2(line []byte) (ip net.IP, err error) {
|
||||
type WrappedConn struct {
|
||||
net.Conn
|
||||
ProxiedIP net.IP
|
||||
Config ListenerConfig
|
||||
TLS bool
|
||||
Tor bool
|
||||
STSOnly bool
|
||||
WebSocket bool
|
||||
HideSTS bool
|
||||
// Secure indicates whether we believe the connection between us and the client
|
||||
// was secure against interception and modification (including all proxies):
|
||||
Secure bool
|
||||
@ -218,35 +222,30 @@ type WrappedConn struct {
|
||||
// ReloadableListener is a wrapper for net.Listener that allows reloading
|
||||
// of config data for postprocessing connections (TLS, PROXY protocol, etc.)
|
||||
type ReloadableListener struct {
|
||||
// TODO: make this lock-free
|
||||
sync.Mutex
|
||||
realListener net.Listener
|
||||
config ListenerConfig
|
||||
isClosed bool
|
||||
// nil means the listener is closed:
|
||||
config atomic.Pointer[ListenerConfig]
|
||||
}
|
||||
|
||||
func NewReloadableListener(realListener net.Listener, config ListenerConfig) *ReloadableListener {
|
||||
return &ReloadableListener{
|
||||
result := &ReloadableListener{
|
||||
realListener: realListener,
|
||||
config: config,
|
||||
}
|
||||
result.config.Store(&config) // heap escape
|
||||
return result
|
||||
}
|
||||
|
||||
func (rl *ReloadableListener) Reload(config ListenerConfig) {
|
||||
rl.Lock()
|
||||
rl.config = config
|
||||
rl.Unlock()
|
||||
rl.config.Store(&config)
|
||||
}
|
||||
|
||||
func (rl *ReloadableListener) Accept() (conn net.Conn, err error) {
|
||||
conn, err = rl.realListener.Accept()
|
||||
|
||||
rl.Lock()
|
||||
config := rl.config
|
||||
isClosed := rl.isClosed
|
||||
rl.Unlock()
|
||||
config := rl.config.Load()
|
||||
|
||||
if isClosed {
|
||||
if config == nil {
|
||||
// Close() was called
|
||||
if err == nil {
|
||||
conn.Close()
|
||||
}
|
||||
@ -279,14 +278,17 @@ func (rl *ReloadableListener) Accept() (conn net.Conn, err error) {
|
||||
return &WrappedConn{
|
||||
Conn: conn,
|
||||
ProxiedIP: proxiedIP,
|
||||
Config: config,
|
||||
TLS: config.TLSConfig != nil,
|
||||
Tor: config.Tor,
|
||||
STSOnly: config.STSOnly,
|
||||
WebSocket: config.WebSocket,
|
||||
HideSTS: config.HideSTS,
|
||||
// Secure will be set later by client code
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (rl *ReloadableListener) Close() error {
|
||||
rl.Lock()
|
||||
rl.isClosed = true
|
||||
rl.Unlock()
|
||||
rl.config.Store(nil)
|
||||
|
||||
return rl.realListener.Close()
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user