mirror of
https://github.com/minio/minio.git
synced 2025-01-11 23:13:23 -05:00
Rewrite connection muxer peek process to avoid server blocking by silent clients (#3187)
This commit is contained in:
parent
754c0770d6
commit
5ff30777e1
@ -134,11 +134,52 @@ func (c *ConnMux) Close() (err error) {
|
||||
type ListenerMux struct {
|
||||
net.Listener
|
||||
config *tls.Config
|
||||
// acceptResCh is a channel for transporting wrapped net.Conn (regular or tls)
|
||||
// after peeking the content of the latter
|
||||
acceptResCh chan ListenerMuxAcceptRes
|
||||
// Cond is used to signal Close when there are no references to the listener.
|
||||
cond *sync.Cond
|
||||
refs int
|
||||
}
|
||||
|
||||
// ListenerMuxAcceptRes contains then final net.Conn data (wrapper by tls or not) to be sent to the http handler
|
||||
type ListenerMuxAcceptRes struct {
|
||||
conn net.Conn
|
||||
err error
|
||||
}
|
||||
|
||||
// newListenerMux listens and wraps accepted connections with tls after protocol peeking
|
||||
func newListenerMux(listener net.Listener, config *tls.Config) *ListenerMux {
|
||||
l := ListenerMux{
|
||||
Listener: listener,
|
||||
config: config,
|
||||
cond: sync.NewCond(&sync.Mutex{}),
|
||||
acceptResCh: make(chan ListenerMuxAcceptRes),
|
||||
}
|
||||
// Start listening, wrap connections with tls when needed
|
||||
go func() {
|
||||
// Loop for accepting new connections
|
||||
for {
|
||||
conn, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
l.acceptResCh <- ListenerMuxAcceptRes{err: err}
|
||||
return
|
||||
}
|
||||
// Wrap the connection with ConnMux to be able to peek the data in the incoming connection
|
||||
// and decide if we need to wrap the connection itself with a TLS or not
|
||||
go func(conn net.Conn) {
|
||||
connMux := NewConnMux(conn)
|
||||
if connMux.PeekProtocol() == "tls" {
|
||||
l.acceptResCh <- ListenerMuxAcceptRes{conn: tls.Server(connMux, l.config)}
|
||||
} else {
|
||||
l.acceptResCh <- ListenerMuxAcceptRes{conn: connMux}
|
||||
}
|
||||
}(conn)
|
||||
}
|
||||
}()
|
||||
return &l
|
||||
}
|
||||
|
||||
// IsClosed - Returns if the underlying listener is closed fully.
|
||||
func (l *ListenerMux) IsClosed() bool {
|
||||
l.cond.L.Lock()
|
||||
@ -187,16 +228,8 @@ func (l *ListenerMux) Accept() (net.Conn, error) {
|
||||
l.incRef()
|
||||
defer l.decRef()
|
||||
|
||||
conn, err := l.Listener.Accept()
|
||||
if err != nil {
|
||||
return conn, err
|
||||
}
|
||||
connMux := NewConnMux(conn)
|
||||
protocol := connMux.PeekProtocol()
|
||||
if protocol == "tls" {
|
||||
return tls.Server(connMux, l.config), nil
|
||||
}
|
||||
return connMux, nil
|
||||
res := <-l.acceptResCh
|
||||
return res.conn, res.err
|
||||
}
|
||||
|
||||
// ServerMux - the main mux server
|
||||
@ -247,11 +280,7 @@ func initListeners(serverAddr string, tls *tls.Config) ([]*ListenerMux, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listeners = append(listeners, &ListenerMux{
|
||||
Listener: listener,
|
||||
config: tls,
|
||||
cond: sync.NewCond(&sync.Mutex{}),
|
||||
})
|
||||
listeners = append(listeners, newListenerMux(listener, tls))
|
||||
return listeners, nil
|
||||
}
|
||||
var addrs []string
|
||||
@ -272,11 +301,7 @@ func initListeners(serverAddr string, tls *tls.Config) ([]*ListenerMux, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
listeners = append(listeners, &ListenerMux{
|
||||
Listener: listener,
|
||||
config: tls,
|
||||
cond: sync.NewCond(&sync.Mutex{}),
|
||||
})
|
||||
listeners = append(listeners, newListenerMux(listener, tls))
|
||||
}
|
||||
return listeners, nil
|
||||
}
|
||||
|
@ -59,11 +59,8 @@ func runTest(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
ln = &ListenerMux{
|
||||
Listener: ln,
|
||||
config: &tls.Config{},
|
||||
cond: sync.NewCond(&sync.Mutex{}),
|
||||
}
|
||||
|
||||
ln = newListenerMux(ln, &tls.Config{})
|
||||
|
||||
addr := ln.Addr().String()
|
||||
waitForListener := make(chan error)
|
||||
|
Loading…
Reference in New Issue
Block a user