resp

package
v1.3.0 Latest Latest
Warning

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

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

Documentation

Overview

Package resp Tellstone Redis-Compatible Wire Protocol File: acl.go Description: ACL command family (SETUSER, DELUSER, LIST, LOG) — the Redis-flavored management alias over the RBAC policy store. Users bind to a role plus password options exactly like ROLE SETUSER; LIST renders each user with its role's command and namespace permissions but never a password hash; LOG returns the recent auth-failure buffer. Reply building is RESP2 only; the binary protocol carries its own wire encoding.

Authors:

Maximilian Hagen

Package resp Tellstone Redis-Compatible Wire Protocol File: command.go Description: COMMAND command family (COUNT, DOCS, INFO, LIST, HELP). Introspection surface for the RESP server: redis-cli and cluster-aware clients probe it during the handshake to learn the server's capabilities — which commands exist, their arity, and where the key arguments sit. The table is static because Tellstone's command set is fixed at build time; subcommands nest under their parent (ROLE, ACL, COMMAND) exactly like Valkey. Reply building is RESP2 only; the binary protocol carries its own wire encoding and does not expose this surface.

Authors:

Maximilian Hagen

Package resp Tellstone Redis-Compatible Wire Protocol File: handshake.go Description: Traffic-independent enforcement of the TLS handshake deadline. Connections handed to the TLS state machine — on accept for implicit TLS, on upgrade for STARTTLS — are registered here and swept from the gnet engine ticker, so a client that stops sending after the transition cannot hold a socket, its read buffer, and its TLS state past the deadline.

Authors:

Surafel Workayehu

Package resp Tellstone Redis-Compatible Wire Protocol File: protocol.go Description: Zero-allocation RESP2 (Redis Serialization Protocol) codec. Parses multibulk command frames directly out of the network read buffer and provides append-style reply encoders. Used by the optional RESP listener so Tellstone can be driven by standard tooling (redis-benchmark, memtier_benchmark) for cross-system comparison.

Authors:

Maximilian Hagen

Package resp Tellstone Redis-Compatible Wire Protocol File: respreply.go Description: Reply encoder that adapts the shared command layer's Reply contract to RESP2 output. The encoder appends into the connection's reusable buffer so the GET, SET, and DEL path stays allocation-free; only the error paths build strings.

Authors:

Maximilian Hagen

Package resp Tellstone Redis-Compatible Wire Protocol File: role.go Description: ROLE command family (CREATE, SETUSER, DELUSER, DELETE, LIST, GETUSER). Mutations delegate to the rbac.Store helpers, which clone the active snapshot and republish it with one atomic swap, so readers always observe a complete policy. Reply building is RESP2 only; the binary protocol carries its own wire encoding.

Authors:

Maximilian Hagen

Package resp Tellstone Redis-Compatible Wire Protocol File: server.go Description: Optional gnet event-loop server speaking RESP2, reusing the shared storage engine via a small Store interface. Supports PING, GET, SET (with optional EX/PX), DEL, and AUTH; unknown commands return an error without dropping the connection. Exists so Tellstone can be driven by standard Redis tooling (redis-benchmark, memtier_benchmark) for cross-system comparison. Supports optional implicit TLS 1.3 or an explicit STARTTLS in-place upgrade via the internal TLS library. When a server password is configured (--require-pass / TSD_REQUIRE_PASS), connections must authenticate via AUTH before issuing commands other than PING and QUIT.

Authors:

Maximilian Hagen

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func AppendArray added in v1.1.0

func AppendArray(dst []byte, n int) []byte

AppendArray appends a RESP array header ("*<n>\r\n").

func AppendBulk

func AppendBulk(dst, b []byte) []byte

AppendBulk appends a RESP bulk string ("$<len>\r\n<b>\r\n").

func AppendError

func AppendError(dst []byte, s string) []byte

AppendError appends a RESP error ("-<s>\r\n").

func AppendInt

func AppendInt(dst []byte, n int64) []byte

AppendInt appends a RESP integer (":<n>\r\n").

func AppendNullBulk

func AppendNullBulk(dst []byte) []byte

AppendNullBulk appends a RESP2 null bulk string ("$-1\r\n").

func AppendSimpleString

func AppendSimpleString(dst []byte, s string) []byte

AppendSimpleString appends a RESP simple string ("+<s>\r\n").

func EqualFold

func EqualFold(a []byte, b string) bool

EqualFold reports whether the ASCII command token a equals the upper-case literal b case-insensitively. b must already be upper-case (e.g. "GET").

func Parse

func Parse(buf []byte, dst [][]byte) (args [][]byte, consumed int, err error)

Parse decodes a single RESP2 multibulk command from buf, appending the argument slices (which point INTO buf) to dst[:0]. It returns the arguments, the number of bytes consumed, and an error. errIncomplete means buf needs more data; errProtocol means malformed framing.

Only the multibulk form (*<n>\r\n $<len>\r\n<bytes>\r\n ...) is supported, which is what redis-benchmark and memtier_benchmark emit.

Types

type Server

type Server struct {
	gnet.BuiltinEventEngine
	// contains filtered or unexported fields
}

Server is an edge-triggered RESP2 listener backed by gnet.

func NewServer

func NewServer(addr string, store Store, shards []*shard.Shard, logger log.Logger, tlsConfigs *tlslib.ConfigStore, requirePass string, startTLS bool, policy *rbac.Store, provider oauth.Provider, audit *audit.LogEngine) *Server

NewServer creates a RESP server bound to addr that dispatches commands to store. shards is optional — if nil, per-shard metrics are not tracked. tlsConfigs is optional — if nil, plaintext TCP is used. When configured, each accepted connection atomically loads the latest immutable TLS configuration. requirePass is optional — if empty, AUTH is a no-op and connections start authenticated; otherwise it is hashed once at startup and clients must AUTH before issuing commands. startTLS keeps the RESP listener plaintext until a client successfully issues STARTTLS. policy is optional — if nil, RBAC is disabled and every authenticated command is allowed; otherwise AUTH resolves per-user credentials and sessions gate data commands. audit is the shared audit engine; it must be non-nil (pass a disabled engine when audit logging is off) and is always called without a nil guard.

func (*Server) BytesRead

func (s *Server) BytesRead() uint64

func (*Server) BytesWritten

func (s *Server) BytesWritten() uint64

func (*Server) ConnectedClients

func (s *Server) ConnectedClients() uint64

func (*Server) ListenAndServe

func (s *Server) ListenAndServe() error

ListenAndServe starts the multi-reactor epoll event loop (blocking).

func (*Server) OnBoot

func (s *Server) OnBoot(eng gnet.Engine) gnet.Action

func (*Server) OnClose

func (s *Server) OnClose(c gnet.Conn, err error) (action gnet.Action)

func (*Server) OnOpen

func (s *Server) OnOpen(c gnet.Conn) (out []byte, action gnet.Action)

func (*Server) OnTick added in v1.1.0

func (s *Server) OnTick() (time.Duration, gnet.Action)

OnTick sweeps the pre-handshake registry. gnet runs it on a dedicated goroutine started alongside the event loops, never on one of them, so it must touch only concurrency-safe state — see handshakeSweeper. The interval is a tenth of the deadline: a stalled socket is then reaped within 10% of it, and a single knob (handshakeTimeout) shrinks both for tests.

func (*Server) OnTraffic

func (s *Server) OnTraffic(c gnet.Conn) gnet.Action

OnTraffic parses every complete command currently buffered, batches all replies into a single write, and advances the inbound buffer once — which makes pipelined workloads (redis-benchmark -P / memtier --pipeline) amortize syscalls.

func (*Server) ProtocolErrors

func (s *Server) ProtocolErrors() uint64

func (*Server) Shutdown

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

Shutdown gracefully stops the event loop, waiting for in-flight connections to drain or ctx to expire. It blocks until ListenAndServe has reached OnBoot, so it is safe to call concurrently with ListenAndServe from another goroutine (e.g. a signal handler).

func (*Server) TotalConnections

func (s *Server) TotalConnections() uint64

type Store

type Store interface {
	Get(key string) ([]byte, bool)
	Set(key string, value []byte, ttl time.Duration) error
	Delete(key string) bool
}

Store is the subset of the storage engine the RESP server needs. *storage.Engine satisfies it directly, which keeps this package decoupled and easy to test with a fake.

Jump to

Keyboard shortcuts

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