Skip to content

IFM Protocol Specification ​

Version ​

v0.1 Draft — This specification is a work in progress.


Overview ​

IFM is a packet-based broadcast protocol over a decentralized mesh network. Unlike streaming protocols, everything in IFM is represented as discrete packets with metadata. Applications needing continuous media (voice, video) send packets at regular intervals.

Key Properties ​

  • Binary format — Compact, fast serialization
  • Signed packets — Every packet authenticated via Ed25519
  • TTL-limited — Packets expire after 16 hops
  • Deduplicated — BLAKE3 packet IDs prevent replay
  • Transport-agnostic — Works over QUIC, WebRTC, TCP

Companion document: Station Discovery & Relay Protocol — how stations are announced/found and relays are scored/selected without a central server.


Wire Format ​

All packets use a binary encoding (bincode-compatible). The on-wire format:

Field Definitions ​

FieldTypeSizeDescription
versionu81 byteProtocol version (current: 1)
frequency[u8; 32]32 bytesBLAKE3 hash of canonical frequency identifier
packet_id[u8; 32]32 bytesBLAKE3 hash of entire packet (minus signature)
sender[u8; 32]32 bytesSender's Ed25519 public key
timestampu648 bytesUnix milliseconds since epoch
ttlu81 byteTime-to-live in hops (default: 16)
sequenceu648 bytesMonotonically increasing per-sender sequence
payload_typeu81 byteSee Payload Types table
payload_lengthu324 bytesLength of payload in bytes
payloadVec<u8>VariableEncrypted/compressed payload data
signature[u8; 64]64 bytesEd25519 signature over all above fields

Payload Types ​

ValueConstantDescription
0x00TEXTUTF-8 text message
0x01VOICEOpus-encoded audio frame (20ms)
0x02VIDEOVideo frame (codec indicated in payload)
0x03IMAGEImage data (format in payload header)
0x04FILEFile chunk (see File Transfer)
0x05JSONStructured JSON data
0x06PINGKeepalive / latency probe
0x07PRESENCEPresence update (join/leave/status)
0x08CONTROLProtocol control messages
0x09PLUGINPlugin-specific payload

Packet Types (Control Messages) ​

Control messages use payload_type = CONTROL (0x08) with a JSON payload:

json
{
  "type": "HELLO | WELCOME | JOIN | LEAVE | ANNOUNCE | PING | PONG",
  "data": { ... }
}

HELLO ​

Sent when tuning to a frequency to announce presence.

json
{
  "type": "HELLO",
  "data": {
    "node_id": "12D3KooW...",
    "display_name": "optional name",
    "capabilities": ["voice", "chat", "file"],
    "frequencies": ["91.700", "chat.general"]
  }
}

WELCOME ​

Response to HELLO from peers already on the frequency.

json
{
  "type": "WELCOME",
  "data": {
    "node_id": "12D3KooW...",
    "peer_count": 42,
    "frequency_metadata": {
      "name": "General Chat",
      "description": "Main discussion channel",
      "language": "en",
      "encryption": "none"
    }
  }
}

JOIN ​

Explicit join request (for protected/hidden frequencies).

json
{
  "type": "JOIN",
  "data": {
    "frequency": "private.team",
    "key_proof": "optional cryptographic proof of key possession"
  }
}

LEAVE ​

Graceful departure from a frequency.

json
{
  "type": "LEAVE",
  "data": {
    "frequency": "91.700",
    "reason": "user_left | timeout | error"
  }
}

ANNOUNCE ​

Frequency metadata broadcast (periodic or on change).

json
{
  "type": "ANNOUNCE",
  "data": {
    "frequency": "91.700",
    "metadata": {
      "name": "Music Lounge",
      "description": "Lo-fi beats",
      "listener_count": 128,
      "capabilities": ["voice", "music"]
    }
  }
}

PING / PONG ​

Latency measurement and keepalive.

json
{ "type": "PING", "data": { "timestamp": 1699999999999, "nonce": "abc123" } }
{ "type": "PONG", "data": { "original_timestamp": 1699999999999, "nonce": "abc123" } }

Packet ID Generation ​

packet_id = BLAKE3(
  version ||
  frequency ||
  sender ||
  timestamp ||
  ttl ||
  sequence ||
  payload_type ||
  payload_length ||
  payload
)

Properties:

  • Deterministic — same packet always produces same ID
  • Collision-resistant — 256-bit output
  • Enables duplicate detection without storing full packets
  • Used for deduplication cache keys

Packet Lifetime (TTL) ​

  • Initial TTL: 16 hops
  • Decrement: Each relay decrements by 1
  • Expiry: Packet discarded when TTL reaches 0
  • Purpose: Prevents infinite circulation, bounds network diameter

Broadcast Mechanism (GossipSub) ​

IFM uses libp2p GossipSub for mesh broadcast:

1. Node creates packet, signs it
2. Publishes to GossipSub topic = frequency hash
3. GossipSub delivers to mesh peers (fanout=6)
4. Each peer:
   a. Verifies signature (Ed25519)
   b. Checks TTL > 0
   c. Checks packet_id not in dedup cache
   d. Adds to local cache
   e. Forwards to its mesh peers (TTL - 1)
5. Recipients decode and deliver to application

GossipSub Parameters ​

ParameterValueDescription
fanout6Number of peers to forward to
mesh_n6Target mesh degree
mesh_n_low4Minimum mesh degree
mesh_n_high12Maximum mesh degree
gossip_factor0.25Percentage of mesh to gossip to

Frequency Resolution ​

Human Frequency → Topic ID ​

Frequency Types & Canonical Prefixes ​

TypePrefixExampleEncryption
Publicifm://public/ifm://public/91.700None
Protectedifm://protected/ifm://protected/team.alphaChaCha20-Poly1305
Hiddenifm://hidden/ifm://hidden/game.room.42ChaCha20-Poly1305

Serialization ​

Binary Encoding (bincode) ​

  • Little-endian
  • Fixed-size integers
  • Length-prefixed variable data
  • No schema in band — schema defined by protocol version

Example: Minimal TEXT Packet (hex) ​

01                                              # version = 1
abcdef... (32 bytes)                           # frequency hash
123456... (32 bytes)                           # packet_id
fedcba... (32 bytes)                           # sender public key
00 00 00 00 00 65 4a 8b                        # timestamp (little-endian u64)
10                                             # ttl = 16
00 00 00 00 00 00 00 01                        # sequence = 1
00                                             # payload_type = TEXT (0)
05 00 00 00                                    # payload_length = 5
48 65 6c 6c 6f                                 # payload = "Hello"
9a 8b 7c... (64 bytes)                         # Ed25519 signature

Versioning ​

  • version field in packet header
  • Current version: 1
  • Breaking changes increment version
  • Nodes MUST reject packets with unknown version
  • Forward compatibility: ignore unknown payload types

Error Handling ​

ConditionAction
Invalid signatureDrop packet, do not relay
TTL = 0Drop packet
Duplicate packet_idDrop packet (already in cache)
Unknown versionDrop packet
Payload too largeDrop packet (max 1MB default)
Decode failureDrop packet

Maximum Sizes ​

LimitValueRationale
Max packet size1 MBPrevents DoS, fits in MTU with fragmentation
Max payload size1 MB - overhead~1 MB for file chunks
Dedup cache100,000 entries~3.2 MB for packet IDs
Sequence window2^32 per senderWraparound handled by timestamp

Mermaid: Packet Flow ​

Released under the MIT License.