minio/pkg/minhttp/listen.go
2016-02-11 15:43:36 -08:00

70 lines
1.7 KiB
Go

/*
* Minio Cloud Storage, (C) 2015 Minio, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package minhttp
import (
"net"
"os"
"sync"
)
// rateLimitedListener returns a Listener that accepts at most n simultaneous
// connections from the provided Listener.
func rateLimitedListener(l net.Listener, nconn int) net.Listener {
if nconn > 0 {
return &rateLimitListener{l, make(chan struct{}, nconn)}
}
return l
}
type rateLimitListener struct {
net.Listener
sem chan struct{}
}
func (l *rateLimitListener) accept() { l.sem <- struct{}{} }
func (l *rateLimitListener) release() { <-l.sem }
// File - necessary to expose underlying socket fd
func (l *rateLimitListener) File() (f *os.File, err error) {
return l.Listener.(fileListener).File()
}
// Accept - accept method for accepting new connections
func (l *rateLimitListener) Accept() (net.Conn, error) {
l.accept()
c, err := l.Listener.Accept()
if err != nil {
l.release()
return nil, err
}
return &rateLimitListenerConn{Conn: c, release: l.release}, nil
}
type rateLimitListenerConn struct {
net.Conn
releaseOnce sync.Once
release func()
}
func (l *rateLimitListenerConn) Close() error {
err := l.Conn.Close()
l.releaseOnce.Do(l.release)
return err
}