package proxy import ( "crypto/tls" "errors" "net" "strconv" ) // NewServer binds one miner-facing TCP listener. // // srv, errorValue := proxy.NewServer(bind, nil, limiter, onAccept) func NewServer(bind BindAddr, tlsCfg *tls.Config, limiter *RateLimiter, onAccept func(net.Conn, uint16)) (*Server, error) { address := net.JoinHostPort(bind.Host, strconv.Itoa(int(bind.Port))) listener, errorValue := net.Listen("tcp", address) if errorValue != nil { return nil, errorValue } return &Server{ addr: bind, tlsCfg: tlsCfg, limiter: limiter, onAccept: onAccept, listener: listener, done: make(chan struct{}), }, nil } // Start begins accepting connections in a goroutine. // // srv.Start() func (s *Server) Start() { if s == nil || s.listener == nil { return } go func() { for { conn, errorValue := s.listener.Accept() if errorValue != nil { select { case <-s.done: return default: continue } } if s.limiter != nil && !s.limiter.Allow(conn.RemoteAddr().String()) { _ = conn.Close() continue } if s.tlsCfg != nil { conn = tls.Server(conn, s.tlsCfg) } if s.onAccept == nil { _ = conn.Close() continue } s.onAccept(conn, s.addr.Port) } }() } // Stop closes the listener. // // srv.Stop() func (s *Server) Stop() { if s == nil || s.listener == nil { return } select { case <-s.done: default: close(s.done) } _ = s.listener.Close() } var errServerClosed = errors.New("server closed")