|
@@ -1,13 +1,37 @@
|
|
/*
|
|
/*
|
|
- Package to allow go applications to immediately start
|
|
|
|
- listening on a socket, unix, tcp, udp but hold connections
|
|
|
|
- until the application has booted and is ready to accept them
|
|
|
|
|
|
+listenbuffer uses the kernel's listening backlog functionality to queue
|
|
|
|
+connections, allowing applications to start listening immediately and handle
|
|
|
|
+connections later. This is signaled by closing the activation channel passed to
|
|
|
|
+the constructor.
|
|
|
|
+
|
|
|
|
+The maximum amount of queued connections depends on the configuration of your
|
|
|
|
+kernel (typically called SOMAXXCON) and cannot be configured in Go with the
|
|
|
|
+net package. See `src/net/sock_platform.go` in the Go tree or consult your
|
|
|
|
+kernel's manual.
|
|
|
|
+
|
|
|
|
+ activator := make(chan struct{})
|
|
|
|
+ buffer, err := NewListenBuffer("tcp", "localhost:4000", activator)
|
|
|
|
+ if err != nil {
|
|
|
|
+ panic(err)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // will block until activator has been closed or is sent an event
|
|
|
|
+ client, err := buffer.Accept()
|
|
|
|
+
|
|
|
|
+Somewhere else in your application once it's been booted:
|
|
|
|
+
|
|
|
|
+ close(activator)
|
|
|
|
+
|
|
|
|
+`buffer.Accept()` will return the first client in the kernel listening queue, or
|
|
|
|
+continue to block until a client connects or an error occurs.
|
|
*/
|
|
*/
|
|
package listenbuffer
|
|
package listenbuffer
|
|
|
|
|
|
import "net"
|
|
import "net"
|
|
|
|
|
|
-// NewListenBuffer returns a listener listening on addr with the protocol.
|
|
|
|
|
|
+// NewListenBuffer returns a net.Listener listening on addr with the protocol
|
|
|
|
+// passed. The channel passed is used to activate the listenbuffer when the
|
|
|
|
+// caller is ready to accept connections.
|
|
func NewListenBuffer(proto, addr string, activate chan struct{}) (net.Listener, error) {
|
|
func NewListenBuffer(proto, addr string, activate chan struct{}) (net.Listener, error) {
|
|
wrapped, err := net.Listen(proto, addr)
|
|
wrapped, err := net.Listen(proto, addr)
|
|
if err != nil {
|
|
if err != nil {
|
|
@@ -20,20 +44,26 @@ func NewListenBuffer(proto, addr string, activate chan struct{}) (net.Listener,
|
|
}, nil
|
|
}, nil
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// defaultListener is the buffered wrapper around the net.Listener
|
|
type defaultListener struct {
|
|
type defaultListener struct {
|
|
- wrapped net.Listener // the real listener to wrap
|
|
|
|
- ready bool // is the listner ready to start accpeting connections
|
|
|
|
- activate chan struct{}
|
|
|
|
|
|
+ wrapped net.Listener // The net.Listener wrapped by listenbuffer
|
|
|
|
+ ready bool // Whether the listenbuffer has been activated
|
|
|
|
+ activate chan struct{} // Channel to control activation of the listenbuffer
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Close closes the wrapped socket.
|
|
func (l *defaultListener) Close() error {
|
|
func (l *defaultListener) Close() error {
|
|
return l.wrapped.Close()
|
|
return l.wrapped.Close()
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Addr returns the listening address of the wrapped socket.
|
|
func (l *defaultListener) Addr() net.Addr {
|
|
func (l *defaultListener) Addr() net.Addr {
|
|
return l.wrapped.Addr()
|
|
return l.wrapped.Addr()
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+// Accept returns a client connection on the wrapped socket if the listen buffer
|
|
|
|
+// has been activated. To active the listenbuffer the activation channel passed
|
|
|
|
+// to NewListenBuffer must have been closed or sent an event.
|
|
func (l *defaultListener) Accept() (net.Conn, error) {
|
|
func (l *defaultListener) Accept() (net.Conn, error) {
|
|
// if the listen has been told it is ready then we can go ahead and
|
|
// if the listen has been told it is ready then we can go ahead and
|
|
// start returning connections
|
|
// start returning connections
|