2026-04-04 10:39:59 +00:00
|
|
|
package proxy
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"crypto/tls"
|
|
|
|
|
"errors"
|
|
|
|
|
"net"
|
|
|
|
|
"strconv"
|
|
|
|
|
)
|
|
|
|
|
|
2026-04-04 14:21:44 +00:00
|
|
|
// NewServer opens a listener and prepares the accept loop.
|
2026-04-04 10:39:59 +00:00
|
|
|
//
|
2026-04-04 14:21:44 +00:00
|
|
|
// srv, errorValue := proxy.NewServer(proxy.BindAddr{Host: "0.0.0.0", Port: 3333}, nil, rateLimiter, onAccept)
|
2026-04-04 12:01:40 +00:00
|
|
|
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)))
|
2026-04-04 10:39:59 +00:00
|
|
|
listener, errorValue := net.Listen("tcp", address)
|
|
|
|
|
if errorValue != nil {
|
|
|
|
|
return nil, errorValue
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return &Server{
|
2026-04-04 12:01:40 +00:00
|
|
|
addr: bindAddress,
|
|
|
|
|
tlsCfg: tlsConfig,
|
|
|
|
|
limiter: rateLimiter,
|
2026-04-04 10:39:59 +00:00
|
|
|
onAccept: onAccept,
|
|
|
|
|
listener: listener,
|
|
|
|
|
done: make(chan struct{}),
|
|
|
|
|
}, nil
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-04 13:07:29 +00:00
|
|
|
// Start accepts miners in a background goroutine.
|
2026-04-04 10:39:59 +00:00
|
|
|
//
|
|
|
|
|
// srv.Start()
|
2026-04-04 12:01:40 +00:00
|
|
|
func (server *Server) Start() {
|
|
|
|
|
if server == nil || server.listener == nil {
|
2026-04-04 10:39:59 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
|
for {
|
2026-04-04 12:01:40 +00:00
|
|
|
conn, errorValue := server.listener.Accept()
|
2026-04-04 10:39:59 +00:00
|
|
|
if errorValue != nil {
|
|
|
|
|
select {
|
2026-04-04 12:01:40 +00:00
|
|
|
case <-server.done:
|
2026-04-04 10:39:59 +00:00
|
|
|
return
|
|
|
|
|
default:
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-04 12:01:40 +00:00
|
|
|
if server.limiter != nil && !server.limiter.Allow(conn.RemoteAddr().String()) {
|
2026-04-04 10:39:59 +00:00
|
|
|
_ = conn.Close()
|
|
|
|
|
continue
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-04 12:01:40 +00:00
|
|
|
if server.tlsCfg != nil {
|
|
|
|
|
conn = tls.Server(conn, server.tlsCfg)
|
2026-04-04 10:47:58 +00:00
|
|
|
}
|
|
|
|
|
|
2026-04-04 12:01:40 +00:00
|
|
|
if server.onAccept == nil {
|
2026-04-04 10:39:59 +00:00
|
|
|
_ = conn.Close()
|
|
|
|
|
continue
|
|
|
|
|
}
|
2026-04-04 12:01:40 +00:00
|
|
|
server.onAccept(conn, server.addr.Port)
|
2026-04-04 10:39:59 +00:00
|
|
|
}
|
|
|
|
|
}()
|
|
|
|
|
}
|
|
|
|
|
|
2026-04-04 14:21:44 +00:00
|
|
|
// Stop closes the listener without forcing existing sockets shut.
|
2026-04-04 10:39:59 +00:00
|
|
|
//
|
|
|
|
|
// srv.Stop()
|
2026-04-04 12:01:40 +00:00
|
|
|
func (server *Server) Stop() {
|
|
|
|
|
if server == nil || server.listener == nil {
|
2026-04-04 10:39:59 +00:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
select {
|
2026-04-04 12:01:40 +00:00
|
|
|
case <-server.done:
|
2026-04-04 10:39:59 +00:00
|
|
|
default:
|
2026-04-04 12:01:40 +00:00
|
|
|
close(server.done)
|
2026-04-04 10:39:59 +00:00
|
|
|
}
|
2026-04-04 12:01:40 +00:00
|
|
|
_ = server.listener.Close()
|
2026-04-04 10:39:59 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var errServerClosed = errors.New("server closed")
|