github.com/damirazo/docker@v1.9.0/pkg/listenbuffer/buffer.go (about)

     1  /*
     2  Package listenbuffer uses the kernel's listening backlog functionality to queue
     3  connections, allowing applications to start listening immediately and handle
     4  connections later. This is signaled by closing the activation channel passed to
     5  the constructor.
     6  
     7  The maximum amount of queued connections depends on the configuration of your
     8  kernel (typically called SOMAXXCON) and cannot be configured in Go with the
     9  net package. See `src/net/sock_platform.go` in the Go tree or consult your
    10  kernel's manual.
    11  
    12  	activator := make(chan struct{})
    13  	buffer, err := NewListenBuffer("tcp", "localhost:4000", activator)
    14  	if err != nil {
    15  		panic(err)
    16  	}
    17  
    18  	// will block until activator has been closed or is sent an event
    19  	client, err := buffer.Accept()
    20  
    21  Somewhere else in your application once it's been booted:
    22  
    23  	close(activator)
    24  
    25  `buffer.Accept()` will return the first client in the kernel listening queue, or
    26  continue to block until a client connects or an error occurs.
    27  */
    28  package listenbuffer
    29  
    30  import "net"
    31  
    32  // NewListenBuffer returns a net.Listener listening on addr with the protocol
    33  // passed. The channel passed is used to activate the listenbuffer when the
    34  // caller is ready to accept connections.
    35  func NewListenBuffer(proto, addr string, activate <-chan struct{}) (net.Listener, error) {
    36  	wrapped, err := net.Listen(proto, addr)
    37  	if err != nil {
    38  		return nil, err
    39  	}
    40  
    41  	return &defaultListener{
    42  		wrapped:  wrapped,
    43  		activate: activate,
    44  	}, nil
    45  }
    46  
    47  // defaultListener is the buffered wrapper around the net.Listener
    48  type defaultListener struct {
    49  	wrapped  net.Listener    // The net.Listener wrapped by listenbuffer
    50  	ready    bool            // Whether the listenbuffer has been activated
    51  	activate <-chan struct{} // Channel to control activation of the listenbuffer
    52  }
    53  
    54  // Close closes the wrapped socket.
    55  func (l *defaultListener) Close() error {
    56  	return l.wrapped.Close()
    57  }
    58  
    59  // Addr returns the listening address of the wrapped socket.
    60  func (l *defaultListener) Addr() net.Addr {
    61  	return l.wrapped.Addr()
    62  }
    63  
    64  // Accept returns a client connection on the wrapped socket if the listen buffer
    65  // has been activated. To active the listenbuffer the activation channel passed
    66  // to NewListenBuffer must have been closed or sent an event.
    67  func (l *defaultListener) Accept() (net.Conn, error) {
    68  	// if the listen has been told it is ready then we can go ahead and
    69  	// start returning connections
    70  	if l.ready {
    71  		return l.wrapped.Accept()
    72  	}
    73  	<-l.activate
    74  	l.ready = true
    75  	return l.Accept()
    76  }