Jason Transfer Protocol — JTP/1.0
January 24, 2026
Jason Transfer Protocol ("JTP") is a compact binary request/response protocol for listing and transferring images over TCP (optionally TLS), keyed by xxHash64-derived IDs.
# Abstract
JTP is a lightweight binary protocol for fast image distribution. A client first discovers available content with a catalog request (LIST), then requests one or more images by their content-derived identifiers (GET_BY_ID). Images are addressed by the first 8 bytes of xxHash64 over the file bytes, enabling deduplication and integrity checks; optional TLS provides confidentiality on the wire.
# Transport
JTP requires an ordered, reliable byte stream transport.
- The default transport is TCP.
- JTP may be wrapped in TLS to provide confidentiality and integrity.
- The reference server listens on 0.0.0.0:8443.
TLS and ALPN
- When TLS is used, servers MAY advertise ALPN protocol identifier: jtp/1
- Clients that support ALPN SHOULD offer jtp/1.
- JTP does not define certificate distribution. Deployments may use self-signed certificates, a local CA, or public PKI.
Keep-Alive
JTP supports connection reuse through a keep-alive mechanism. When enabled, multiple requests can be sent over a single connection, avoiding repeated TLS handshakes.
- If the keep-alive flag is set in a request, the server SHOULD keep the connection open after sending the response.
- If the flag is not set, the server SHOULD close the connection after the response.
- Servers MAY implement idle timeouts to close stale keep-alive connections.
- Clients MUST handle server-initiated connection closes gracefully.
# ImageID
ImageID is a 64-bit value computed from the raw image file bytes:
ImageID = xxHash64(image_bytes, seed = 0)
On the wire, ImageID is transmitted as u64 big-endian. When rendered as hex, the recommended representation is the hex encoding of the 8 big-endian bytes.
# Flags
JTP uses a one-byte Flags field with the following bit assignments:
| Field | Size (bytes) | Description |
|---|---|---|
| Bits 0..2 | 0b0000_0111 | File type (0-7) |
| Bit 3 | 0b0000_1000 | Compressed (1 = Zstd compressed) |
| Bit 4 | 0b0001_0000 | Encrypted (reserved for future use) |
| Bits 5..7 | 0b1110_0000 | Reserved (MUST be 0) |
File Type Codes
| Field | Size (bytes) | Description |
|---|---|---|
| 0 | PNG | |
| 1 | JPEG | jpg/jpeg |
| 2 | WebP | |
| 3 | BMP | |
| 4 | GIF | |
| 5-6 | Reserved | |
| 7 | Unknown | Use for unknown types |
Compression
When bit 3 is set, the image data is Zstd compressed. Receivers MUST decompress before use. If a receiver does not support compression, it SHOULD fail the request rather than misinterpreting bytes.
# Requests
The first byte of every request is ReqType (u8). For requests that support connection reuse, the second byte is RequestFlags (u8).
Request Flags
| Field | Size (bytes) | Description |
|---|---|---|
| Bit 0 | keep-alive | 1 = keep connection open after response |
| Bits 1-7 | reserved | MUST be 0 |
LIST (ReqType = 1)
Request the catalog of available images.
| Field | Size (bytes) | Description |
|---|---|---|
| ReqType | 1 | 1 = LIST |
| RequestFlags | 1 | Flags (bit 0 = keep-alive) |
GET_BY_ID (ReqType = 0)
Request specific images by their IDs. Count MUST NOT exceed 255.
| Field | Size (bytes) | Description |
|---|---|---|
| ReqType | 1 | 0 = GET_BY_ID |
| RequestFlags | 1 | Flags (bit 0 = keep-alive) |
| Count | 1 | Number of IDs (N), max 255 |
| ImageID | 8 × N | Requested image IDs (big-endian) |
BATCH (ReqType = 2)
Delta sync: client sends the IDs it already has; server returns only the missing images.
| Field | Size (bytes) | Description |
|---|---|---|
| ReqType | 1 | 2 = BATCH |
| RequestFlags | 1 | Flags (bit 0 = keep-alive) |
| HaveCount | 1–5 | Have ID count (varint u32) |
| ImageID | 8 × N | IDs the client already has |
LIST_AND_GET (ReqType = 5)
Combined catalog listing and image transfer in a single round-trip. Server responds with all available images.
| Field | Size (bytes) | Description |
|---|---|---|
| ReqType | 1 | 5 = LIST_AND_GET |
| RequestFlags | 1 | Flags (bit 0 = keep-alive) |
# Responses
LIST Response (Header = JTPL)
| Field | Size (bytes) | Description |
|---|---|---|
| Header | 4 | ASCII "JTPL" |
| Count | 2 | Number of entries (u16) |
| Entries | variable | Repeated Count times |
Each entry:
| Field | Size (bytes) | Description |
|---|---|---|
| ImageID | 8 | Image ID (u64, big-endian) |
| Flags | 1 | File type + feature flags |
| NameLen | 2 | Filename length (u16) |
| Filename | NameLen | UTF-8 basename |
| Size | 1–5 | Data size (varint u32) |
Image Packet
Used by GET_BY_ID, BATCH, and LIST_AND_GET responses.
| Field | Size (bytes) | Description |
|---|---|---|
| Flags | 1 | File type + feature flags |
| Length | 1–5 | Data length (varint u32) |
| ImageID | 8 | Image ID (u64, big-endian) |
| Data | Length | Raw image bytes |
Receivers SHOULD validate: ImageID == xxHash64(Data, seed=0) (after decompression if compressed).
BATCH Response (Header = JTPB)
| Field | Size (bytes) | Description |
|---|---|---|
| Header | 4 | ASCII "JTPB" |
| MissingCount | 1–5 | Missing image count (varint u32) |
| Images | variable | Repeated MissingCount times (image packet) |
LIST_AND_GET Response (Header = JTPG)
| Field | Size (bytes) | Description |
|---|---|---|
| Header | 4 | ASCII "JTPG" |
| Count | 2 | Number of images (u16) |
| Images | variable | Repeated Count times (image packet) |
# Error Handling
JTP defines an optional structured error response for servers that wish to provide detailed error information.
ERROR Response (Header = JTPE)
| Field | Size (bytes) | Description |
|---|---|---|
| Header | 4 | ASCII "JTPE" |
| ErrorCode | 1 | Error code |
| MessageLen | 2 | Length of message (u16) |
| Message | MessageLen | UTF-8 error description |
Error Codes
| Field | Size (bytes) | Description |
|---|---|---|
| 1 | NotFound | Requested resource not found |
| 2 | InvalidRequest | Malformed or invalid request |
| 3 | ServerError | Internal server error |
| 4 | UnsupportedFeature | Feature not supported by server |
| 5 | RateLimited | Request rate limit exceeded |
Servers may also signal errors by closing the connection or terminating the TLS session. Clients should treat unexpected EOF, invalid headers, or decoding errors as request failure.
# Limits
- Maximum single image size: 4 GiB - 1 (u32 framing)
- Maximum images per LIST: 65,535 (u16 count)
- Maximum GET_BY_ID count: 255 (u8 count)
- Servers SHOULD reject BATCH requests with HaveCount exceeding 1,000,000
# Examples
Hex dumps are spaced by byte. Fixed-width integers are big-endian; sizes/lengths use unsigned LEB128 varints.
LIST request (with keep-alive)
01 01
- 01 = ReqType (LIST)
- 01 = RequestFlags (keep-alive=1)
LIST response (Count = 1)
4A 54 50 4C 00 01 AA BB CC DD EE FF 00 11 01 00 09 6A 61 73 6F 6E 31 2E 6A 70 67 B4 24
- JTPL header, Count=1
- Entry: ImageID(8) + Flags(01=jpg) + NameLen(9)
- Filename 'jason1.jpg' + Size(0x00001234 varint)
GET_BY_ID request (Count = 1)
00 00 01 AA BB CC DD EE FF 00 11
- 00 = ReqType (GET_BY_ID)
- 00 = RequestFlags (no keep-alive)
- 01 = Count
- 8 bytes of ImageID
Image packet response
01 04 AA BB CC DD EE FF 00 11 DE AD BE EF
- Flags(01=jpg) + Length(4 varint)
- ImageID echoes the requested ID (8 bytes)
- 4 bytes of file data (example)
ERROR response
4A 54 50 45 02 00 0F 49 6E 76 61 6C 69 64 20 72 65 71 75 65 73 74
- JTPE header + ErrorCode(2=InvalidRequest) + MessageLen(15)
- Message: "Invalid request"
# Security Considerations
- Use TLS to prevent passive observation and active tampering.
- ImageID is content-derived and can be used to validate integrity, but it is not a cryptographic MAC.
- Servers should validate and cap counts/sizes to mitigate denial-of-service.