blob: 56f43bf65baa0faf9b73564fedefb31061915101 [file] [log] [blame]
Dmitri Shuralyov5d997792016-11-07 15:05:57 -08001// Copyright 2013 The Go Authors. All rights reserved.
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +10002// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5// Package netutil provides network utility functions, complementing the more
6// common ones in the net package.
David Symonds8aa6e202014-12-09 14:17:11 +11007package netutil // import "golang.org/x/net/netutil"
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +10008
Andrew Gerrandee2e27e2013-08-15 13:52:04 +10009import (
10 "net"
11 "sync"
12)
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100013
14// LimitListener returns a Listener that accepts at most n simultaneous
15// connections from the provided Listener.
16func LimitListener(l net.Listener, n int) net.Listener {
Brad Fitzpatricka4798762014-05-22 11:59:35 -070017 return &limitListener{l, make(chan struct{}, n)}
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100018}
19
20type limitListener struct {
21 net.Listener
Brad Fitzpatricka4798762014-05-22 11:59:35 -070022 sem chan struct{}
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100023}
24
Brad Fitzpatricka4798762014-05-22 11:59:35 -070025func (l *limitListener) acquire() { l.sem <- struct{}{} }
26func (l *limitListener) release() { <-l.sem }
27
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100028func (l *limitListener) Accept() (net.Conn, error) {
Brad Fitzpatricka4798762014-05-22 11:59:35 -070029 l.acquire()
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100030 c, err := l.Listener.Accept()
31 if err != nil {
Brad Fitzpatricka4798762014-05-22 11:59:35 -070032 l.release()
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100033 return nil, err
34 }
Brad Fitzpatricka4798762014-05-22 11:59:35 -070035 return &limitListenerConn{Conn: c, release: l.release}, nil
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100036}
37
38type limitListenerConn struct {
39 net.Conn
Brad Fitzpatricka4798762014-05-22 11:59:35 -070040 releaseOnce sync.Once
41 release func()
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100042}
43
44func (l *limitListenerConn) Close() error {
45 err := l.Conn.Close()
Brad Fitzpatricka4798762014-05-22 11:59:35 -070046 l.releaseOnce.Do(l.release)
Andrew Gerrandbeab8eb2013-08-14 11:00:04 +100047 return err
48}