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.

Request and response flow

# 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:

FieldSize (bytes)Description
Bits 0..20b0000_0111File type (0-7)
Bit 30b0000_1000Compressed (1 = Zstd compressed)
Bit 40b0001_0000Encrypted (reserved for future use)
Bits 5..70b1110_0000Reserved (MUST be 0)

File Type Codes

FieldSize (bytes)Description
0PNG
1JPEGjpg/jpeg
2WebP
3BMP
4GIF
5-6Reserved
7UnknownUse 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

FieldSize (bytes)Description
Bit 0keep-alive1 = keep connection open after response
Bits 1-7reservedMUST be 0

LIST (ReqType = 1)

Request the catalog of available images.

FieldSize (bytes)Description
ReqType11 = LIST
RequestFlags1Flags (bit 0 = keep-alive)

GET_BY_ID (ReqType = 0)

Request specific images by their IDs. Count MUST NOT exceed 255.

FieldSize (bytes)Description
ReqType10 = GET_BY_ID
RequestFlags1Flags (bit 0 = keep-alive)
Count1Number of IDs (N), max 255
ImageID8 × NRequested image IDs (big-endian)

BATCH (ReqType = 2)

Delta sync: client sends the IDs it already has; server returns only the missing images.

FieldSize (bytes)Description
ReqType12 = BATCH
RequestFlags1Flags (bit 0 = keep-alive)
HaveCount1–5Have ID count (varint u32)
ImageID8 × NIDs 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.

FieldSize (bytes)Description
ReqType15 = LIST_AND_GET
RequestFlags1Flags (bit 0 = keep-alive)

# Responses

LIST Response (Header = JTPL)

FieldSize (bytes)Description
Header4ASCII "JTPL"
Count2Number of entries (u16)
EntriesvariableRepeated Count times

Each entry:

FieldSize (bytes)Description
ImageID8Image ID (u64, big-endian)
Flags1File type + feature flags
NameLen2Filename length (u16)
FilenameNameLenUTF-8 basename
Size1–5Data size (varint u32)

Image Packet

Used by GET_BY_ID, BATCH, and LIST_AND_GET responses.

FieldSize (bytes)Description
Flags1File type + feature flags
Length1–5Data length (varint u32)
ImageID8Image ID (u64, big-endian)
DataLengthRaw image bytes

Receivers SHOULD validate: ImageID == xxHash64(Data, seed=0) (after decompression if compressed).

BATCH Response (Header = JTPB)

FieldSize (bytes)Description
Header4ASCII "JTPB"
MissingCount1–5Missing image count (varint u32)
ImagesvariableRepeated MissingCount times (image packet)

LIST_AND_GET Response (Header = JTPG)

FieldSize (bytes)Description
Header4ASCII "JTPG"
Count2Number of images (u16)
ImagesvariableRepeated 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)

FieldSize (bytes)Description
Header4ASCII "JTPE"
ErrorCode1Error code
MessageLen2Length of message (u16)
MessageMessageLenUTF-8 error description

Error Codes

FieldSize (bytes)Description
1NotFoundRequested resource not found
2InvalidRequestMalformed or invalid request
3ServerErrorInternal server error
4UnsupportedFeatureFeature not supported by server
5RateLimitedRequest 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.