conn

package
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Apr 19, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package conn provides shared HTTP/1.1 and HTTP/2 connection handling.

Index

Constants

This section is empty.

Variables

View Source
var ErrHijacked = errors.New("celeris: connection hijacked")

ErrHijacked is returned by ProcessH1 when the connection was hijacked. The engine must not close or reuse the FD after receiving this error.

View Source
var ErrUpgradeH2C = errors.New("celeris: h2c upgrade requested")

ErrUpgradeH2C is returned by ProcessH1 after it has written the 101 Switching Protocols response in reply to an RFC 7540 §3.2 h2c upgrade request. The engine must NOT treat this as an error: instead it must read state.UpgradeInfo and switch the connection to H2.

The original handler has NOT been invoked; it will be dispatched on H2 stream 1 by NewH2StateFromUpgrade once the H2 stack is up.

Functions

func CloseH1 added in v1.1.0

func CloseH1(state *H1State)

CloseH1 releases the cached stream and context (if any) back to their pools.

func CloseH2

func CloseH2(state *H2State)

CloseH2 cleans up H2 state. Releases all streams still held by the manager to prevent memory leaks on connection close.

func DecodeHTTP2Settings added in v1.4.0

func DecodeHTTP2Settings(s string) ([]byte, error)

DecodeHTTP2Settings base64url-decodes the HTTP2-Settings header value. RFC 7540 §3.2.1 specifies base64url without padding, but some clients include padding — accept both.

Validation: the decoded payload length must be a multiple of 6 (one SETTINGS entry = u16 id + u32 value). Any other length indicates a malformed payload.

func ProcessH1

func ProcessH1(ctx context.Context, data []byte, state *H1State, handler stream.Handler,
	write func([]byte)) error

ProcessH1 processes incoming H1 data, parsing requests and calling the handler. The write callback is used to send response bytes back to the connection.

func ProcessH2

func ProcessH2(ctx context.Context, data []byte, state *H2State, _ stream.Handler,
	write func([]byte), _ H2Config) error

ProcessH2 processes incoming H2 data. On first call, validates the client preface and sends server settings. PING, SETTINGS ACK) and falls back to x/net framer for complex types.

func ReleaseUpgradeInfo added in v1.4.0

func ReleaseUpgradeInfo(info *UpgradeInfo)

ReleaseUpgradeInfo resets every field and returns the struct to the pool. Aliased slices (Body, Remaining) keep their source buffers alive via their slice references, so we MUST nil them out before returning to the pool or the next acquirer's value will pin stale memory.

Types

type H1State

type H1State struct {
	RemoteAddr         string
	HijackFn           func() (net.Conn, error)                            // set by engine; nil if unsupported
	MaxRequestBodySize int64                                               // 0 = use default (100 MB)
	OnExpectContinue   func(method, path string, headers [][2]string) bool // nil = always accept
	OnDetach           func()                                              // set by engine; called on Context.Detach
	Detached           bool                                                // set by OnDetach; breaks pipelining loop

	// WSDataDelivery is set by the WebSocket middleware after upgrade (101 sent).
	// When non-nil and Detached, subsequent reads are delivered as raw bytes
	// to this callback instead of being parsed as H1 requests. The callback
	// is called on the event loop thread — it must not block.
	WSDataDelivery func(data []byte)

	// RawWriteFn is set after Detach. It writes raw bytes to the engine's
	// write buffer, bypassing H1 chunked encoding. Used by WebSocket for
	// frame writes.
	RawWriteFn func([]byte)

	// OnDetachClose is called by the engine when it closes a detached
	// connection (timeout, error, shutdown). The WebSocket middleware sets
	// this to close the io.Pipe and data channel, unblocking the handler
	// goroutine. Called under cs.detachMu — must not block.
	//
	// Detached-connection API surface — stable. The fields below
	// (OnDetachClose, OnError, PauseRecv, ResumeRecv, IdleDeadlineNs) form
	// the contract between the engine layer and any long-lived-connection
	// middleware (WebSocket, SSE, gRPC streaming, etc). They are part of
	// the celeris public API: changes require a major version bump.
	OnDetachClose func()

	// OnError is called by the engine when an I/O failure occurs on a
	// detached connection (read error, write error, EPIPE, ECONNRESET, etc).
	// The WebSocket middleware uses this to surface engine-side errors
	// from the next user-level Read or Write call. Called under cs.detachMu
	// — must not block.
	OnError func(err error)

	// PauseRecv and ResumeRecv are set by the engine in OnDetach. The
	// middleware calls them to apply TCP-level backpressure on the inbound
	// data path. They may be called from any goroutine and are no-ops if
	// the engine cannot pause reads (e.g. std hijacked path).
	PauseRecv  func()
	ResumeRecv func()

	// IdleDeadlineNs holds the absolute deadline (Unix nanoseconds) at
	// which a detached connection should be closed by the engine. The
	// WebSocket middleware updates this after each successful frame read;
	// the engine's idle sweep checks it on detached connections. 0 = no
	// deadline.
	IdleDeadlineNs atomic.Int64

	// EnableH2Upgrade, when true, permits this connection to honor a
	// valid RFC 7540 §3.2 h2c upgrade request. Set by the engine at
	// initProtocol time from resource.Config.EnableH2Upgrade.
	EnableH2Upgrade bool
	// UpgradeInfo is populated by ProcessH1 just before returning
	// ErrUpgradeH2C. The engine consumes it via switchToH2 and then clears
	// it. Always nil on a clean (non-upgrade) connection.
	UpgradeInfo *UpgradeInfo
	// contains filtered or unexported fields
}

H1State holds per-connection H1 parsing state.

func NewH1State

func NewH1State() *H1State

NewH1State creates a new H1 connection state with zero-copy header parsing.

func (*H1State) UpdateWriteFn added in v1.2.0

func (s *H1State) UpdateWriteFn(fn func([]byte))

UpdateWriteFn replaces the response adapter's write function. Called by OnDetach to route StreamWriter writes through the mutex-guarded writeFn.

type H2Config

type H2Config struct {
	MaxConcurrentStreams uint32
	InitialWindowSize    uint32
	MaxFrameSize         uint32
	MaxRequestBodySize   int64 // 0 = use default (100 MB)
}

H2Config holds H2 connection configuration.

type H2State

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

H2State holds per-connection H2 state.

Sub-structures (outBuf, inBuf, wq, rw, inlineRW) are embedded as VALUES rather than pointer fields so the whole struct is allocated in one heap block instead of 8. Pointer callers take &s.outBuf etc; since heap allocations don't move in Go, the inner pointers stay stable for the lifetime of the H2State.

`processor`, `parser`, and `writer` remain pointer fields — Processor in particular is already large (sync.Mutex, multiple maps, hpack state) and has its own lifecycle hooks, so collapsing it into the parent would invert the existing layering.

func NewH2State

func NewH2State(handler stream.Handler, cfg H2Config, write func([]byte), wakeupFD int) *H2State

NewH2State creates a new H2 connection state. wakeupFD is an eventfd used to signal the event loop when handler goroutines enqueue responses (-1 to disable, falling back to polling).

func NewH2StateFromUpgrade added in v1.4.0

func NewH2StateFromUpgrade(handler stream.Handler, cfg H2Config, write func([]byte), wakeupFD int, info *UpgradeInfo) (*H2State, error)

NewH2StateFromUpgrade constructs an H2State that has already absorbed the RFC 7540 §3.2 h2c upgrade: the server preface (SETTINGS + ACK) is written synchronously, the client's HTTP2-Settings are applied, and the original H1 request is injected as stream 1. The engine then feeds info.Remaining — which may contain the expected H2 client preface and initial SETTINGS frame — through ProcessH2 on the same iteration.

Unlike NewH2State, this function writes to the connection directly (before returning) because the 101 response has already been sent and the client is entitled to see the server SETTINGS immediately.

func (*H2State) DrainWriteQueue added in v1.1.0

func (s *H2State) DrainWriteQueue(write func([]byte))

DrainWriteQueue drains async handler responses to the write function. Called from the event loop thread (outside H2State.mu).

func (*H2State) SetRemoteAddr added in v1.1.0

func (s *H2State) SetRemoteAddr(addr string)

SetRemoteAddr sets the remote address on the H2 stream manager so that all streams created on this connection inherit the peer address.

func (*H2State) WriteQueuePending added in v1.1.0

func (s *H2State) WriteQueuePending() bool

WriteQueuePending returns true if the write queue has pending data.

type UpgradeInfo added in v1.4.0

type UpgradeInfo struct {
	// Settings is the base64url-decoded HTTP2-Settings payload. Each entry
	// is a 6-byte pair (u16 identifier + u32 value); length is always a
	// multiple of 6 (DecodeHTTP2Settings rejects others).
	Settings []byte
	// Method is the H1 request method (used to build the H2 :method
	// pseudo-header).
	Method string
	// URI is the raw request URI as sent on the request line (used for
	// :path).
	URI string
	// Headers are the request's non-hop-by-hop headers, lowercased,
	// excluding Upgrade/Connection/HTTP2-Settings (which are consumed by
	// the upgrade mechanism itself and do not belong on H2 stream 1).
	Headers [][2]string
	// Body holds the request body (may be empty).
	Body []byte
	// Remaining holds the bytes AFTER the H1 request in the recv buffer.
	// May contain 0 bytes, a partial H2 client preface, a full preface, or
	// preface + additional frames. The engine feeds this to ProcessH2
	// synchronously after switchToH2 so no data is dropped at the seam.
	Remaining []byte
}

UpgradeInfo carries the state needed to switch an H1 connection to H2 mid-stream. It is populated by ProcessH1 on an h2c upgrade, then consumed by the engine's switchToH2 path.

Jump to

Keyboard shortcuts

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