RTMP.Handshake (rtmp v0.1.0)

Copy Markdown View Source

The simple (non-digest) RTMP handshake, server side.

The client sends C0 (one version byte) and C1 (1536 bytes); the server answers with S0 and S1 as soon as C0 arrives, and S2 (an echo of C1) once C1 arrives; the client finishes with C2 (1536 bytes, an echo of S1). After C2 the connection speaks the chunk stream protocol.

S0/S1 are sent on C0 alone rather than waiting for C1 — the spec allows either, and answering early means a client that waits for S1 before sending C1 can't deadlock against us.

Only the simple handshake is supported. The HMAC "digest" handshake used by some Flash-era clients is not — modern encoders (OBS, FFmpeg, vMix, hardware encoders) use the simple one. Encrypted RTMPE (version byte 6) is rejected.

This module is a pure state machine: feed it bytes with feed/2, send whatever it hands back, and stop once it returns {:done, ...}. Timeouts are the caller's job (RTMP.Connection applies one per step).

Summary

Types

Which client message the server is currently waiting for.

t()

Functions

Feeds received bytes into the handshake.

Size in bytes of C1, C2, S1 and S2.

Types

step()

@type step() :: :c0 | :c1 | :c2

Which client message the server is currently waiting for.

t()

@type t() :: %RTMP.Handshake{buffer: binary(), step: step()}

Functions

feed(hs, data)

@spec feed(t(), binary()) ::
  {:more, t(), iodata()} | {:done, binary(), iodata()} | {:error, term()}

Feeds received bytes into the handshake.

Returns:

  • {:more, hs, to_send} — need more bytes; send to_send (may be empty).
  • {:done, rest, to_send} — handshake complete; rest is any data that arrived after C2 and belongs to the chunk stream.
  • {:error, reason} — the client sent something that isn't a valid simple handshake.

new()

@spec new() :: t()

packet_size()

@spec packet_size() :: pos_integer()

Size in bytes of C1, C2, S1 and S2.