go-proxy/server_runtime.go
Virgil 48c6e0fc6d feat(proxy): implement RFC runtime primitives
Co-Authored-By: Virgil <virgil@lethean.io>
2026-04-04 10:39:59 +00:00

80 lines
1.4 KiB
Go

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.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")