server

package
v1.8.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 1, 2026 License: MIT Imports: 42 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type CertManager added in v1.6.0

type CertManager struct {
	// contains filtered or unexported fields
}

CertManager manages TLS certificates with automatic reloading

func NewCertManager added in v1.6.0

func NewCertManager(certPath, keyPath string) (*CertManager, error)

NewCertManager creates a new certificate manager

func (*CertManager) GetCertificate added in v1.6.0

func (cm *CertManager) GetCertificate(hello *tls.ClientHelloInfo) (*tls.Certificate, error)

GetCertificate returns the current certificate

func (*CertManager) GetTLSConfig added in v1.6.0

func (cm *CertManager) GetTLSConfig() *tls.Config

GetTLSConfig returns a TLS config that uses dynamic certificate loading Each call returns a fresh config to avoid race conditions

func (*CertManager) Reload added in v1.6.0

func (cm *CertManager) Reload() error

Reload forces a certificate reload

func (*CertManager) Stop added in v1.6.0

func (cm *CertManager) Stop()

Stop stops the certificate manager and waits for cleanup

type Listener added in v1.6.4

type Listener interface {
	// Proto returns the transport tag — "udp", "tcp", "tls", "doh",
	// "doh3", "doq" — used for logging and metrics.
	Proto() string

	// Addr returns the configured bind address.
	Addr() string

	// Bind acquires the underlying socket (and any TLS material it
	// needs) synchronously. A non-nil return means the listener is
	// not ready to serve.
	Bind(ctx context.Context) error

	// Serve blocks until Shutdown is called or the socket is closed.
	// It must only be called after a successful Bind.
	Serve(ctx context.Context) error

	// Shutdown releases the underlying socket. Safe to call before
	// Serve or after Serve has already returned.
	Shutdown(ctx context.Context) error

	// Critical reports whether a Bind failure on this listener should
	// abort server startup. Plain DNS (UDP+TCP on cfg.Bind) is
	// critical; optional services (TLS, DoH, DoH3, DoQ) are not —
	// a missing cert or misconfigured addr only disables that service.
	Critical() bool

	// Serving reports whether the Serve loop is currently active.
	// This is stricter than "Bind succeeded": QUIC-based listeners
	// (DoH3, DoQ) complete their real startup inside Serve, so a
	// listener can be bound but not actually serving if Serve
	// returned an error during its own setup phase.
	Serving() bool
}

Listener is the lifecycle contract for a single DNS service endpoint (UDP, TCP, DoT, DoH, DoH3, DoQ). It separates bind from serve so that the Server can fail fast on port-in-use, missing cert, etc. instead of swallowing the error inside a background goroutine.

Lifecycle: Bind → Serve → Shutdown. Bind may be called at most once. Serve returns when Shutdown is called or the underlying socket closes. Shutdown is idempotent.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server type.

func New

func New(cfg *config.Config) *Server

New return new server.

func (*Server) GetTLSConfig added in v1.6.4

func (s *Server) GetTLSConfig() *tls.Config

GetTLSConfig satisfies certProvider. It lazily materialises the shared CertManager on first TLS listener Bind and hands out its live TLS config (with rotation hooks) to each listener that asks.

func (*Server) HasListener added in v1.6.4

func (s *Server) HasListener(proto string) bool

func (*Server) InlineReady added in v1.8.0

func (s *Server) InlineReady() bool

InlineReady reports whether the pipeline carries an inline barrier; the engines enable the reader fast path only when it does.

func (*Server) Quiesced added in v1.8.0

func (s *Server) Quiesced() bool

HasListener reports whether a listener with the given proto tag is actually serving right now — stricter than "Bind succeeded". DoH3 and DoQ do their real QUIC bring-up inside Serve, so checking only membership in s.active can report success even when the transport never started. Asking the listener via Serving() gives the truth. Quiesced reports whether every owned transport has all of its job slabs back in the ring: nothing is being read into, served, or staged for a send.

It is the completion barrier a measurement needs. A client holding its last reply proves the bytes left, not that the slab that carried them was released — the release runs after the send, on the server's own goroutine — so anything that samples the process at that moment (an allocation gate, a leak check, a drain assertion) is otherwise reduced to sleeping and hoping. Transports that own no slabs are quiescent by construction and answer for themselves.

func (*Server) ReloadCertificate added in v1.6.0

func (s *Server) ReloadCertificate() error

ReloadCertificate forces a certificate reload on all TLS listeners.

func (*Server) Run

func (s *Server) Run(ctx context.Context) error

Run binds every configured listener synchronously, returns a non-nil error if a critical listener (plain DNS UDP/TCP) could not bind, and otherwise spawns Serve goroutines that run until ctx is cancelled. Run itself is non-blocking — main waits on ctx and polls Stopped for graceful shutdown.

func (*Server) ServeDNS

func (s *Server) ServeDNS(w dns.ResponseWriter, r *dns.Msg)

ServeDNS keeps *Server a dns.Handler for embedders: the rewrite moved the owned transports off this entry, but code that mounts a Server under the library's mux did not change. A dns.ResponseWriter is a Transport already; nothing here is on the serving path.

func (*Server) ServeDNSContext added in v1.7.4

func (s *Server) ServeDNSContext(parent context.Context, w dns.ResponseWriter, r *dns.Msg)

ServeDNSContext is ServeDNS with a caller-owned parent context, kept for the same embedders.

func (*Server) ServeHTTP

func (s *Server) ServeHTTP(w http.ResponseWriter, r *http.Request)

ServeHTTP implements http.Handler (DoH + DoH3).

func (*Server) ServeMsg added in v1.8.0

func (s *Server) ServeMsg(parent context.Context, w middleware.Transport, r *dns.Msg)

ServeMsg serves one decoded DNS request under the transport's lifetime and the configured end-to-end middleware/resolution timeout. It is the entry for transports that already hold a message — DNS-over-HTTP and DNS-over-QUIC supply client-aware parents — and for embedders. Its writers made no byte-sink promise, so they never receive raw packed bytes; the owned raw transports enter through ServeRaw instead, which is the one road to the direct-pack capability.

func (*Server) ServeRaw added in v1.8.0

func (s *Server) ServeRaw(w middleware.Transport, raw []byte, readTime time.Time) bool

ServeRaw is the single raw-transport ingress. An eligible packet on a job transport enters the chain as a wire-born request on the job carrier — no decode, no context allocation; anything else decodes here and takes the ordinary lazy-deadline entry with the direct-pack capability (the owned transports are raw byte sinks).

func (*Server) ServeRawInline added in v1.8.0

func (s *Server) ServeRawInline(w middleware.Transport, raw []byte, readTime time.Time) (handled bool)

ServeRawInline is ServeRaw for a transport reader that must not block: the full chain runs with the inline-only mark, and the cache — the one handler whose downstream can block on the network — declines a query it cannot answer from its wire ladder, unwritten. handled reports whether the query reached a terminal here; a false return with handoff true means the caller owns an admitted, guarded, unanswered job it must replay on a worker with ServeRawReplay. A packet the strict path cannot carry is a handoff outright: the decoded fallback resolves, and resolving blocks.

func (*Server) ServeRawReplay added in v1.8.0

func (s *Server) ServeRawReplay(w middleware.Transport, raw []byte, readTime time.Time) bool

ServeRawReplay finishes a query the inline pass handed off. The full pipeline runs with the replay mark: handlers whose entry effects fired on the inline pass skip them, and the middlewares that key off the response fire here, once, when this pass writes.

func (*Server) Stop added in v1.6.0

func (s *Server) Stop()

Stop releases long-lived resources (currently just the cert manager).

func (*Server) Stopped added in v1.3.2

func (s *Server) Stopped() bool

Stopped reports whether the shutdown is complete: every Serve goroutine has exited *and* the supervisor has finished with every listener. That is the question a caller polling for shutdown actually has, because the only use for the answer is doing something else with what the server held — exiting, or binding the same addresses again.

Both halves are needed. The plain UDP and TCP listeners close their sockets inside Shutdown before the Serve they unblock returns, so for them the goroutine count alone would do. QUIC does not work that way: http3 and DoQ hand their accept loop a PacketConn they do not own, so Serve returns as soon as the server stops accepting while the socket stays open until the supervisor closes it a few statements later. A caller that rebound on the goroutine count alone met "address already in use", rarely for DoH3 and often for DoQ.

It does not mean nothing is running. A handler that outlasts its listener's drain deadline is force-closed and left to finish on its own — the alternative is a shutdown that a single stuck request can hang forever — so work can outlive this by as long as that handler takes. Process exit is the backstop for that, and an in-process restart is safe from the socket's point of view but not a guarantee that the old server's last requests have unwound.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL