RTMP.AMF0 (rtmp v0.1.0)

Copy Markdown View Source

AMF0 encoding and decoding.

RTMP command messages (connect, publish, ...) and data messages (onMetaData) are sequences of AMF0 values.

Value mapping

AMF0 typeElixir (decoded)Encoded from
Numberfloat, or :nan / :infinity / :neg_infinityinteger, float, those atoms
Booleantrue / falsetrue / false
Stringbinarybinary shorter than 64 KiB
Long Stringbinarybinary of 64 KiB or more
Objectmap with binary keysmap (atom or binary keys)
ECMA Arraymap with binary keys{:ecma_array, map}
Strict Arraylistlist
Nullnilnil
Undefined:undefined:undefined
DateDateTime (millisecond precision, UTC)DateTime
Typed Object{:typed_object, class, map}same
XML Document{:xml, binary}same
Reference{:reference, index}same
Unsupported:unsupported:unsupported

Objects and ECMA arrays both decode to plain maps, so the distinction is lost on a round trip; encode a map as {:ecma_array, map} when the receiver needs an ECMA array (FLV onMetaData, for example).

NaN and the infinities can't be represented as BEAM floats, so they decode to atoms instead of failing — some encoders really do send them in metadata.

Robustness

Decoding never raises on malformed input; it returns {:error, reason}. Nesting deeper than 64 levels is rejected, so hostile input can't drive unbounded recursion. AMF3 values (the AVM+ switch marker) are not supported and decode to an error.

Summary

Functions

Decodes one AMF0 value from the front of binary.

Decodes every AMF0 value in binary, which must contain nothing else.

Encodes one value. Raises ArgumentError for terms with no AMF0 mapping — encoding is only ever done on your own data, never on network input.

Encodes a list of values back to back, the way command messages are laid out.

Maximum nesting depth accepted when decoding.

Types

value()

@type value() ::
  float()
  | :nan
  | :infinity
  | :neg_infinity
  | boolean()
  | binary()
  | map()
  | list()
  | nil
  | :undefined
  | :unsupported
  | DateTime.t()
  | {:ecma_array, map()}
  | {:typed_object, binary(), map()}
  | {:xml, binary()}
  | {:reference, non_neg_integer()}

Functions

decode(binary)

@spec decode(binary()) :: {:ok, value(), binary()} | {:error, term()}

Decodes one AMF0 value from the front of binary.

Returns {:ok, value, rest} or {:error, reason}.

decode_all(binary)

@spec decode_all(binary()) :: {:ok, [value()]} | {:error, term()}

Decodes every AMF0 value in binary, which must contain nothing else.

encode(value)

@spec encode(value()) :: binary()

Encodes one value. Raises ArgumentError for terms with no AMF0 mapping — encoding is only ever done on your own data, never on network input.

encode_all(values)

@spec encode_all([value()]) :: binary()

Encodes a list of values back to back, the way command messages are laid out.

max_depth()

@spec max_depth() :: pos_integer()

Maximum nesting depth accepted when decoding.