b01f5d065f
- Extract newRecorderObject, checkRateLimit, sniffingDial, and handleSniffedProtocol from the Handle method into dedicated files (sniffing.go, util.go) to reduce Handle from ~100 to ~65 lines. - Introduce SnifferBuilder: populated once during Init, reused via Build() per connection. Avoids reconstructing a 9-field sniffing.Sniffer literal on every inbound connection. - Hoist router nil check from the lazy dial closure into Handle so misconfigured handlers fail immediately instead of silently dropping unrecognised traffic with no error. - Add nil-addr guard in checkRateLimit (missing from the old inline version — would panic if the remote address were somehow nil). - Add comprehensive unit tests (44 tests across 5 test files) covering handler creation, Init, metadata parsing (defaults, custom, MITM, error paths), protocol dispatch (HTTP, TLS, unknown, empty), rate limiting, recorder objects, dial plumbing, and SnifferBuilder. - Add package-level godoc explaining the handler scope, limitations vs tcp/forward, and the connection processing flow. - Fix metadata comment: s/SnifferBuilder/sniffing.Sniffer/.
50 lines
1.3 KiB
Go
50 lines
1.3 KiB
Go
package sni
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"net"
|
|
"time"
|
|
|
|
xctx "github.com/go-gost/x/ctx"
|
|
xrecorder "github.com/go-gost/x/recorder"
|
|
)
|
|
|
|
var (
|
|
errRouterNotAvailable = errors.New("sni: router not available")
|
|
)
|
|
|
|
// newRecorderObject creates a HandlerRecorderObject populated with connection
|
|
// metadata (service, addresses, network type, session ID, client address).
|
|
func (h *sniHandler) newRecorderObject(ctx context.Context, conn net.Conn, start time.Time) *xrecorder.HandlerRecorderObject {
|
|
ro := &xrecorder.HandlerRecorderObject{
|
|
Service: h.options.Service,
|
|
RemoteAddr: conn.RemoteAddr().String(),
|
|
LocalAddr: conn.LocalAddr().String(),
|
|
Network: "tcp",
|
|
Time: start,
|
|
SID: xctx.SidFromContext(ctx).String(),
|
|
}
|
|
if srcAddr := xctx.SrcAddrFromContext(ctx); srcAddr != nil {
|
|
ro.ClientAddr = srcAddr.String()
|
|
}
|
|
return ro
|
|
}
|
|
|
|
// checkRateLimit verifies that the remote address has not exceeded the
|
|
// configured connection rate limit. Returns true if allowed, or if no rate
|
|
// limiter is configured.
|
|
func (h *sniHandler) checkRateLimit(addr net.Addr) bool {
|
|
if h.options.RateLimiter == nil {
|
|
return true
|
|
}
|
|
if addr == nil {
|
|
return true
|
|
}
|
|
host, _, _ := net.SplitHostPort(addr.String())
|
|
if limiter := h.options.RateLimiter.Limiter(host); limiter != nil {
|
|
return limiter.Allow(1)
|
|
}
|
|
return true
|
|
}
|