| /* |
| Package 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 |
| |
| import "net" |
| |
| // 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) { |
| wrapped, err := net.Listen(proto, addr) |
| if err != nil { |
| return nil, err |
| } |
| |
| return &defaultListener{ |
| wrapped: wrapped, |
| activate: activate, |
| }, nil |
| } |
| |
| // defaultListener is the buffered wrapper around the net.Listener |
| type defaultListener 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 { |
| return l.wrapped.Close() |
| } |
| |
| // Addr returns the listening address of the wrapped socket. |
| func (l *defaultListener) Addr() net.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) { |
| // if the listen has been told it is ready then we can go ahead and |
| // start returning connections |
| if l.ready { |
| return l.wrapped.Accept() |
| } |
| <-l.activate |
| l.ready = true |
| return l.Accept() |
| } |