uRPC is a minimal binary RPC protocol designed for high-performance async runtimes (uvent). It uses a compact big-endian header and fully supports multiplexing: many concurrent RPCs over a single connection.
Every message on the wire is a Frame:
+-------------------+-----------------------------+
| Header (fixed) | Payload (binary, length N) |
+-------------------+-----------------------------+
Size: 28 bytes
Byte order: Big-Endiann
Layout:
uint32 magic // 'URPC' = 0x55525043
uint8 version // protocol version, currently 1
uint8 type // frame type (see FrameType table)
uint16 flags // bitmask (END_STREAM, ERROR, COMPRESSED, …)
uint32 reserved // must be 0; reserved for future protocol extensions
uint32 stream_id // logical RPC stream ID
uint64 method_id // FNV1a64("Service.Method")
uint32 length // payload size in bytes
The reserved field is included in the header but is not used by the current
protocol version. Implementations MUST send it as zero and MUST ignore its value
when receiving.
Important:
TLS/mTLS encrypt the transport stream, but the protocol header is still parsed
normally because OpenSSL decrypts before delivering bytes to async_read.
App-level AES (if enabled) encrypts only the payload, never the header.
0 = Request
1 = Response
2 = Stream // reserved for future streaming
3 = Cancel
4 = Ping
5 = Pong
| Type | Name | Direction | Description |
|---|---|---|---|
| 0 | Request | C → S | RPC request |
| 1 | Response | S → C | RPC response |
| 2 | Stream | S → C | Streaming chunk (reserved) |
| 3 | Cancel | C → S | Cooperative cancellation |
| 4 | Ping | C ↔ S | Health check |
| 5 | Pong | C ↔ S | Health check response |
flags is a bitmask:
0x01—END_STREAM0x02—ERROR0x04—COMPRESSED0x08—TLS(transport is TLS)0x10—MTLS(mutual TLS)0x20—ENCRYPTED(payload encrypted with app-level AES)
Rules:
- Request frames MUST NOT set
ERROR. - Response frames MUST set
ERRORwhen they carry an error payload. - AES and TLS flags never imply header encryption — only payload (AES) or entire transport (TLS).
- Client opens a connection (TCP or TLS/mTLS).
- Client sends a Request with unique
stream_idandmethod_id. - Server dispatches to registered handler.
- Handler returns a binary vector.
- Server sends Response with same
stream_id. - Client matches by
stream_id.
Multiplexing allows many in-flight RPCs on one connection.
Errors are encoded as binary payloads.
+-----------------------+-----------------------+---------------------------+
| uint32 code (BE) | uint32 msg_len (BE) | msg[msg_len] | details[] |
+-----------------------+-----------------------+---------------------------+
If ERROR flag is set:
- client marks call as failed,
- extracts code/message,
- the returned vector is empty.
Used for liveness checks.
Ping:
type = 4
flags = END_STREAM
stream_id = non-zero
length = 0
Pong:
type = 5
flags = END_STREAM
stream_id = same as Ping
length = 0
0is reserved- client allocates increasing non-zero IDs
- response must reuse request's ID
- stream closes on END_STREAM
64-bit FNV1a:
uint64_t id = urpc::method_id("Example.Echo");Compile-time:
server.register_method_ct<urpc::method_id("Example.Echo")>(handler);Enabling TLS/mTLS is purely a transport decision:
- framing stays the same
- header remains plaintext at the protocol level
- OpenSSL decrypts before
async_read - handler logic unchanged
mTLS additionally verifies client certificates.
If enabled (both sides agree):
- a per-connection AES-256-GCM key is derived via TLS exporter
- payload is replaced by:
IV[12] + ciphertext[N] + TAG[16]
- header is never encrypted
- flags include
ENCRYPTED
AES works on top of TLS or plain TCP (if you provide your own key).
urpc_cli --host 127.0.0.1 --port 45900 --method Example.Echo --data "hello"TLS:
urpc_cli --tls --tls-ca ca.crt \
--tls-server-name localhost \
--host 127.0.0.1 --port 45900 \
--method Example.Echo --data "hi"mTLS:
urpc_cli --tls \
--tls-ca ./ca.crt \
--tls-cert ./client.crt \
--tls-key ./client.key \
--tls-server-name localhost \
--method Example.Echo \
--data "hello secure"AES:
urpc_cli --aes --aes-key hex:001122334455...Payload is opaque and length-prefixed:
- JSON
- Protobuf
- MsgPack
- custom binary formats
uRPC is distributed under the MIT license