package proxy import ( "crypto/tls" "errors" "net" "strconv" ) // NewServer opens a listener and prepares the accept loop. // // srv, errorValue := proxy.NewServer(proxy.BindAddr{Host: "0.0.0.0", Port: 3333}, nil, rateLimiter, onAccept) func NewServer(bindAddress BindAddr, tlsConfig *tls.Config, rateLimiter *RateLimiter, onAccept func(net.Conn, uint16)) (*Server, error) { address := net.JoinHostPort(bindAddress.Host, strconv.Itoa(int(bindAddress.Port))) listener, errorValue := net.Listen("tcp", address) if errorValue != nil { return nil, errorValue } return &Server{ addr: bindAddress, tlsCfg: tlsConfig, limiter: rateLimiter, onAccept: onAccept, listener: listener, done: make(chan struct{}), }, nil } // Start accepts miners in a background goroutine. // // srv.Start() func (server *Server) Start() { if server == nil || server.listener == nil { return } go func() { for { conn, errorValue := server.listener.Accept() if errorValue != nil { select { case <-server.done: return default: continue } } if server.limiter != nil && !server.limiter.Allow(conn.RemoteAddr().String()) { _ = conn.Close() continue } if server.tlsCfg != nil { conn = tls.Server(conn, server.tlsCfg) } if server.onAccept == nil { _ = conn.Close() continue } server.onAccept(conn, server.addr.Port) } }() } // Stop closes the listener without forcing existing sockets shut. // // srv.Stop() func (server *Server) Stop() { if server == nil || server.listener == nil { return } select { case <-server.done: default: close(server.done) } _ = server.listener.Close() } var errServerClosed = errors.New("server closed")