Hopf
Native, asynchronous, non-blocking, event-driven multi-protocol networking framework in Rust. Successor to Gumdrop without the servlet container — same architectural contracts, TPC execution, plain buffers, and in-tree protocol work.
Hopf is not a server-only product. The default topology is a graph of endpoints on one Runtime: listen and dial are equal. Peer compositions (N listeners + M dialers) are normal. Clients routinely host multiple protocols in one process (at minimum DNS under dial).
Contents
Why Hopf?
- Thread-per-core performance
- mio readiness loops; each connection stays on one reactor for life
- I/O, TLS, and protocol bytes never migrate mid-connection
- storage / blocking work on a separate pool, independent of connection count
- transport-level backpressure and plain
&[u8]/ pooled buffers
- Equal listen and dial
- one Runtime, one composition script, server and client roles as peers
- dynamic bindings: add and remove listeners and dialers while running
- Security substrate (AWS-LC in core)
- TCP TLS 1.2/1.3 and UDP DTLS 1.2/1.3, both in-tree in
hopf-coreon AWS-LC (aws-lc-rs); QUIC's RFC 9000 transport and TLS 1.3 handshake in-tree inhopf-quic, also on AWS-LC directly. Norustlsorquinn-protoin any production dependency graph. - Remaining: DTLS's generic
Endpointintegration (the handshake/record engine and version negotiation are shipped; no protocol crate dials/listens over DTLS yet), and optional GSSAPI/Kerberos SASL. See conformance → Security substrate. - PQC-first QUIC: TLS 1.3 only; hybrid
X25519MLKEM768offered first (prefer-post-quantum)
- TCP TLS 1.2/1.3 and UDP DTLS 1.2/1.3, both in-tree in
- Shared security and policy
- TrustPolicy / IdentityMaterial / SASL across protocols
- CIDR ACLs, accept rate limits, quota seams
- OpenTelemetry (OTLP/HTTP + JSONL) off the hot path
- Near-zero dependencies
- no Tokio, Hyper, Axum, Tower, or serde-as-architecture
- sibling incremental parsers: tractrix, rjsonparser, rmimeparser, rprotobuf
- Protocol depth, not a thin HTTP façade
- HTTP is one peer among many — mail, DNS, FTP, WebDAV, WebSocket, gRPC share the same substrate
- MQTT broker and client; AMQP 0-9-1 client (
hopf-amqp, RabbitMQ wire protocol)
Full feature list
Framework substrate (hopf-core)
- TPC Runtime with accept loop, per-core reactors, timers, buffer pools
Endpoint/ProtocolHandler/Service/Listener/Connectorseams- Dynamic TCP listen and dial (
add_tcp_listener,connect, remove bindings) - STARTTLS and TLS-from-accept/dial via in-tree
hopf-core::tls(acceptor_from_pem,connector_from_pem, and related helpers on AWS-LC) - UDP datagram handling (DNS and friends); DTLS 1.2/1.3 handshake and record engines in
hopf-core::dtls/dtls12(genericEndpointdial/listen integration still outstanding) StorageExecutorfor blocking filesystem / heavy work with fail-fast backpressure- Panic isolation at the connection boundary
- Composition builder (canonical) + XML loader via tractrix (closed registry, no DI)
- Peer ACL (CIDR allow/deny), accept rate limits, quota tracker seam
- Telemetry hook seam (implementations in
hopf-otel)
TLS (hopf-core::tls)
- In-tree TLS 1.2/1.3 record layer and handshakes on AWS-LC (
aws-lc-rs); PEM server and client helpers (acceptor_from_pem,connector_from_pem, and variants) - Hybrid-first PQC key exchange:
X25519MLKEM768preferred when the peer supports it - ALPN negotiation surfaced as
SecurityInfo - Always-on TLS listeners and STARTTLS on cleartext endpoints
- Shared
SharedTlsAcceptor/SharedTlsConnectorconfigs across protocols;TcpConnectiondrivesTlsVariantviaTlsRecordSink - Full API and wiring: TLS
QUIC and HTTP/3 (hopf-quic, hopf-http)
- In-tree RFC 9000 transport and RFC 9001 TLS 1.3 handshake, both in
hopf-quicon AWS-LC directly — noquinn-protoor other external QUIC/TLS library dependency, plus a dedicated mio UDP driver - Each bidirectional QUIC stream is an
Endpoint - HTTP/3 server and client (RFC 9114) with in-tree QPACK (RFC 9204)
- ALPN
h3 - PQC-first processing: QUIC crypto is TLS 1.3-only (RFC 9001), driven by the same in-tree handshake engine TCP TLS 1.3 uses. There is no TLS 1.2 fallback on the QUIC path. Key exchange offers hybrid ML-KEM (
X25519MLKEM768) first, then classical groups if the peer cannot do PQC - Connection-level hooks for control / unidirectional streams
HTTP (hopf-http)
- Unified HTTP Stream API — version- and transport-agnostic
- HTTP/1.0 and 1.1 — chunked TE, persistent connections, h2c Upgrade
- HTTP/2 — HPACK, multiplexing, cleartext prior-knowledge and h2c, ALPN
h2 - HTTP/3 — see above
- Server and client handler SPIs (
ServerHandler/ClientHandler) - Deferred / offloaded responses via
ServerResponseHandle+ storage pool - Protocol upgrade seam (101 / Extended CONNECT) for WebSocket and related
- Authentication factories: Basic, Digest, Bearer (TrustPolicy-backed)
- Configurable
HttpLimits(line length, headers, chunk and body caps)
WebDAV (hopf-webdav)
- RFC 4918 Class 1+2 filesystem handler for Hopf HTTP servers
- PROPFIND / PROPPATCH / MKCOL / COPY / MOVE / LOCK / UNLOCK
- Dead properties (xattr / sidecar / none) and in-process locks, or file-backed shared locks / mirrored sidecar tree via
lock_root/sidecar_root - GET/HEAD/PUT/DELETE with optional write; welcome files
- Filesystem work on
StorageExecutor
WebSocket (hopf-websocket)
- RFC 6455 framing and event handlers
- Bootstrap via HTTP/1.1 Upgrade, HTTP/2 Extended CONNECT (RFC 8441), HTTP/3 Extended CONNECT (RFC 9220)
- Text / binary / ping / pong / close; configurable max payload and subprotocol
- Stock echo factory for demos
gRPC (hopf-grpc)
- Unary gRPC over Hopf HTTP Streams
- Length-prefixed framing;
application/grpc - Runtime
.protomodel (no generated stubs) via rprotobuf - Server
GrpcService+ clientGrpcClient::unary_call
DNS (hopf-dns)
- Resolver: a stub resolver in the RFC 1034 §5.3.1 sense (relies on configured upstreams for recursion) but full-featured otherwise: response caching, EDNS0, RFC 7873 cookies, bailiwick filtering, cache-poisoning resilience (RFC 5452), automatic UDP→TCP truncation fallback, and optional DNSSEC chain-of-trust validation — multi-protocol per upstream server (
add_server_dot/add_server_doq/add_server_doh,dot/doq/dohfeatures): every query helper, retry/failover across a mixed-transport server list, CNAME chase, caching, and DNSSEC validation work the same regardless of which transport actually carried the query - Server (
DnsService,serverfeature): a no-op protocol shell (cookies, TSIG, UDP/TCP/DoT/DoQ framing) with pluggableDnsQueryHandlers: a cachingForwarderHandler, anAuthoritativeZoneHandler, closures and chains of them (split-horizon) - Authoritative zones: BIND-style zone files (
$INCLUDE,$GENERATE), RFC 2136 dynamic update, NOTIFY, AXFR/IXFR, TSIG, secondaries that refresh on NOTIFY and the SOA timers, atomic write-back to the zone file (verified against BINDdigandnsupdate) DnsClientTransport(DoT/DoQ/DoH) also usable standalone for an app that wants to speak one specific encrypted transport directly, outside the resolverconnect_by_namefor async dial-by-hostname onArc<Runtime>- Examples: UDP caching forwarder (
dns-proxy) and authoritative server (dns-authoritative) - Planned: DNS over DTLS (Gumdrop parity) when DTLS lands in
hopf-core
mDNS / DNS-SD (hopf-mdns)
- Multicast DNS responder (RFC 6762): probing with simultaneous-probe tie-break and automatic rename on conflict, announcing with cache-flush, known-answer suppression, unicast (QU) reply support, goodbye on shutdown/drop
- Multicast DNS querier: one-shot and periodic queries backed by an active TTL-fraction-refresh cache (RFC 6762 §5.2) with cache-flush and goodbye grace-period handling (§10.1/§10.2)
- DNS-SD (RFC 6763):
register_service/browsepush-based API — PTR/SRV/TXT publication, the_services._dns-sd._udpmeta-query, TXT attribute codec - Reuses
hopf-dns's wire types directly (no parallel DNS codec); IPv4 only (noff02::fb) - Standalone crate; optional umbrella feature
mdns(pulls indns)
MASQUE (hopf-masque)
- RFC 9298 CONNECT-UDP (full server relay + client) and RFC 9484 CONNECT-IP (accept/capsule plumbing; app supplies IP forwarding) over HTTP/1.1, HTTP/2, and HTTP/3
- Standalone crate; optional umbrella feature
masque,masque-h3(client dial helpers only needh3)
SOCKS (hopf-socks)
- SOCKS4, SOCKS4a, SOCKS5 (RFC 1928): CONNECT, BIND, UDP ASSOCIATE
- Server and client for all three commands (BIND and UDP ASSOCIATE clients go beyond SOCKS's usual CONNECT-only client scope, added for symmetry with the server)
- RFC 1929 username/password auth, server and client
- RFC 1961 GSSAPI auth not implemented — planned with optional GSSAPI in
hopf-auth - Optional umbrella feature
socks
LDAP (hopf-ldap)
- Async LDAPv3 client (RFC 4511) and
LdapCredentialStore; no directory/server side - Bind (simple, anonymous), search (RFC 4515 filters), unbind; definite-length BER codec
- LDAPS (implicit TLS) and StartTLS (RFC 4511 §4.14); referral chase (RFC 4516, opt-in)
- Content synchronization client side (RFC 4533): RefreshOnly/RefreshAndPersist, cookie resume, present/delete phase convergence
LdapCredentialStoredoes search-then-bind for PLAIN/LOGIN; no SASL bind to the directory, no admin API (modify/add/delete/compare)
FTP (hopf-ftp)
- FTP / FTPS server and callback-driven client (RFC 959 + extensions)
- PASV/EPSV, PORT/EPRT, MLST/MLSD, SIZE, MDTM, OPTS UTF8
- Explicit AUTH TLS and implicit FTPS; PROT P data protection
- TrustPolicy auth; chrooted filesystem handler; PASV via dynamic Runtime listeners
SMTP (hopf-smtp)
- SMTP / SMTPS server and callback-driven client (RFC 5321 + ESMTP)
- STARTTLS, AUTH PLAIN, PIPELINING, 8BITMIME, SMTPUTF8, CHUNKING/BDAT, SIZE, DSN, …
- Staged connection-handler SPI (hello → mail → rcpt → data)
- Stock accept-all (discard) handler; SimpleRelayService open MX relay (lab use)
- LocalDeliveryService — APPEND to local INBOX via
hopf-mailbox(mbox / Maildir++)
POP3 (hopf-pop3)
- POP3 / POP3S server (RFC 1939 + CAPA / STLS / UTF8 / SASL AUTH)
- USER/PASS, APOP, TOP, UIDL; staged handler SPI with default mailbox-backed handler
- Opens
INBOXviaMailboxFactory; session DELE until QUIT expunge - Async client:
Pop3Client+Pop3Fetchauto-pilot; USER/PASS, APOP, AUTH PLAIN, STLS/POP3S
NNTP (hopf-nntp)
- Async NNTP / NNTPS client (RFC 3977, 4642, 4643): greeting, CAPABILITIES, STARTTLS or implicit TLS, AUTHINFO SASL / USER-PASS
NntpSessioncommand queue usable from any thread; LIST ACTIVE, GROUP, OVER, ARTICLE, HEAD, POST, QUIT helpers; multi-line replies streamed and dot-unstuffed
IMAP (hopf-imap)
- IMAP4rev2 / IMAPS server (RFC 9051) over
hopf-mailbox; staged handler SPI - IDLE, UIDPLUS, MOVE, NAMESPACE, ENABLE / CONDSTORE / QRESYNC, UNSELECT, ID, LIST-EXTENDED / LIST-STATUS, QUOTA
- COMPRESS=DEFLATE, UTF8=ACCEPT, SORT, THREAD (ORDEREDSUBJECT / REFERENCES), STATUS=SIZE, OBJECTID, METADATA, NOTIFY (SELECTED-mailbox subset)
- Storage work on the pool; pipelined commands queued and answered in order
- Async client:
ImapClient+ImapFetch/ImapIdleauto-pilots; tag-correlated pipelining, STARTTLS/IMAPS, production IDLE
MQTT (hopf-mqtt)
- MQTT 3.1.1 full semantics plus a useful 5.0 core: wire properties, reason codes, Receive Maximum flow control, subscription options (No Local, Retain As Published, Retain Handling), Session Expiry
- QoS 0/1/2, retained messages, wills, topic wildcards, session takeover / resume
- Multi-reactor fan-out via
ConnHandle; stagedConnectHandlerSPI backed byCredentialStore - Async client:
MqttClient+MqttClientDrivercallbacks - Optional MQTT-over-WebSocket bridge (
websocketfeature) sharing broker state with the TCP listener
AMQP 0-9-1 (hopf-amqp)
- AMQP 0-9-1 async client (RabbitMQ wire protocol); client-only — no broker in this crate
- Connection handshake (
PLAIN/AMQPLAIN), tune negotiation, heartbeats - Multi-channel open/close; exchange / queue declare, bind, unbind, purge, delete
basic.publishwith streamed content frames; publisher confirms andbasic.returnbasic.consumepush deliveries (ack / nack / reject / qos)- AMQPS via implicit TLS on dial; DNS via
hopf-dns - Umbrella Cargo feature
amqp(hopf::amqp)
AMQP 1.0 (hopf-amqp1)
- AMQP 1.0 (ISO/IEC 19464) async client; separate crate from
hopf-amqp— shares only theAMQPwire magic, framing/types/session model are unrelated. Client-only — no broker - SASL PLAIN (when credentials configured) or ANONYMOUS, auto-negotiated
- Connection open, sessions (begin/end), sender/receiver links (attach/detach); session flow control and link credit
- Sending header/properties/application-properties/data, auto-split across
transferframes for large messages; receiving streamed incrementally as transfers arrive - Delivery settlement (accept/reject/release/modify) and outcome notifications
- AMQPS via implicit TLS on dial; DNS via
hopf-dns - Umbrella Cargo feature
amqp1(hopf::amqp1)
Mailbox (hopf-mailbox)
- IMAP-level storage SPI (wire server:
hopf-imap) - mbox and Maildir++ backends; flags, APPEND, SEARCH (RFC 9051 criteria)
- Optional body indexing (
.gidx); storage-pool helpers for search
Auth (hopf-auth)
- TrustPolicy / IdentityMaterial for listen and dial
- SASL: PLAIN, LOGIN, CRAM-MD5, DIGEST-MD5, SCRAM-SHA-256, OAUTHBEARER, EXTERNAL
- Planned: GSSAPI/Kerberos SASL (RFC 4752, Gumdrop parity) as optional feature
- HTTP Digest helpers; password / token / certificate stores for demos and wiring
Telemetry (hopf-otel)
- OpenTelemetry OTLP/HTTP (protobuf) and JSONL exporters
- Off-hot-path batch worker; HTTP Stream instrumentation wrapper
- W3C
traceparentinject / extract
Protocols at a glance
| Protocol | Crate | Server | Client | Notes |
|---|---|---|---|---|
| HTTP/1.x | hopf-http |
✓ | ✓ | Stream API |
| HTTP/2 | hopf-http |
✓ | ✓ | h2c + ALPN |
| HTTP/3 | hopf-http + hopf-quic |
✓ | ✓ | in-tree H3 |
| WebDAV | hopf-webdav |
✓ | — | on HTTP |
| WebSocket | hopf-websocket |
✓ | helpers | H1/H2/H3 upgrade |
| gRPC (unary) | hopf-grpc |
✓ | ✓ | on HTTP Streams |
| DNS | hopf-dns |
✓ | ✓ | stub + forwarder; DoT/DoQ/DoH (TCP TLS / QUIC); DoDTLS not wired |
| FTP / FTPS | hopf-ftp |
✓ | ✓ | callback-driven client |
| SMTP / SMTPS | hopf-smtp |
✓ | ✓ | callback-driven client |
| POP3 / POP3S | hopf-pop3 |
✓ | ✓ | callback-driven client (Pop3Fetch) |
| NNTP / NNTPS | hopf-nntp |
— | ✓ | callback-driven client (NntpSession) |
| IMAP / IMAPS | hopf-imap |
✓ | ✓ | pipelined client (ImapFetch / ImapIdle) |
| MQTT | hopf-mqtt |
✓ | ✓ | 3.1.1 + v5 core; optional WS bridge |
| AMQP 0-9-1 | hopf-amqp |
— | ✓ | client-only (RabbitMQ); AMQPS |
| AMQP 1.0 | hopf-amqp1 |
— | ✓ | client-only (ISO/IEC 19464); separate crate from hopf-amqp; AMQPS |
| LDAP | hopf-ldap |
— | ✓ | client-only; LDAPS/StartTLS; RFC 4533 content sync |
| Mailbox storage | hopf-mailbox |
SPI | — | mbox / Maildir++ |
| mDNS / DNS-SD | hopf-mdns |
✓ | ✓ | multicast UDP |
| MASQUE | hopf-masque |
✓ | ✓ | CONNECT-UDP full relay; CONNECT-IP is app-driven plumbing; H1/H2/H3 |
| SOCKS | hopf-socks |
✓ | ✓ | no RFC 1961 GSSAPI yet |
| QUIC | hopf-quic |
✓ | ✓ | Endpoint per stream; in-tree RFC 9000 transport, no external QUIC library |
| TLS / DTLS | hopf-core |
✓ | ✓ | in-tree TLS 1.2/1.3 and DTLS 1.2/1.3 on AWS-LC; TCP via hopf-core::tls PEM helpers + TcpListenerConfig / TcpConnectorConfig |
Feature manuals in the sidebar document RFCs, every configuration knob, handler SPIs, and examples. Start with Getting started or Architecture.