listener.go 968 B

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. package service
  2. import (
  3. "net"
  4. "sync"
  5. )
  6. type tcpListener struct {
  7. port uint16
  8. s *Service
  9. addr *net.TCPAddr
  10. accept chan net.Conn
  11. // closed is closed instead of accept so a handler blocked handing off a
  12. // connection can't send on a closed channel.
  13. closed chan struct{}
  14. closeOnce sync.Once
  15. }
  16. func (l *tcpListener) Accept() (net.Conn, error) {
  17. // select picks randomly among ready cases, so without this a handler still
  18. // waiting to hand off could win over closed after Close has returned.
  19. select {
  20. case <-l.closed:
  21. return nil, net.ErrClosed
  22. default:
  23. }
  24. select {
  25. case conn := <-l.accept:
  26. return conn, nil
  27. case <-l.closed:
  28. return nil, net.ErrClosed
  29. }
  30. }
  31. func (l *tcpListener) Close() error {
  32. l.closeOnce.Do(func() {
  33. l.s.mu.Lock()
  34. delete(l.s.mu.listeners, l.port)
  35. l.s.mu.Unlock()
  36. close(l.closed)
  37. })
  38. return nil
  39. }
  40. // Addr returns the listener's network address.
  41. func (l *tcpListener) Addr() net.Addr {
  42. return l.addr
  43. }