Network Working Group M. Thornburgh
Internet-Draft Adobe
Intended status: Informational January 4, 2013
Expires: July 8, 2013
Adobe's Secure Real-Time Media Flow Protocoldraft-thornburgh-adobe-rtmfp-01
Abstract
This memo describes the Secure Real-Time Media Flow Protocol (RTMFP),
an endpoint-to-endpoint communication protocol designed to securely
transport parallel flows of real-time video, audio, and data
messages, as well as bulk data, over IP networks. RTMFP has features
making it effective for peer-to-peer (P2P) as well as client-server
communications, even when Network Address Translators (NATs) are
used.
Status of this Memo
This Internet-Draft is submitted in full conformance with the
provisions of BCP 78 and BCP 79. This document may not be modified,
and derivative works of it may not be created, except to format it
for publication as an RFC or to translate it into languages other
than English.
Internet-Drafts are working documents of the Internet Engineering
Task Force (IETF). Note that other groups may also distribute
working documents as Internet-Drafts. The list of current Internet-
Drafts is at http://datatracker.ietf.org/drafts/current/.
Internet-Drafts are draft documents valid for a maximum of six months
and may be updated, replaced, or obsoleted by other documents at any
time. It is inappropriate to use Internet-Drafts as reference
material or to cite them other than as "work in progress."
This Internet-Draft will expire on July 8, 2013.
Copyright Notice
Copyright (c) 2013 IETF Trust and the persons identified as the
document authors. All rights reserved.
This document is subject to BCP 78 and the IETF Trust's Legal
Provisions Relating to IETF Documents
(http://trustee.ietf.org/license-info) in effect on the date of
publication of this document. Please review these documents
Thornburgh Expires July 8, 2013 [Page 1]

Internet-Draft Adobe RTMFP January 20131. Introduction
Adobe's Secure Real-Time Media Flow Protocol (RTMFP) is intended for
use as an endpoint-to-endpoint data transport service in IP networks.
It has features that make it well suited to the transport of real-
time media (such as low-delay video, audio, and data) as well as bulk
data, and for client-server as well as peer-to-peer (P2P)
communication. These features include independent parallel message
flows which may have different delivery priorities, variable message
reliability (from TCP-like full reliability to UDP-like best effort),
multi-point congestion control, and built-in security. Session
multiplexing and facilities to support UDP hole-punching simplify
Network Address Translator (NAT) traversal in peer-to-peer systems.
This memo describes the syntax and operation of the Secure Real-Time
Media Flow Protocol.
1.1. Design Highlights of RTMFP
o The security framework is an in-band part of the basic protocol
and is always on. The application designer chooses the
cryptographic formats and algorithms to suit the needs of the
application, and may update them as the state of the security arts
progresses.
o Cryptographic Endpoint Discriminators can resist port scanning.
o All header, control, and framing information, except for network
addressing information and a session identifier, is encrypted.
o There is a single session and associated congestion control state
between a pair of endpoints.
o Each session may have zero or more unidirectional message-oriented
flows in each direction. All of a session's sending flows share
the session's congestion control state.
o Return Flow Association (Section 2.3.11.1.2) generalizes
bidirectional communication to arbitrarily complex trees of flows.
o Messages in flows can be arbitrarily large and are fragmented for
transmission.
o Messages of any size may be sent with full, partial, or no
reliability (sender's choice). Messages may be delivered to the
receiving user in original queuing order or network arrival order
(receiver's choice).
Thornburgh Expires July 8, 2013 [Page 5]

Internet-Draft Adobe RTMFP January 2013
o Flows are named with arbitrary, user-defined metadata
(Section 2.3.11.1.1) rather than port or stream numbers.
o The sequence numbers of each flow are independent of all other
flows, and are not permanently bound to a session-wide
transmission ordering. This allows real-time priority decisions
to be made at transmission or retransmission time.
o Each flow has its own receive window, and therefore independent
flow control.
o Round-trips are expensive, and are minimized or eliminated when
possible.
o After a session is established, flows begin by sending the flow's
messages with no additional handshake (and associated round-
trips).
o Transmitting bytes on the network is much more expensive than
moving bytes in a CPU or memory. Wasted bytes are minimized or
eliminated when possible and practical, and variable length
encodings are used, even at the expense of breaking 32-bit
alignment and making the text diagrams in this specification look
awkward.
o P2P lookup and peer introduction (including UDP hole punching for
NAT and firewall traversal) is supported directly by the session
startup handshake.
o Session identifiers allow an endpoint to multiplex many sessions
over a single local transport address while allowing sessions to
survive changes in transport address (as may happen in mobile or
wireless deployments).
1.2. Terminology
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
"SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
"OPTIONAL" in this memo are to be interpreted as described in
[RFC2119].
2. Syntax
Definitions of types and structures in this specification use
traditional text diagrams paired with procedural descriptions using a
C-like syntax.
Thornburgh Expires July 8, 2013 [Page 6]

Internet-Draft Adobe RTMFP January 20132.1. Common Elements
This section lists types and structures that are used throughout this
specification.
2.1.1. Elementary Types and Constructs
This section lists the elementary types and constructs out of which
all of the following sections' definitions are built.
uint8_t var;
An unsigned integer 8 bits (one byte) in length and byte aligned.
uint16_t var;
An unsigned integer 16 bits in length, in network byte order ("big
endian") and byte aligned.
uint32_t var;
An unsigned integer 32 bits in length, in network byte order and byte
aligned.
uint128_t var;
An unsigned integer 128 bits in length, in network byte order and
byte aligned.
uintn_t var :bitsize;
An unsigned integer of any other size, potentially not byte aligned.
Its size in bits is specified explicitly by bitsize.
bool_t var :1;
A boolean flag having the value true (set) or false (clear) and being
one bit in length.
type var[num];
A packed array of type with length num*sizeof(type)*8 bits.
struct name_t { ... } name :bitsize;
A packed structure. Its size in bits is specified by bitsize.
Thornburgh Expires July 8, 2013 [Page 7]

Internet-Draft Adobe RTMFP January 2013
remainder();
The number of bytes from the current offset to the end of the
enclosing structure.
type var[remainder()];
A packed array of type, its size extending to the end of the
enclosing structure.
Note that a bitsize of "variable" indicates that the size of the
structure is determined by the sizes of its interior components. A
bitsize of "n*8" indicates that the size of the structure is a whole
number of bytes and is byte aligned.
2.1.2. Variable Length Unsigned Integer (VLU)
A VLU encodes any finite non-negative integer into one or more bytes.
For each encoded byte, if the high bit is set, the next byte is also
part of the VLU. If the high bit is clear, this is the final byte of
the VLU. The remaining bits encode the number, seven bits at a time,
from most significant to least significant.
0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7
+~+~+~+~+~+~+~+~+ +-+-+-+-+-+-+-+-+
|1| digit |...............|0| digit |
+~+~+~+~+~+~+~+~+ +-+-+-+-+-+-+-+-+
^ ^
+--------- zero or more --------+
struct vlu_t
{
value = 0;
do {
bool_t more :1;
uintn_t digit :7;
value = (value * 128) + digit;
} while(more);
} :variable*8;
+-------------/-+
| \ |
+-------------/-+
VLU depiction in following figures
Unless stated otherwise in this specification, implementations SHOULD
Thornburgh Expires July 8, 2013 [Page 8]

Internet-Draft Adobe RTMFP January 2013
handle VLUs encoding values with at least 64 significant bits.
2.1.3. Option
An Option is a Length-Type-Value triplet. Length and Type are
encoded in VLU format. Length is the number of bytes of payload
following the Length field. The payload comprises the Type and Value
fields. Type identifies the kind of option this is. The syntax of
the Value field is determined by the type of option.
An option may have a length of zero, in which case it has no type and
no value and is empty. An empty option is called a "Marker".
+-------------/-+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| length \ | type \ | value |
+-------------/-+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
^ ^
+-------- length bytes long (may be 0) ---------+
struct option_t
{
vlu_t length :variable*8; // "L"
if(length > 0)
{
struct {
vlu_t type :variable*8; // "T"
uint8_t value[remainder()]; // "V"
} payload :length*8;
}
} :variable*8;
+---/---/-------+
| L \ T \ V |
+---/---/-------+
Option depiction in following figures
2.1.4. Option List
An Option List is a sequence of zero or more non-empty Options
terminated by a Marker.
Thornburgh Expires July 8, 2013 [Page 9]

Internet-Draft Adobe RTMFP January 2013
origin : The origin tag of this address. Possible values are:
0 : Unknown, unspecified, or "other"
1 : Address was reported by the origin as a local, directly-
attached interface address
2 : Address was derived by observation of the source of received
packets
3 : Address is a relay, proxy, or introducer (a Redirector and/or
Forwarder)
ipAddress : The Internet address, in network byte order.
port : The 16 bit port number, in network byte order.
2.2. Network Layer2.2.1. Encapsulation
RTMFP Multiplex packets are usually carried in UDP [RFC0768]
datagrams so that they may transit commonly deployed NATs and
firewalls, and so that RTMFP may be implemented on commonly deployed
operating systems without special privileges or permissions.
RTMFP Multiplex packets MAY be carried by any suitable datagram
transport or encapsulation where endpoints are addressed by an
Internet socket address (that is, an IPv4 or IPv6 address and a 16-
bit port number).
The choice of port numbers is not mandated by this specification.
Higher protocol layers or the application define the port numbers
used.
Thornburgh Expires July 8, 2013 [Page 11]

Internet-Draft Adobe RTMFP January 20132.2.3. Encryption
RTMFP packets are encrypted according to a Cryptography Profile.
This specification doesn't mandate a particular choice of
cryptography. The application defines the cryptographic syntax and
algorithms.
Packet encryption SHOULD be a block cipher operating in CBC (or
similar) mode. Encrypted packets MUST be decipherable without inter-
packet dependency, since packets may be lost, duplicated, or
reordered in the network.
The packet encryption layer is responsible for data integrity and
authenticity, for example by means of a checksum or cryptographic
message authentication code.
Note that the structures described below are of plain, unencrypted
packets. Encrypted packets MUST be decrypted according to the
Session Key associated with the Multiplex Session ID before being
interpreted according to this specification.
The cryptography profile defines a well-known Default Session Key
that is used at session startup, during which per-session key(s) are
negotiated by the two endpoints. A Session ID of zero denotes use of
the Default Session Key. The Default Session Key is also used with
non-zero Session IDs during the latter phases of session startup
(Section 2.3.6, Section 2.3.8).
2.2.4. Packet
An (unencrypted, plain) RTMFP Packet consists of a variable sized
common header, zero or more chunks, and padding. Padding MAY be
inserted by the encryption layer of the sender to meet cipher block
size constraints, and is ignored by the receiver. A sender's
encryption layer MAY pad the end of a packet with bytes with value
0xff such that the resulting packet is a natural and appropriate size
for the cipher. Alternatively, the Cryptography Profile MAY define
its own framing and padding scheme, if needed, such that decrypted
packets are compatible with the syntax defined in this section.
Thornburgh Expires July 8, 2013 [Page 13]

Internet-Draft Adobe RTMFP January 2013
timeCritical : Time Critical Forward Notification. If set,
indicates that this packet contains real-time user data.
timeCriticalReverse : Time Critical Reverse Notification. If set,
indicates that the sender is currently receiving packets on other
sessions that have the timeCritical flag set.
timestampPresent : If set, indicates that the timestamp field is
present. If clear, there is no timestamp field.
timestampEchoPresent : If set, indicates that the timestamp echo
field is present. If clear, there is no timestamp echo field.
mode : The mode of this packet. Values are:
0 : Forbidden value
1 : Initiator Mark
2 : Responder Mark
3 : Startup
timestamp : If the timestampPresent flag is set, this field is
present and contains the low 16 bits of the sender's 250 Hz clock
(4 milliseconds per tick) at transmit time. The sender's clock
MAY have its origin at any time in the past.
timestampEcho : If the timestampEchoPresent flag is set, this field
is present and contains the sender's estimate of what the
timestamp field of a packet received from the other end would be
at the time this packet was transmitted, using the method
described in Section 3.5.2.1.
chunks : Zero or more chunks follow the header. A packet SHOULD
contain at least one chunk.
padding : Zero or more bytes of padding follow the chunks. The
following conditions indicate padding:
* Fewer than three bytes (the size of a chunk header) remain in
the packet.
* The chunkLength field of the current chunk indicates that the
chunk payload wouldn't fit in the remaining bytes of the
packet.
Packet mode 0 is not allowed. Packets marked with this mode are
Thornburgh Expires July 8, 2013 [Page 15]

Internet-Draft Adobe RTMFP January 2013
invalid and MUST be discarded.
The original initiator of a session MUST mark all non-startup packets
it sends in that session with packet mode 1 "Initiator Mark". It
SHOULD ignore any packet received in that session with packet mode 1.
The original responder of a session MUST mark all non-startup packets
it sends in that session with packet mode 2 "Responder Mark". It
SHOULD ignore any packet received in that session with packet mode 2.
Packet mode 3 is for session startup. Session startup chunks MUST
ONLY be in packets with this mode.
Chunks that are not for session startup MUST ONLY be in packets with
modes 1 or 2.
2.3. Chunks
0 1 2
0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5|6 7 8 9 0 1 2 3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| chunkType | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| chunkPayload (chunkLength bytes, may be zero) |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct chunk_t
{
uint8_t chunkType;
uint16_t chunkLength;
uint8_t chunkPayload[chunkLength];
} :variable*8;
chunkType : The chunk type code.
chunkLength : The size, in bytes, of the chunk payload.
chunkPayload : The type-specific payload of this chunk, chunkLength
bytes in length (may be empty).
The following chunk type codes are defined:
0x7f : Packet Fragment (Section 2.3.1)
Thornburgh Expires July 8, 2013 [Page 16]

Internet-Draft Adobe RTMFP January 2013
segments that do not exceed the path MTU, and to allow the segments
to be sent through the network at a moderated rate to avoid jamming
interfaces, links, or paths.
0 1 2
0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5|6 7 8 9 0 1 2 3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x7f | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-------------/-+-------------/-+
|M| reserved | packetID \ | fragmentNum \ |
+-+-+-+-+-+-+-+-+-------------/-+-------------/-+
+---------------------------------------------------------------+
| packetFragment |
+---------------------------------------------------------------/
struct fragmentChunkPayload_t
{
bool_t moreFragments :1; // M
uintn_t reserved :7;
vlu_t packetID :variable*8;
vlu_t fragmentNum :variable*8;
uint8_t packetFragment[remainder()];
} :chunkLength*8;
moreFragments : If set, the indicated packet comprises additional
fragments. If clear, this fragment is the final fragment of the
packet.
reserved : Reserved for future use.
packetID : VLU, the identifier of this segmented packet. All
fragments of the same packet have the same packetID.
fragmentNum : VLU, the index of this fragment of the indicated
packet. The first fragment of the packet has index 0. Fragments
are numbered consecutively.
packetFragment : The bytes of the indicated segment of the indicated
original plain RTMFP packet. A packetFragment MUST NOT be empty.
The use of this mechanism is detailed in Section 3.4.
2.3.2. Initiator Hello Chunk (IHello)
This chunk is sent by the initiator of a new session to begin the
startup handshake. This chunk MUST ONLY be in a packet with Session
ID 0, encrypted with the default session key, and having packet mode
Thornburgh Expires July 8, 2013 [Page 18]

Internet-Draft Adobe RTMFP January 2013
3 (Startup).
0 1 2
0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5|6 7 8 9 0 1 2 3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x30 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| epdLength \ | endpointDiscriminator (epdLength bytes) |
+-------------/-+-----------------------------------------------/
+---------------------------------------------------------------+
| tag |
+---------------------------------------------------------------/
struct ihelloChunkPayload_t
{
vlu_t epdLength :variable*8;
uint8_t endpointDiscriminator[epdLength];
uint8_t tag[remainder()];
} :chunkLength*8;
epdLength : VLU, the length of the following endpointDiscriminator
field in bytes.
endpointDiscriminator : The Endpoint Discriminator for the identity
with which the initiator wants to communicate.
tag : Initiator-provided data to be returned in a Responder Hello's
tagEcho field. The tag/tagEcho is used to match Responder Hellos
to the initiator's session startup state independent of the
responder's address.
The use of IHello is detailed in Section 3.5.1.
2.3.3. Forwarded Initiator Hello Chunk (FIHello)
This chunk is sent on behalf of an initiator by a Forwarder. It MUST
ONLY be sent in an established session having packet mode 1 or 2. A
receiver MAY treat this chunk as though it was an Initiator Hello
received directly from replyAddress. Alternatively, if the receiver
is selected by the Endpoint Discriminator, it MAY respond to
replyAddress with an Implied Redirect (Section 2.3.5).
Thornburgh Expires July 8, 2013 [Page 19]

Internet-Draft Adobe RTMFP January 2013
The use of Redirect is detailed in Section 3.5.1.4.
2.3.6. RHello Cookie Change Chunk
This chunk MAY be sent by a responder to an initiator in response to
an Initiator Initial Keying if that chunk's cookie appears to have
been created by the responder but the cookie is incorrect (for
example, it includes a hash of the initiator's address, but the
initiator's address is different than the one which elicited the
Responder Hello containing the original cookie).
This chunk MUST ONLY be sent in a packet encrypted with the default
session key and having packet mode 3, and with the Session ID
indicated in the initiatorSessionID field of the Initiator Initial
Keying to which this is a response.
0 1 2
0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5|6 7 8 9 0 1 2 3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x79 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+-----------------------------------------------+
| oldCookieLen\ | oldCookie (oldCookieLen bytes) |
+-------------/-+-----------------------------------------------/
+---------------------------------------------------------------+
| newCookie |
+---------------------------------------------------------------/
struct rhelloCookieChangeChunkPayload_t
{
vlu_t oldCookieLen :variable*8;
uint8_t oldCookie[oldCookieLen];
uint8_t newCookie[remainder()];
} :chunkLength*8;
oldCookieLen : VLU, the length of the following oldCookie field in
bytes.
oldCookie : The cookie that was sent in a previous Responder Hello
and Initiator Initial Keying.
newCookie : The new cookie that the responder would like sent (and
signed) in a replacement Initiator Initial Keying. The old and
new cookies need not have the same lengths.
On receipt of this chunk, the initiator SHOULD compute, sign, and
send a new Initiator Initial Keying having newCookie in place of
oldCookie. The use of this chunk is detailed in Section 3.5.1.2.
Thornburgh Expires July 8, 2013 [Page 23]

Internet-Draft Adobe RTMFP January 2013
initiatorSessionID : The Session ID to be used by the responder when
sending packets to the Initiator.
cookieLength : VLU, the length of the following cookieEcho field in
bytes.
cookieEcho : The cookie from the Responder Hello, unaltered.
certLength : VLU, the length of the following initiatorCertificate
field in bytes.
initiatorCertificate : The initiator's identity credentials.
skicLength : VLU, the length of the following
sessionKeyInitiatorComponent field in bytes.
sessionKeyInitiatorComponent : The initiator's portion of the
session key negotiation according to the Cryptography Profile.
initiatorSignedParameters : The payload portion of this chunk up to
the signature field.
signature : The initiator's digital signature of the
initiatorSignedParameters according to the Cryptography Profile.
Note: this specification doesn't mandate a specific choice of
cryptography. The Cryptography Profile determines the syntax,
algorithms, and interpretation of the initiatorCertificate,
responderCertificate, sessionKeyInitiatorComponent,
sessionKeyResponderComponent, and signature, and how the
sessionKeyInitiatorComponent and sessionKeyResponderComponent are
combined to derive the session keys.
The use of IIKeying is detailed in Section 3.5.1.
2.3.8. Responder Initial Keying Chunk (RIKeying)
This chunk is sent by a responder in response to an Initiator Initial
Keying as the final phase of session startup. This chunk MUST ONLY
be in a packet encrypted with the default session key, having packet
mode 3 (Startup), and sent to the initiator with the Session ID
specified by the initiatorSessionID field from the Initiator Initial
Keying.
Thornburgh Expires July 8, 2013 [Page 25]

Internet-Draft Adobe RTMFP January 2013
responderSignedParameters : The concatenation of the
responderSignedParametersPortion (the payload portion of this
chunk up to the signature field) and the
sessionKeyInitiatorComponent from the Initiator Initial Keying to
which this chunk is a response.
Note: this specification doesn't mandate a specific choice of
cryptography. The Cryptography Profile determines the syntax,
algorithms, and interpretation of the initiatorCertificate,
responderCertificate, sessionKeyInitiatorComponent,
sessionKeyResponderComponent, and signature, and how the
sessionKeyInitiatorComponent and sessionKeyResponderComponent are
combined to derive the session keys.
Once the responder has computed the sessionKeyResponderComponent, it
has all of the information and state necessary for an established
session with the initiator. Once the responder has sent this chunk
to the initiator, the session is established and ready to carry flows
of user data.
Once the initiator receives, verifies, and processes this chunk, it
has all of the information and state necessary for an established
session with the responder. The session is established and ready to
carry flows of user data.
The use of RIKeying is detailed in Section 3.5.1.
2.3.9. Ping Chunk
This chunk is sent in order to elicit a Ping Reply from the receiver.
It MUST ONLY be in a packet belonging to an established session and
having packet mode 1 or 2.
0 1 2
0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5|6 7 8 9 0 1 2 3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x01 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| message |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct pingChunkPayload_t
{
uint8_t message[chunkLength];
} :chunkLength*8;
Thornburgh Expires July 8, 2013 [Page 27]

Internet-Draft Adobe RTMFP January 2013
message : The (potentially empty) message that is expected to be
returned by the other end of the session in a Ping Reply.
The receiver of this chunk SHOULD reply as immediately as is
practical with a Ping Reply.
Ping and the expected Ping Reply are typically used for session
keepalive, endpoint address change verification, and path MTU
discovery. See Section 3.5.4 for details.
2.3.10. Ping Reply Chunk
This chunk is sent in response to a Ping chunk. It MUST ONLY be in a
packet belonging to an established session and having packet mode 1
or 2.
0 1 2
0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5|6 7 8 9 0 1 2 3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x41 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| messageEcho |
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct pingReplyChunkPayload_t
{
uint8_t messageEcho[chunkLength];
} :chunkLength*8;
messageEcho : The message from the Ping to which this is a response,
unaltered.
2.3.11. User Data Chunk
This chunk is the basic unit of transmission for the user messages of
a flow. A user message comprises one or more fragments. Each
fragment is carried in its own chunk and has a unique sequence number
in its flow.
Thornburgh Expires July 8, 2013 [Page 28]

Internet-Draft Adobe RTMFP January 2013
0 : This fragment is a complete message.
1 : This fragment is the first of a multi-fragment message.
2 : This fragment is the last of a multi-fragment message.
3 : This fragment is in the middle of a multi-fragment message.
A single-fragment user message has a fragment control of
"0-whole". When a message has more than one fragment, the first
fragment has a fragment control of "1-begin", then zero or more
"3-middle" fragments, and finally a "2-end" fragment. The
sequence numbers of a multi-fragment message MUST be contiguous.
abandon : If set, this sequence number has been abandoned by the
sender. The userData, if any, MUST be ignored.
final : If set, this is the last sequence number of the flow.
flowID : VLU, the flow identifier.
sequenceNumber : VLU, the sequence number of this fragment.
Fragments are assigned contiguous increasing sequence numbers in a
flow. The first sequence number of a flow SHOULD be 1. The first
sequence number of a flow MUST be greater than zero. Sequence
numbers are unbounded and do not wrap.
fsnOffset : VLU, the difference between the Sequence Number and the
Forward Sequence Number. This field MUST NOT be zero if the
abandon flag is not set. This field MUST NOT be greater than
sequenceNumber.
forwardSequenceNumber : The flow sender will not send (or resend)
any fragment with a sequence number less than or equal to the
forward sequence number.
options : If the optionsPresent flag is set, a list of zero or more
Options terminated by a Marker is present. See Section 2.3.11.1
for defined options.
userData : The actual user data for this sequence number.
The use of User Data is detailed in Section 3.6.2.
2.3.11.1. Options for User Data
This section lists options that may appear in User Data option lists.
A conforming implementation MUST support the options in this section.
Thornburgh Expires July 8, 2013 [Page 30]

Internet-Draft Adobe RTMFP January 2013
A flow receiver MUST reject a flow containing a flow option that is
not understood if the option type is less than 8192. A flow receiver
MUST ignore any flow option that is not understood if the option type
is 8192 or greater.
The following option type codes are defined for User Data:
0x00 : Users's Per-Flow Metadata (Section 2.3.11.1.1)
0x0a : Return Flow Association (Section 2.3.11.1.2)
2.3.11.1.1. User's Per-Flow Metadata
This option conveys the user's per-flow metadata for the flow to
which it's attached.
+-------------/-+-------------/-+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
| length \ | 0x00 \ | userMetadata |
+-------------/-+-------------/-+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
struct userMetadataOptionValue_t
{
uint8_t userMetadata[remainder()];
} :remainder()*8;
The user associates application-defined metadata with each flow. The
metadata does not change over the life of the flow. Every flow MUST
have metadata. A flow sender MUST send this option with the first
User Data chunk for this flow in each packet until an acknowledgement
for this flow is received. A flow sender SHOULD NOT send this option
more than once for each flow in any one packet. A flow sender SHOULD
NOT send this option for a flow once the flow has been acknowledged.
This specification doesn't mandate the encoding, syntax, or
interpretation of the user's per-flow metadata; this is determined by
the application.
The userMetadata SHOULD NOT exceed 512 bytes. The userMetadata MAY
be 0 bytes in length.
2.3.11.1.2. Return Flow Association
A new flow MAY be considered to be in return (or response) to a flow
sent by the other endpoint. This option encodes the receive flow
identifier to which this new sending flow is a response.
Thornburgh Expires July 8, 2013 [Page 31]

Internet-Draft Adobe RTMFP January 2013
+-------------/-+-------------/-+-------------/-+
| length \ | 0x0a \ | flowID \ |
+-------------/-+-------------/-+-------------/-+
struct returnFlowAssociationOptionValue_t
{
vlu_t flowID :variable*8;
} :variable*8;
Consider endpoints A and B. Endpoint A begins a flow with identifier
5 to endpoint B. A is the flow sender for A's flowID=5 and B is the
flow receiver for A's flowID=5. B begins a return flow with
identifier 7 to A in response to A's flowID=5. B is the flow sender
for B's flowID=7 and A is the flow receiver for B's flowID=7. B
sends this option with flowID set to 5 to indicate that B's flowID=7
is in response to and associated with A's flowID=5.
If there is a return association, the flow sender MUST send this
option with the first User Data chunk for this flow in each packet
until an acknowledgement for this flow is received. A flow sender
SHOULD NOT send this option more than once for each flow in any one
packet. A flow sender SHOULD NOT send this option for a flow once
the flow has been acknowledged.
A flow MUST NOT indicate more than one return association.
A flow MUST indicate its return association, if any, upon its first
transmission of a User Data chunk. A return association can't be
added to a sending flow after it begins.
A flow receiver MUST reject a new receiving flow having a return flow
association that does not indicate an OPEN sending flow.
2.3.12. Next User Data Chunk
This chunk is equivalent to the User Data Chunk for purposes of
sending the user messages of a flow. When used, it MUST ONLY follow
a User Data or another Next User Data chunk in the same packet.
Thornburgh Expires July 8, 2013 [Page 32]

Internet-Draft Adobe RTMFP January 2013
bit field : A sequence of zero or more bytes representing a bit
field of received sequence numbers after the cumulative
acknowledgement, least significant bit first. A set bit indicates
receipt of a sequence number. A clear bit indicates that sequence
number was not received. The least significant bit of the first
byte is the second sequence number following the cumulative
acknowledgement, the next bit is the third sequence number
following, and so on.
50 00 05 | Bitmap Ack, length=5 bytes
05 7f 10 | flowID=5, bufAvail=127*1024 bytes, cumAck=0..16
79 06 | 01111001 00000110 = 18, 21, 22, 23, 24, 27, 28
Example bitmap ack indicating acknowledgement of sequence numbers 0
through 16, 18, 21 through 24, 27 and 28.
2.3.14. Data Acknowledgement Ranges Chunk (Range Ack)
This chunk is sent by the flow receiver to indicate to the flow
sender the User Data sequence numbers that have been received for one
flow. It MUST ONLY be in a packet belonging to an established
session and having packet mode 1 or 2.
The flow receiver MAY choose to acknowledge User Data with this chunk
or with a Bitmap Ack. It SHOULD choose whichever format has the most
compact encoding of the sequence numbers received.
Thornburgh Expires July 8, 2013 [Page 36]

Internet-Draft Adobe RTMFP January 2013
holesMinusOne / receivedMinusOne : Zero or more acknowledgement
ranges, run-length encoded. Runs are encoded as zero or more
pairs of VLUs indicating the number (minus one) of missing
sequence numbers followed by the number (minus one) of received
sequence numbers, starting at the cumulative acknowledgement.
51 00 07 | Range Ack, length=7
05 7f 10 | flowID=5, bufAvail=127*1024 bytes, cumAck=0..16
00 00 | holes=1, received=1 -- missing 17, received 18
01 03 | holes=2, received=4 -- missing 19..20, received 21..24
Example range ack indicating acknowledgement of sequence numbers 0
through 16, 18, 21, 22, 23, 24.
2.3.15. Buffer Probe Chunk
This chunk is sent by the flow sender in order to request the current
available receive buffer (in the form of a Data Acknowledgement) for
a flow. It MUST ONLY be in a packet belonging to an established
session and having packet mode 1 or 2.
0 1 2
0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5|6 7 8 9 0 1 2 3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x18 | chunkLength |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-------------/-+
| flowID \ |
+-------------/-+
struct bufferProbeChunkPayload_t
{
vlu_t flowID :variable*8;
} :chunkLength*8;
flowID : VLU, the flow identifier.
The receiver of this chunk SHOULD reply as immediately as is
practical with a Data Acknowledgement.
2.3.16. Flow Exception Report Chunk
This chunk is sent by the flow receiver to indicate that it is not
(or is no longer) interested in the flow and would like the flow
sender to close the flow. This chunk SHOULD precede every Data
Acknowledgement chunk for the same flow in this condition.
Thornburgh Expires July 8, 2013 [Page 38]

Internet-Draft Adobe RTMFP January 20132.3.18. Session Close Acknowledgement Chunk (Close Ack)
This chunk is sent in response to a Session Close Request to indicate
the sender has terminated the session. It MUST ONLY be in a packet
belonging to an established or closing session and having packet mode
1 or 2.
0 1 2
0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5|6 7 8 9 0 1 2 3|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| 0x4c | 0 |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
This chunk has no payload.
The use of Close Ack is detailed in Section 3.5.5.
3. Operation3.1. Overview
Between any pair of communicating endpoints is a single,
bidirectional, secured, congestion controlled session.
Unidirectional flows convey messages from one end to the other within
the session.
An endpoint initiates a session to a far end when communication is
desired. An initiator begins with one or more candidate destination
socket addresses, and may learn and try more candidate addresses
during startup handshaking. Eventually a first suitable response is
received, and that endpoint is selected. Startup proceeds to the
selected endpoint. In the case of session startup glare, one
endpoint is the prevailing initiator and the other assumes the role
of responder. Encryption keys and session identifiers are negotiated
between the endpoints, and the session is established.
Each endpoint may begin sending message flows to the other end. For
each flow, the far end may accept it and deliver its messages to the
user, or it may reject the flow and transmit an exception to the
sender. The flow receiver may close and reject a flow at a later
time, after first accepting it. The flow receiver acknowledges all
data sent to it regardless of whether the flow was accepted.
Acknowledgements drive a congestion control mechanism.
An endpoint may have concurrent sessions with other far endpoints.
The multiple sessions are distinguished by a session identifier
rather than by socket address. This allows an endpoint's address to
Thornburgh Expires July 8, 2013 [Page 40]

Internet-Draft Adobe RTMFP January 2013
change mid-session without having to tear down and re-establish a
session. The existing cryptographic state for a session can be used
to verify a change of address while protecting against session
hijacking or denial-of-service.
A sender may indicate to a receiver that some user messages are of a
time-critical or real-time nature. A receiver may indicate to
senders on concurrent sessions that it is receiving time-critical
messages from another endpoint. The other senders SHOULD modify
their congestion control parameters to yield capacity to the session
carrying time-critical messages.
A sender may close a flow. The flow is completed when the receiver
has no outstanding gaps before the final fragment of the flow. The
sender and receiver reserve a completed flow's identifier for a time
to allow in-flight messages to drain from the network.
Eventually, neither end will have any flows open to the other. The
session will be idle and quiescent. Either end may reliably close
the session to recover its resources.
In certain circumstances, an endpoint may be ceasing operation and
not have time to wait for acknowledgement of a reliable session
close. In this case the halting endpoint may send an abrupt session
close to advise the far end that it is halting immediately.
3.2. Endpoint Identity
Each RTMFP endpoint has an identity. The identity is encoded in a
certificate. This specification doesn't mandate any particular
certificate format, cryptographic algorithms, or cryptographic
properties for certificates.
An endpoint is named by an Endpoint Discriminator. This
specification doesn't mandate any particular format for Endpoint
Discriminators.
An Endpoint Discriminator MAY select more than one identity, and MAY
match more than one distinct certificate.
Multiple distinct Endpoint Discriminators MAY match one certificate.
Multiple endpoints SHOULD NOT have the same identity.
An endpoint MAY have more than one address.
The Cryptography Profile implements the following functions for
identities, certificates, and Endpoint Discriminators, whose
Thornburgh Expires July 8, 2013 [Page 41]

Internet-Draft Adobe RTMFP January 2013
operation MUST be deterministic:
o Test whether a given certificate is authentic. Authenticity MAY
comprise verifying an issuer signature chain in a public key
infrastructure.
o Test whether a given Endpoint Discriminator selects a given
certificate.
o Test whether a given Endpoint Discriminator selects the local
endpoint.
o Generate a Canonical Endpoint Discriminator for a given
certificate. Canonical Endpoint Discriminators for distinct
identities SHOULD be distinct.
o Given a certificate, a message, and a digital signature over the
message, test whether the signature is valid and generated by the
owner of the certificate.
o Generate a digital signature for a given message corresponding to
the near identity.
o Given the near identity and a far certificate, determine which one
shall prevail as Initiator and which shall assume the Responder
role in the case of startup glare. The far end MUST arrive at the
same conclusion. A comparison function MAY comprise performing a
lexicographic ordering of the binary certificates, and declaring
the far identity the prevailing endpoint if the far certificate is
ordered before the near certificate, and otherwise declaring the
near identity to be the prevailing endpoint.
o Given a first certificate and a second certificate, test whether a
new incoming session from the second shall override an existing
session with the first. A test SHOULD comprise testing whether
the certificates are identical.
All other semantics for certificates and Endpoint Discriminators are
determined by the Cryptography Profile and the application.
3.3. Packet Multiplex
An RTMFP typically has one or more interfaces through which it
communicates with other RTMFP endpoints. RTMFP can communicate with
multiple distinct other RTMFP endpoints through each local interface.
Session multiplexing over a shared interface can facilitate peer-to-
peer communications through a NAT, by enabling third party endpoints
such as Forwarders (Section 3.5.1.5) and Redirectors
Thornburgh Expires July 8, 2013 [Page 42]

Internet-Draft Adobe RTMFP January 2013
(Section 3.5.1.4) to observe the translated public address and inform
peers of the translation.
An interface is typically a UDP socket (Section 2.2.1), but MAY be
any suitable datagram transport service where endpoints can be
addressed by IPv4 or IPv6 socket addresses.
RTMFP uses a session ID to multiplex and demultiplex communications
with distinct endpoints (Section 2.2.2), in addition to the endpoint
socket address. This allows an RTMFP to detect a far-end address
change (as might happen for example in mobile and wireless scenarios)
and for communication sessions to survive address changes. This also
allows an RTMFP to act as a Forwarder or Redirector for an endpoint
with which it has an active session, by distinguishing startup
packets from those of the active session.
On receiving a packet, an RTMFP decodes the session ID to look up the
corresponding session information context and decryption key.
Session ID 0 is reserved for session startup and MUST NOT be used for
an active session. A packet for session ID 0 uses the Default
Session Key as defined by the Cryptography Profile.
3.4. Packet Fragmentation
When an RTMFP packet (Section 2.2.4) is unavoidably larger than the
path MTU (such as a startup packet containing an RHello
(Section 2.3.4) or IIKeying (Section 2.3.7) chunk with a large
certificate), it can be fragmented into segments that do not exceed
the path MTU using the Packet Fragment chunk (Section 2.3.1).
The packet fragmentation mechanism SHOULD ONLY be used to segment
unavoidably large packets. Accordingly, this mechanism SHOULD ONLY
be employed during session startup with session ID 0. This mechanism
MUST NOT be used instead of the natural fragmentation mechanism of
the User Data (Section 2.3.11) and Next User Data (Section 2.3.12)
chunks for dividing the messages of the user's data flows into
segments that do not exceed the path MTU.
A fragmented plain RTMFP packet is reassembled by concatenating the
packetFragment fields of the fragments for the packet in contiguous
ascending order, starting from index 0 through and including the
final fragment.
When reassembling packets for Session ID 0, a receiver SHOULD
identify the packets by both the socket address from which the packet
containing the fragment was received as well as the indicated
packetID.
Thornburgh Expires July 8, 2013 [Page 43]

Internet-Draft Adobe RTMFP January 2013
A receiver SHOULD allow up to 60 seconds to completely receive a
fragmented packet for which progress is being made. A packet is
progressing if at least one new fragment for it was received in the
last second.
A receiver MUST discard a Packet Fragment chunk having an empty
packetFragment field.
The mode of each packet containing Packet Fragments for the same
fragmented packet MUST match the mode of the fragmented packet. A
receiver MUST discard any new Packet Fragment chunk received in a
packet with a mode different from the mode of the packet containing
the first received fragment. A receiver MUST discard any reassembled
packet with a mode different than the packets containing its
fragments.
In order to avoid jamming the network, the sender MUST rate limit
packet transmission. In the absence of specific path capacity
information (for instance, during session startup), a sender SHOULD
NOT send more than 4380 bytes nor more than four packets per distinct
endpoint every 200ms.
To avoid resource exhaustion, a receiver SHOULD limit the number of
concurrent packet reassembly buffers and the size of each buffer.
3.5. Sessions
A session is the protocol relationship between a pair of
communicating endpoints, comprising the shared and endpoint-specific
information context necessary to carry out the communication. The
session context at each end includes at least:
o TS_RX: the last timestamp received from the far end;
o TS_RX_TIME: the time at which TS_RX was first observed to be
different than its previous value;
o TS_ECHO_TX: the last timestamp echo sent to the far end;
o MRTO: the measured retransmission timeout;
o ERTO: the effective retransmission timeout;
o Cryptographic keys for encrypting and decrypting packets, and for
verifying the validity of packets, according to the Cryptography
Profile;
Thornburgh Expires July 8, 2013 [Page 44]

Internet-Draft Adobe RTMFP January 2013
o Cryptographic near and far nonces, according to the Cryptography
Profile, the near nonce being the far end's far nonce, and vice
versa;
o The certificate of the far end;
o The receive session identifier, used by the far end when sending
packets to this end;
o The send session identifier to use when sending packets to the far
end;
o DESTADDR: the socket address to which to send packets to the far
end;
o The set of all sending flow contexts (Section 3.6.2);
o The set of all receiving flow contexts (Section 3.6.3);
o The transmission budget, which controls the rate at which data is
sent into the network (for example, a congestion window);
o OUTSTANDING_BYTES: the total amount of user message data
outstanding, or in flight, in the network; that is the sum of the
OUTSTANDING_BYTES of each sending flow in the session;
o RX_DATA_PACKETS: a count of the number of received packets
containing at least one User Data chunk since the last
acknowledgement was sent, initially 0;
o ACK_NOW: a boolean flag indicating whether an acknowledgement
should be sent immediately, initially false;
o DELACK_ALARM: an alarm to trigger an acknowledgement after a
delay, initially unset;
o The state, at any time being one of the following values: the
opening states IHELLO_SENT and KEYING_SENT; the OPEN state; the
closing states NEARCLOSE and FARCLOSE_LINGER; and the closed
states CLOSED and OPEN_FAILED; and
o The role of this end of the session, which is either Initiator or
Responder.
Thornburgh Expires July 8, 2013 [Page 45]

Internet-Draft Adobe RTMFP January 20133.5.1. Startup3.5.1.1. Normal Handshake
RTMFP sessions are established with a 4-way handshake in two round
trips. The Initiator begins by sending an IHello to one or more
candidate addresses for the desired destination endpoint. A
Responder statelessly sends an RHello in response. The first correct
RHello received at the Initiator is selected; all others are ignored.
The Initiator computes its half of the session keying and sends an
IIKeying. The Responder receives the IIKeying, and if it is
acceptable, computes its half of the session keying, at which point
it can also compute the shared session keying and session nonces.
The Responder creates a new OPEN session with the Initiator, and
sends an RIKeying. The Initiator receives the RIKeying, and if it is
acceptable, it computes the shared session keying and session nonces.
The Initiator's session is now OPEN.
. Initiator Responder .
| IHello |
|(EPD,Tag) |
IHELLO_SENT |(SID=0) |
|------------------------------->|
| |
| RHello |
| (Tag,Cookie,RCert)|
| (SID=0)|
|<-------------------------------|
KEYING_SENT | |
| IIKeying |
|(ISID,Cookie,ICert,SKIC,ISig) |
|(SID=0) |
|------------------------------->|
| |
| RIKeying |
| (RSID,SKRC,RSig)|
| (SID=ISID,Key=Default)| OPEN
|<-------------------------------|
OPEN | |
| S E S S I O N |
|<-------------------(SID=ISID)--|
. |--(SID=RSID)------------------->| .
Normal Handshake.
In the following sections the handshake is detailed from the
perspectives of the Initiator and Responder.
Thornburgh Expires July 8, 2013 [Page 46]

Internet-Draft Adobe RTMFP January 20133.5.1.1.1. Initiator
The Initiator determines that a session is needed for an Endpoint
Discriminator. The Initiator creates state for a new opening session
and begins with a candidate endpoint address set containing at least
one address. The new session is placed in the IHELLO_SENT state.
If the session does not move to the OPEN state before an ultimate
open timeout, the session has failed and moves to the OPEN_FAILED
state. The RECOMMENDED ultimate open timeout is 95 seconds.
The Initiator chooses a new, unique Tag not used by any currently
opening session. The Tag SHOULD be cryptographically pseudorandom
and SHOULD NOT be less than 8 bytes in length. The Initiator
constructs an IHello chunk (Section 2.3.2) with the Endpoint
Discriminator and the Tag.
While the Initiator is in the IHELLO_SENT state, it sends the IHello
to each candidate endpoint address in the set, on a backoff schedule.
The backoff SHOULD NOT be less than multiplicative with not less than
1.5 seconds added to the interval between each attempt. The backoff
SHOULD be scheduled separately for each candidate address, since new
candidates can be added over time.
If the Initiator receives a Redirect chunk (Section 2.3.5) with a Tag
Echo matching this session, AND this session is in the IHELLO_SENT
state, then for each redirect destination indicated in the Redirect:
if the candidate endpoint address set contains fewer than
REDIRECT_THRESHOLD addresses, add the indicated redirect destination
to the candidate endpoint address set. REDIRECT_THRESHOLD SHOULD NOT
be more than 24.
If the Initiator receives an RHello chunk (Section 2.3.4) with a Tag
Echo matching this session, AND this session is in the IHELLO_SENT
state, AND the Responder certificate matches the desired Endpoint
Discriminator, AND the certificate is authentic according to the
Cryptography Profile, then:
1. If the Canonical Endpoint Discriminator for the responder
certificate matches the Canonical Endpoint Discriminator of
another existing session in the KEYING_SENT or OPEN states, AND
the certificate of the other opening session matches the desired
Endpoint Discriminator, then: this session is a duplicate and
SHOULD be aborted in favor of the other existing session;
otherwise
2. Move to the KEYING_SENT state. Set DESTADDR, the far end address
for the session, to the address from which this RHello was
Thornburgh Expires July 8, 2013 [Page 47]

Internet-Draft Adobe RTMFP January 2013
received. The Initiator chooses a new, unique receive session
ID, not used by any other session, for the Responder to use when
sending packets to the Initiator. It computes a Session Key
Initiator Component appropriate to the responder's certificate
according to the Cryptography Profile. Using this data and the
cookie from the RHello, the Initiator constructs and signs an
IIKeying chunk (Section 2.3.7).
While the Initiator is in the KEYING_SENT state, it sends the
IIKeying to DESTADDR on a backoff schedule. The backoff SHOULD NOT
be less than multiplicative with not less than 1.5 seconds added to
the interval between each attempt.
If the Initiator receives an RIKeying chunk (Section 2.3.8) in a
packet with this session's receive session identifier, AND this
session is in the KEYING_SENT state, AND the signature in the chunk
is authentic according to the far end's certificate (from the
RHello), AND the Session Key Responder Component successfully
combines with the Session Key Initiator Component and the near and
far certificates to form the shared session keys and nonces according
to the Cryptography Profile, then the session has opened
successfully. The session moves to the OPEN state. The send session
identifier is set from the RIKeying. Packet encryption, decryption,
and verification now use the newly computed shared session keys, and
the session nonces are available for application-layer cryptographic
challenges.
3.5.1.1.2. Responder
On receipt of an IHello chunk (Section 2.3.2) with an Endpoint
Discriminator that selects its identity, an endpoint SHOULD construct
an RHello chunk (Section 2.3.4) and send it to the address from which
the IHello was received. To avoid a potential resource exhaustion
denial-of-service, the endpoint SHOULD NOT create any persistent
state associated with the IHello. The endpoint MUST generate the
cookie for the RHello in such a way that it can be recognized as
authentic and valid when echoed in an IIKeying. The endpoint SHOULD
use the address from which the IHello was received as part of the
cookie generation formula. Cookies SHOULD be valid only for a
limited time; that lifetime SHOULD NOT be less than 95 seconds.
On receipt of an FIHello chunk (Section 2.3.3) from a Forwarder
(Section 3.5.1.5) where the Endpoint Discriminator selects its
identity, an endpoint SHOULD do one of the following:
1. Compute, construct and send an RHello as though the FIHello was
an IHello received from the indicated reply address; or
Thornburgh Expires July 8, 2013 [Page 48]

Internet-Draft Adobe RTMFP January 2013
2. Construct and send an Implied Redirect (Section 2.3.5) to the
FIHello's reply address; or
3. Ignore this FIHello.
On receipt of an IIKeying chunk (Section 2.3.7), if the cookie is not
authentic or if it has expired, ignore this IIKeying; otherwise,
On receipt of an IIKeying chunk, if the cookie appears authentic but
does not match the address from which the IIKeying's packet was
received, perform the special processing at Cookie Change
(Section 3.5.1.2); otherwise,
On receipt of an IIKeying with an authentic and valid cookie, if the
certificate is authentic according to the Cryptography Profile, AND
the signature in the chunk is authentic according to the far end's
certificate and the Cryptography Profile, AND the Session Key
Initiator Component is acceptable, then:
1. If the address from which this IIKeying was received corresponds
to an opening session in the IHELLO_SENT or KEYING_SENT state,
perform the special processing at Glare (Section 3.5.1.3);
otherwise,
2. If the address from which this IIKeying was received corresponds
to a session in the OPEN state, then:
1. If the receiver was the Responder for the OPEN session and
the session identifier, certificate, and Session Key
Initiator Component are identical to those of the OPEN
session, this IIKeying is a retransmission, so resend the
OPEN session's RIKeying using the Default Session Key as
specified below; otherwise,
2. If the certificate from this IIKeying does not override the
certificate of the OPEN session: ignore this IIKeying;
otherwise,
3. The certificate from this IIKeying overrides the certificate
of the OPEN session; this is a new opening session from the
same identity and the existing OPEN session is stale. Move
the existing OPEN session to CLOSED and abort all of its
flows (signaling exceptions to the user), then continue
processing this IIKeying.
Otherwise,
Thornburgh Expires July 8, 2013 [Page 49]

Internet-Draft Adobe RTMFP January 2013
3. Compute a Session Key Responder Component and choose a new,
unique receive session ID not used by any other session for the
Initiator to use when sending packets to the Responder. Using
this data, construct and, with the Session Key Initiator
Component, sign an RIKeying chunk (Section 2.3.8). Using the
Session Key Initiator and Responder Components and the near and
far certificates, the Responder combines and computes the shared
session keys and nonces according to the Cryptography Profile.
The Responder creates a new session in the OPEN state, with the
far endpoint address DESTADDR taken from the source address of
the packet containing the IIKeying and the send session
identifier taken from the IIKeying. The Responder sends the
RIKeying to the Initiator using the Default Session Key and the
requested send session identifier. Packet encryption,
decryption, and verification of all future packets for this
session use the newly computed keys, and the session nonces are
available for application-layer cryptographic challenges.
3.5.1.2. Cookie Change
In some circumstances, the Responder may generate an RHello cookie
for an Initiator's address that isn't the address the Initiator would
use when sending packets directly to the Responder. This can happen,
for example, when the Initiator has multiple local addresses, and
uses one to reach a Forwarder (Section 3.5.1.5) but another to reach
the Responder.
Consider the following example: Initiator has two network interfaces,
a first preferred interface with address Ix = 192.0.2.100:50000, and
a second with address Iy = 198.51.100.101:50001. Responder has one
interface with address Ry = 198.51.100.200:51000, on the same network
as Initiator's second interface. Initiator uses its first interface
to reach a Forwarder. Forwarder observes Initiator's address of Ix
and sends a Forwarded IHello (Section 2.3.3) to Responder. Responder
treats this as if it was an IHello from Ix, calculates a
corresponding cookie, and sends an RHello to Ix. Initiator receives
this RHello from Ry and selects that address as the destination for
the session. It then sends an IIKeying, copying the cookie from the
RHello. However, since the source of the RHello is Ry, on a network
to which the Initiator is directly connected, Initiator uses its
second interface Iy to send the IIKeying. Responder, on receiving
the IIKeying, will compare the cookie to the expected value based on
the source address of the packet, and since the IIKeying source
doesn't match the IHello source used to generate the cookie,
Responder will reject the IIKeying.
If Responder determines that it generated the cookie in the IIKeying
but the cookie doesn't match the sender's address (for example, if
Thornburgh Expires July 8, 2013 [Page 50]

Internet-Draft Adobe RTMFP January 2013
the cookie is in two parts, with a first part generated independently
of the Initiator's address, and a second part dependent on the
address), Responder SHOULD generate a new cookie based on the address
from which the IIKeying was received, and send an RHello Cookie
Change chunk (Section 2.3.6) to the source of the IIKeying, using the
session ID from the IIKeying and the Default Session Key.
If the Initiator receives an RHello Cookie Change chunk for a session
in the KEYING_SENT state, AND the old cookie matches the one
originally sent to the Responder, then: Initiator adopts the new
cookie, constructs and signs a new IIKeying chunk, and sends the new
IIKeying to the Responder. Initiator SHOULD NOT change the cookie
for a session more than once.
Initiator Forwarder Responder
| IHello | |
|(Src=Ix) | |
|------------------------------->| |
| | FIHello |
| |(RA=Ix) |
| |-------------------------------->|
| |
| RHello |
| (Cookie:Ix)|
|<-----------------------------------------------------------------|
| |
| IIKeying |
|(Cookie:Ix,Src=Iy) |
|----------------------------------------------------------------->|
| |
| RHello Cookie Change |
| (Cookie:Ix,Cookie:Iy)|
|<-----------------------------------------------------------------|
| |
| IIKeying |
|(Cookie:Iy) |
|----------------------------------------------------------------->|
| |
| RIKeying |
|<-----------------------------------------------------------------|
| |
|<======================== S E S S I O N =========================>|
Handshake with Cookie Change.
Thornburgh Expires July 8, 2013 [Page 51]

Internet-Draft Adobe RTMFP January 20133.5.1.3. Glare
Glare occurs when two endpoints attempt to initiate sessions to each
other concurrently. Glare is detected by receipt of a valid and
authentic IIKeying from an endpoint address which is a destination
for an opening session. Only one session is allowed between a pair
of endpoints.
Glare is resolved by comparing the certificate in the received
IIKeying with the near end's certificate. The Cryptography Profile
defines a certificate comparison function to determine the prevailing
endpoint when there is glare.
If the near end prevails, discard and ignore the received IIKeying.
The far end will abort its opening session on receipt of IIKeying
from the near end.
Otherwise, the far end prevails:
1. If the certificate in the IIKeying overrides the certificate
associated with the near opening session according to the
Cryptography Profile, then: abort and destroy the near opening
session. Then,
2. Continue with normal Responder IIKeying processing
(Section 3.5.1.1.2).
3.5.1.4. Redirector
A Redirector acts like a name server for Endpoint Discriminators. An
Initiator MAY use a Redirector to discover additional candidate
endpoint addresses for a desired endpoint.
On receipt of an IHello chunk with an Endpoint Discriminator that
does not select the Redirector's identity, it MAY construct and send
a Responder Redirect chunk (Section 2.3.5) back to the Initiator
containing one or more additional candidate addresses for the
indicated endpoint.
Thornburgh Expires July 8, 2013 [Page 52]

Internet-Draft Adobe RTMFP January 2013
Initiator Redirector Responder
| IHello | |
|------------------------------->| |
| | |
| Redirect | |
|<-------------------------------| |
| |
| IHello |
|----------------------------------------------------------------->|
| |
| RHello |
|<-----------------------------------------------------------------|
| |
| IIKeying |
|----------------------------------------------------------------->|
| |
| RIKeying |
|<-----------------------------------------------------------------|
| |
|<======================== S E S S I O N =========================>|
Handshake using a Redirector.
Redirectors SHOULD NOT initiate new sessions to endpoints which might
use the Redirector's address as a candidate for another endpoint,
since the far end might interpret the Redirector's IIKeying as glare
for the far end's initiation to the other endpoint.
3.5.1.5. Forwarder
A Responder might be behind a NAT or firewall that doesn't allow
inbound packets to reach the endpoint until it first sends an
outbound packet for a particular far endpoint address.
A Forwarder's endpoint address MAY be a candidate address for another
endpoint. A Responder MAY use a Forwarder to receive FIHello chunks
sent on behalf of an Initiator.
On receipt of an IHello chunk with an Endpoint Discriminator that
does not select the Forwarder's identity, if the Forwarder has an
OPEN session with an endpoint whose certificate matches the desired
Endpoint Discriminator, the forwarder MAY construct and send an
FIHello chunk (Section 2.3.3) to the selected endpoint over the OPEN
session, using the Tag and Endpoint Discriminator from the IHello
chunk and the source address of the packet containing the IHello for
the corresponding fields of the FIHello.
On receipt of an FIHello chunk, a Responder might send an RHello or
Thornburgh Expires July 8, 2013 [Page 53]

Internet-Draft Adobe RTMFP January 2013
initial candidate. The Redirector portion of the service sends a
Responder Redirect to Initiator containing at least Responder's
public NAT address as previously recorded. The Forwarder portion of
the service sends a Forwarded IHello to Responder containing
Initiator's public NAT address as observed as the source of the
IHello.
Responder sends an RHello to Initiator's public NAT address in
response to the FIHello. This will allow inbound packets to
Responder through its NAT from Initiator's public NAT address.
Initiator sends an IHello to Responder's public NAT address in
response to the Responder Redirect. This will allow inbound packets
to Initiator through its NAT from Responder's public NAT address.
With transit paths created in both NATs, normal session startup can
proceed.
Thornburgh Expires July 8, 2013 [Page 56]

Internet-Draft Adobe RTMFP January 20133.5.2. Congestion Control
An RTMFP MUST implement congestion control and avoidance algorithms
that are "TCP compatible", in accordance with Internet best current
practice [RFC2914]. The algorithms SHOULD NOT be more aggressive
than those described in TCP Congestion Control [RFC5681].
An endpoint maintains a transmission budget in the session
information context of each OPEN session, controlling the rate at
which the endpoint sends data into the network. For window-based
congestion control and avoidance algorithms, the transmission budget
is the congestion window, which is the amount of user data that is
allowed to be outstanding, or in flight, in the network. An endpoint
increases and decreases the transmission budget in response to
acknowledgements and timeouts according to the congestion control and
avoidance algorithms.
A sender MAY implement "slow start" as specified in RFC 5681.
However, a sender MUST disable "slow start", and behave as though
ssthresh is clamped to 0, on a session where a Time Critical Reverse
Notification (Section 2.2.4) indication has been received from the
far end within the last at least 800 milliseconds, unless the sender
is itself sending time critical data to the far end.
A sender SHOULD NOT increase the transmission budget by more than 384
bytes per round trip or 0.5% (whichever is greater) each round trip
on a session where a Time Critical Reverse Notification indication
has been received from the far end within the last at least 800
milliseconds, unless the sender is itself sending time critical data
to the far end.
3.5.2.1. Retransmission Timeout
RTMFP uses the Effective Retransmission Timeout ERTO to detect when a
user data fragment has been lost in the network. The ERTO is
typically calculated in a manner similar to that specified in
Requirements for Internet Hosts - Communication Layers [RFC1122], and
is a function of round trip time measurements and persistent timeout
behavior.
The ERTO SHOULD be at least 250 milliseconds and SHOULD allow for the
receiver to delay sending an acknowledgement for up to 200
milliseconds (Section 3.6.3.4.4). The ERTO MUST NOT be less than the
round trip time.
To facilitate round trip time measurement, an endpoint MUST implement
the Timestamp Echo facility:
Thornburgh Expires July 8, 2013 [Page 58]

Internet-Draft Adobe RTMFP January 2013
o On a session entering the OPEN state, initialize TS_RX_TIME to
negative infinity, and TS_RX and TS_ECHO_TX to have no value.
o On receipt of a packet in an OPEN session with the
timestampPresent (Section 2.2.4) flag set, if the timestamp field
in the packet is different than TS_RX: set TS_RX to the value of
the timestamp field in the packet, and set TS_RX_TIME to the
current time.
o When sending a packet to the far end in an OPEN session:
1. Calculate TS_RX_ELAPSED = current time - TS_RX_TIME. If
TS_RX_ELAPSED is more than 128 seconds, then set TS_RX and
TS_ECHO_TX to have no value and do not include a timestamp
echo; otherwise
2. Calculate TS_RX_ELAPSED_TICKS to be the number of whole 4
millisecond periods in TS_RX_ELAPSED; then
3. Calculate TS_ECHO = (TS_RX + TS_RX_ELAPSED_TICKS) MODULO
65536; then
4. If TS_ECHO is not equal to TS_ECHO_TX, then: set TS_ECHO_TX to
TS_ECHO, set the timestampEchoPresent flag, and set the
timestampEcho field to TS_ECHO_TX.
The remainder of this section describes an OPTIONAL method for
calculating the Effective Retransmission Timeout ERTO. Real-time
applications and P2P mesh applications often require knowing the
round trip time and RTT variance. This section additionally
describes a method for measuring the round trip time and RTT
variance, and calculating a smoothed round trip time.
Let the session information context contain additional variables:
o TS_TX: the last timestamp sent to the far end, initialized to have
no value;
o TS_ECHO_RX: the last timestamp echo received from the far end,
initialized to have no value;
o SRTT: the smoothed round-trip time, initialized to have no value;
o RTTVAR: the round-trip time variance, initialized to 0;
Initialize MRTO to 250 milliseconds.
Initialize ERTO to 3 seconds.
Thornburgh Expires July 8, 2013 [Page 59]

Internet-Draft Adobe RTMFP January 2013
On sending a packet to the far end of an OPEN session, if the current
send timestamp is not equal to TS_TX, then: set TS_TX to the current
send timestamp, set the timestampPresent flag in the packet header,
and set the timestamp field to TS_TX.
On receipt of a packet from the far end of an OPEN session, if the
timestampEchoPresent flag is set in the packet header AND the
timestampEcho field is not equal to TS_ECHO_RX, then:
1. Set TS_ECHO_RX to timestampEcho;
2. Calculate RTT_TICKS = (current send timestamp - timestampEcho)
MODULO 65536;
3. If RTT_TICKS is greater than 32767, the measurement is invalid,
so discard this measurement; otherwise
4. Calculate RTT = RTT_TICKS * 4 milliseconds;
5. If SRTT has a value, then calculate new values of RTTVAR and
SRTT:
1. RTT_DELTA = | SRTT - RTT |;
2. RTTVAR = ((3 * RTTVAR) + RTT_DELTA) / 4;
3. SRTT = ((7 * SRTT) + RTT) / 8;
6. If SRTT has no value, then set SRTT = RTT and RTTVAR = RTT / 2;
7. Set MRTO = SRTT + 4 * RTTVAR + 200 milliseconds;
8. Set ERTO to the greater of MRTO or 250 milliseconds.
A retransmission timeout occurs when the most recently transmitted
user data fragment has remained outstanding in the network for ETRO.
When this timeout occurs, increase ERTO on an exponential backoff
with an ultimate backoff cap:
1. Calculate ERTO_BACKOFF = ERTO * 1.4142;
2. Calculate ERTO_CAPPED to be the lesser of ERTO_BACKOFF and 10
seconds;
3. Set ERTO to the greater of ERTO_CAPPED and MRTO.
Thornburgh Expires July 8, 2013 [Page 60]

Internet-Draft Adobe RTMFP January 20133.5.2.2. Burst Avoidance
An application's sending patterns may cause the transmission budget
to grow to a large value but, at times, for there to be a
comparatively small amount of data outstanding in the network. In
this circumstance, especially with a window-based congestion
avoidance algorithm, if the application then has a large amount of
new data to send (for example, a new bulk data transfer), it could
send data into the network all at once to fill the window. This kind
of transmission burst can jam interfaces, links, and buffers, and is
undesirable.
Accordingly, in any session, an endpoint SHOULD NOT send more than
six packets containing user data between receiving acknowledgements
or retransmission timeouts.
The following describes an OPTIONAL method to avoid bursting large
numbers of packets into the network.
Let the session information context contain an additional variable
DATA_PACKET_COUNT, initialized to 0.
Transmission of a user data fragment on this session is not allowed
if DATA_PACKET_COUNT is greater than or equal to 6, regardless of any
other allowance of the congestion control algorithm.
On transmission of a packet containing at least one User Data chunk
(Section 2.3.11), set DATA_PACKET_COUNT = DATA_PACKET_COUNT + 1.
On receipt of an acknowledgement chunk (Section 2.3.13,
Section 2.3.14), set DATA_PACKET_COUNT to 0.
On a retransmission timeout, set DATA_PACKET_COUNT to 0.
3.5.3. Address Mobility
Sessions are demultiplexed with a 32 bit session ID, rather than by
endpoint address. This allows an endpoint's address to change during
an OPEN session. This can happen, for example, when switching from a
wireless to a wired network, or when moving from one wireless base
station to another, or when a NAT restarts.
If the near end receives a valid packet for an OPEN session from a
source address that doesn't match DESTADDR, the far end might have
changed addresses. The near end SHOULD verify that the far end is
definitively at the new address before changing DESTADDR. A
suggested verification method is described in Section 3.5.4.2.
Thornburgh Expires July 8, 2013 [Page 61]

Internet-Draft Adobe RTMFP January 20133.5.4. Ping
If an endpoint receives a Ping chunk (Section 2.3.9) in a session in
the OPEN state, it SHOULD construct and send a Ping Reply chunk
(Section 2.3.10) in response if possible, copying the message
unaltered. A Ping Reply response SHOULD be sent as quickly as
possible following receipt of a Ping. The semantics of a Ping's
message is reserved for the sender; a receiver SHOULD NOT interpret
the Ping's message.
Endpoints MAY use the mechanism of the Ping chunk and the expected
Ping Reply for any purpose. This specification doesn't mandate any
specific constraints on the format or semantics of a Ping message. A
Ping Reply MUST ONLY be sent as a response to a Ping.
Receipt of a Ping Reply implies live bidirectional connectivity.
This specification doesn't mandate any other semantics for a Ping
Reply.
3.5.4.1. Keepalive
An endpoint MAY use Ping to test for live bidirectional connectivity,
to test that the far end of a session is still OPEN, to keep NAT
translations alive, and to keep firewall holes open.
An endpoint MAY use Ping to hasten detection by the far end of a near
end address change.
An endpoint MAY declare a session to be defunct and dead after a
persistent failure by the far end to return Ping Replies in response
to Pings.
If used for these purposes, a Keepalive Ping SHOULD have an empty
message.
A Keepalive Ping SHOULD NOT be sent more often than once per ERTO.
If a corresponding Ping Reply is not received within ERTO of sending
the Ping, ERTO SHOULD be increased according to Congestion Control
(Section 3.5.2).
3.5.4.2. Address Mobility
This section describes an OPTIONAL but suggested method for
processing and verifying a far end address change.
Let the session context contain additional variables MOB_TX_TS,
MOB_RX_TS, and MOB_SECRET. MOB_TX_TS and MOB_RX_TS have initial
values of negative infinity. MOB_SECRET should be a
Thornburgh Expires July 8, 2013 [Page 62]

Internet-Draft Adobe RTMFP January 2013
cryptographically pseudorandom value not less than 128 bits in length
and known only to this end.
On receipt of a packet for an OPEN session, after processing all
chunks in the packet: if the session is still OPEN, AND the source
address of the packet does not match DESTADDR, AND MOB_TX_TS is at
least one second in the past, then:
1. Set MOB_TX_TS to the current time;
2. Construct a Ping message comprising: a marking to indicate that
it is a mobility check, a timestamp set to MOB_TX_TS, and a
cryptographic hash over the preceding as well as the address from
which the packet was received and MOB_SECRET; and
3. Send this Ping to the address from which the packet was received,
instead of DESTADDR.
On receipt of a Ping Reply in an OPEN session, if the Ping Reply's
message is marked to indicate it is a mobility check, AND the
timestamp in the message is not more than 132 seconds in the past,
AND the timestamp in the message is greater than MOB_RX_TS, AND the
cryptographic hash matches the expected value according to the
contents of the message plus the source address of the packet
containing this Ping Reply and MOB_SECRET, then:
1. Set MOB_RX_TS to the timestamp in the message; and
2. Set DESTADDR to the source address of the packet containing this
Ping Reply.
3.5.4.3. Path MTU Discovery
Packetization Layer Path MTU Discovery [RFC4821] describes a method
for measuring the path MTU between communicating endpoints.
An RTMFP SHOULD perform path MTU discovery.
The method of RFC 4821 MAY be adapted for use in RTMFP by sending a
probe packet comprising one of the Padding chunk types (type 0x00 or
0xff) and a Ping. The Ping chunk SHOULD come after the Padding
chunk, to guard against a false positive response in case the probe
packet is truncated.
3.5.5. Close
An endpoint may close a session at any time. Typically an endpoint
will close a session when there have been no open flows in either
Thornburgh Expires July 8, 2013 [Page 63]

Internet-Draft Adobe RTMFP January 2013
direction for a time. In another circumstance, an endpoint may be
ceasing operation and will close all of its sessions even if they
have open flows.
To close an OPEN session in a reliable and orderly fashion, an
endpoint moves the session to the NEARCLOSE state.
A session that has been in the NEARCLOSE state for at least 90
seconds SHOULD move to the CLOSED state.
A session that has been in the FARCLOSE_LINGER state for at least 19
seconds SHOULD move to the CLOSED state.
On a session transitioning from OPEN to NEARCLOSE and every 5 seconds
thereafter while still in the NEARCLOSE state, send a Session Close
Request chunk (Section 2.3.17).
On a session transitioning from OPEN to the NEARCLOSE,
FARCLOSE_LINGER or CLOSED state: immediately abort and terminate all
open or closing flows. Flows only exist in OPEN sessions.
To close an OPEN session abruptly, send a Session Close
Acknowledgement chunk (Section 2.3.18), then move to the CLOSED
state.
On receipt of a Session Close Request chunk for a session in the
OPEN, NEARCLOSE, or FARCLOSE_LINGER states: send a Session Close
Acknowledgement chunk; then, if the session is in the OPEN state:
move to the FARCLOSE_LINGER state.
On receipt of a Session Close Acknowledgement chunk for a session in
the OPEN, NEARCLOSE, or FARCLOSE_LINGER states: move to the CLOSED
state.
3.6. Flows
A flow is a unidirectional communication channel in a session for
transporting a correlated series of user messages from a sender to a
receiver. Each end of a session may have zero or more sending flows
to the other end. Each sending flow at one end has a corresponding
receiving flow at the other end.
3.6.1. Overview3.6.1.1. Identity
Flows are multiplexed in a session by a flow identifier. Each end of
a session chooses its sending flow identifiers independently of the
Thornburgh Expires July 8, 2013 [Page 64]

Internet-Draft Adobe RTMFP January 2013
other end. The choice of similar flow identifiers by both ends does
not imply an association. A sender MAY choose any identifier for any
flow; therefore, a flow receiver MUST NOT ascribe any semantic
meaning, role, or name to a flow based only on its identifier. There
are no "well known" or reserved flow identifiers.
Bidirectional flow association is indicated with the Return Flow
Association option (Section 2.3.11.1.2). An endpoint MAY indicate
that a new sending flow is in return (or response) to a receiving
flow from the other end. A sending flow MUST NOT indicate more than
one return association. A receiving flow can be specified as the
return association for any number of sending flows. The return flow
association, if any, is fixed for the lifetime of the sending flow.
Flows are named with arbitrary user metadata. This specification
doesn't mandate any particular encoding, syntax, or semantics for the
user metadata except for the encoded size (Section 2.3.11.1.1); the
user metadata is entirely reserved for the application. The user
metadata is fixed for the lifetime of the flow.
3.6.1.2. Messages and Sequencing
Flows provide message-oriented framing. Large messages are
fragmented for transport in the network. Receivers reassemble
fragmented messages and only present complete messages to the user.
A sender queues messages on a sending flow one after another. A
receiver can recover the original queuing order of the messages, even
when they are reordered in transit by the network or as a result of
loss and retransmission. Flows are the basic units of message
sequencing; each flow is sequenced independently of all other flows;
inter-flow message arrival and delivery sequencing is not guaranteed.
Independent flow sequencing allows a sender to prioritize the
transmission or retransmission of the messages of one flow over those
of other flows in a session, allocating capacity from the
transmission budget according to priority. RTMFP is designed for
flows to be the basic unit of prioritization. In any flow, the
sequence numbers of all fragments of a message MUST be greater than
the sequence numbers of all fragments of all previously queued
messages in that flow. Receipt of fragments within a flow out of
sequence number order creates discontiguous gaps at the receiver,
causing it to send an acknowledgement for every packet and for the
size of the encoded acknowledgements to grow. Therefore, for any
flow, the sender SHOULD send lower sequence numbers first.
A sender MAY abandon a queued message at any time, even if some
fragments of that message have been received by the other end. A
Thornburgh Expires July 8, 2013 [Page 65]

Internet-Draft Adobe RTMFP January 2013
receiver MUST be able to detect a gap in the flow when a message is
abandoned; therefore, each message SHOULD take at least one sequence
number from the sequence space even if no fragments for that message
are ever sent. The sender will transmit the fragments of all
messages not abandoned, and retransmit any lost fragments of all
messages not abandoned, until all the fragments of all messages not
abandoned are acknowledged by the receiver. A sender indicates a
Forward Sequence Number (FSN) to instruct the receiver that sequence
numbers less than or equal to the FSN will not be transmitted or
retransmitted. This allows the receiver to move forward over gaps
and continue sequenced delivery of completely received messages to
the user. Any incomplete messages missing fragments with sequence
numbers less than or equal to the FSN were abandoned by the sender
and will never be completed. A gap indication MUST be communicated
to the receiving user.
3.6.1.3. Lifetime
A sender begins a flow by sending user message fragments to the other
end, and including the user metadata and, if any, the return flow
association. The sender continues to include the user metadata and
return flow association until the flow is acknowledged by the far
end, at which point the sender knows that the receiver has received
the user metadata and, if any, the return flow association. After
that point, the flow identifier alone is sufficient.
Flow receivers SHOULD acknowledge all sequence numbers received for
any flow, whether the flow is accepted or rejected. Flow receivers
MUST NOT acknowledge sequence numbers higher than the FSN that were
not received. Acknowledgements drive the congestion control and
avoidance algorithms and therefore must be accurate.
An endpoint MAY reject a receiving flow at any time in the flow's
lifetime. To reject the flow, the receiving endpoint sends a Flow
Exception chunk (Section 2.3.16) immediately preceding every
acknowledgement chunk for the rejected receiving flow.
An endpoint may eventually conclude and close a sending flow. The
last sequence number of the flow is marked with the Final flag. The
sending flow is complete when all sequence numbers of the flow,
including the final sequence number, have been cumulatively
acknowledged by the receiver. The receiving flow is complete when
every sequence number from the FSN to the final sequence number has
been received. The sending flow and corresponding receiving flow at
the respective ends hold the flow identifier of a completed flow in
reserve for a time to allow delayed or duplicated fragments and
acknowledgements to drain from the network without erroneously
initiating a new receiving flow or erroneously acknowledging a new
Thornburgh Expires July 8, 2013 [Page 66]

Internet-Draft Adobe RTMFP January 2013
sending flow.
If a flow sender receives a Flow Exception indication from the other
end, the flow sender SHOULD close the flow and abandon all of the
undelivered queued messages. The flow sender SHOULD indicate an
exception to the user.
3.6.2. Sender
Each sending flow comprises the flow-specific information context
necessary to transfer that flow's messages to the other end. Each
sending flow context includes at least:
o FLOW_ID: this flow's identifier;
o STARTUP_OPTIONS: the set of options to send to the receiver until
this flow is acknowledged, including the User's Per-Flow Metadata
and, if set, the Return Flow Association;
o SEND_QUEUE: the unacknowledged message fragments queued in this
flow, initially empty; each message fragment entry comprising:
* SEQUENCE_NUMBER: the sequence number of this fragment;
* DATA: this fragment's user data;
* FRA: the fragment control value for this message fragment,
having one of the values enumerated for that purpose in User
Data (Section 2.3.11);
* ABANDONED: a boolean flag indicating whether this fragment has
been abandoned;
* SENT_ABANDONED: a boolean flag indicating whether this fragment
was abandoned when sent;
* EVER_SENT: a boolean flag indicating whether this fragment has
been sent at least once, initially false;
* NAK_COUNT: a count of the number of negative acknowledgements
detected for this fragment, initially 0;
* IN_FLIGHT: a boolean flag indicating whether this fragment is
currently in flight in the network, initially false;
* TRANSMIT_SIZE: the size, in bytes, of the encoded User Data
chunk (including the chunk header) for this fragment when it
was transmitted into the network.
Thornburgh Expires July 8, 2013 [Page 67]

Internet-Draft Adobe RTMFP January 2013
o OUTSTANDING_BYTES: the sum of the TRANSMIT_SIZE of each entry in
SEND_QUEUE where entry.IN_FLIGHT is true;
o RX_BUFFER_SIZE: the most recent available buffer advertisement
from the other end (Section 2.3.13, Section 2.3.14), initially
65536 bytes;
o NEXT_SN: the next sequence number to assign to a message fragment,
initially 1;
o FINAL_SN: the sequence number assigned to the final message
fragment of the flow, initially having no value;
o EXCEPTION: a boolean flag indicating whether an exception has been
reported by the receiver, initially false;
o The state, at any time being one of the following values: OPEN,
CLOSING, COMPLETE_LINGER, CLOSED.
3.6.2.1. Startup
The application opens a new sending flow to the other end in an OPEN
session. The implementation chooses a new flow ID that is not
assigned to any other sending flow in that session in the OPEN,
CLOSING, or COMPLETE_LINGER states. The flow starts in the OPEN
state. The STARTUP_OPTIONS for the new flow is set with the User's
Per-Flow Metadata (Section 2.3.11.1.1). If this flow is in return
(or response) to an OPEN receiving flow from the other end, that
flow's ID is encoded in a Return Flow Association
(Section 2.3.11.1.2) option and added to STARTUP_OPTIONS.
At this point the flow exists in the sender, but not the receiver.
The flow begins when user data fragments are transmitted to the
receiver. A sender MAY begin a flow in the absence of immediate user
data by sending a Forward Sequence Number Update (Section 3.6.2.7.1),
by queuing and transmitting a user data fragment that is already
abandoned.
3.6.2.2. Queuing Data
The application queues messages in an OPEN sending flow for
transmission to the far end. The implementation divides each message
into one or more fragments for transmission in User Data chunks
(Section 2.3.11). Each fragment MUST be small enough so that, if
assembled into a Packet (Section 2.2.4) with a maximum-size common
header, User Data chunk header, and, if not empty, this flow's
STARTUP_OPTIONS, the Packet will not exceed the Path MTU
(Section 3.5.4.3).
Thornburgh Expires July 8, 2013 [Page 68]

Internet-Draft Adobe RTMFP January 2013
For each fragment, create a fragment entry and set
fragmentEntry.SEQUENCE_NUMBER to flow.NEXT_SN, and increment
flow.NEXT_SN by one. Set fragmentEntry.FRA according to the encoding
in User Data chunks:
0 : This fragment is a complete message.
1 : This fragment is the first of a multi-fragment message.
2 : This fragment is the last of a multi-fragment message.
3 : This fragment is in the middle of a multi-fragment message.
Append fragmentEntry to flow.SEND_QUEUE.
3.6.2.3. Sending Data
A sending flow is ready to transmit if the SEND_QUEUE contains at
least one entry that is eligible to send and if either RX_BUFFER_SIZE
is greater than OUTSTANDING_BYTES or EXCEPTION is set to true.
A SEND_QUEUE entry is eligible to send if it is not IN_FLIGHT AND at
least one of the following conditions holds:
o The entry is not ABANDONED; or
o The entry is the first one in the SEND_QUEUE; or
o The entry's SEQUENCE_NUMBER is equal to flow.FINAL_SN.
If the session's transmission budget allows, a flow that is ready to
transmit is selected for transmission according to the
implementation's prioritization scheme. The manner of flow
prioritization is not mandated by this specification.
Trim abandoned messages from the front of the queue and find the
Forward Sequence Number FSN:
1. While the SEND_QUEUE contains at least two entries, AND the first
entry is not IN_FLIGHT, AND the first entry is ABANDONED: remove
and discard the first entry from SEND_QUEUE;
2. If the first entry in the SEND_QUEUE is not abandoned: set FSN to
entry.SEQUENCE_NUMBER - 1; otherwise
3. If the first entry in the SEND_QUEUE is IN_FLIGHT AND
entry.SENT_ABANDONED is false: set FSN to entry.SEQUENCE_NUMBER -
1; otherwise
Thornburgh Expires July 8, 2013 [Page 69]

Internet-Draft Adobe RTMFP January 2013
4. The first entry in the SEND_QUEUE is abandoned and is either not
IN_FLIGHT or was already abandoned when sent: set FSN to
entry.SEQUENCE_NUMBER.
The FSN MUST NOT be greater than any sequence number currently in
flight. The FSN MUST NOT be equal to any sequence number currently
in flight that was not abandoned when sent.
Assemble user data chunks for this flow into a packet to send to the
receiver. While enough space remains in the packet and the flow is
ready to transmit:
1. Starting at the head of the SEND_QUEUE, find the first eligible
fragment entry;
2. Encode entry into a User Data chunk (Section 2.3.11) or, if
possible (Section 3.6.2.3.2), a Next User Data chunk
(Section 2.3.12);
3. If present, set chunk.flowID to flow.FLOW_ID;
4. If present, set chunk.sequenceNumber to entry.SEQUENCE_NUMBER;
5. If present, set chunk.fsnOffset to entry.SEQUENCE_NUMBER - FSN;
6. Set chunk.fragmentControl to entry.FRA;
7. Set chunk.abandon to entry.ABANDONED;
8. If entry.SEQUENCE_NUMBER equals flow.FINAL_SN: set chunk.final
to true; else set chunk.final to false;
9. If any options are being sent with this chunk: set
chunk.optionsPresent to true, assemble the options into the
chunk, and assemble a Marker to terminate the option list;
10. If entry.ABANDONED is true, set chunk.userData to empty;
otherwise set chunk.userData to entry.DATA;
11. If adding the assembled chunk to the packet would cause the
packet to exceed the path MTU: do not assemble this chunk into
the packet, enough space no longer remains in the packet, stop.
Otherwise, continue:
12. Set entry.IN_FLIGHT to true;
13. Set entry.EVER_SENT to true;
Thornburgh Expires July 8, 2013 [Page 70]

Internet-Draft Adobe RTMFP January 2013
14. Set entry.NAK_COUNT to 0;
15. Set entry.SENT_ABANDONED to entry.ABANDONED;
16. Set entry.TRANSMIT_SIZE to the size of the assembled chunk,
including the chunk header;
17. Assemble this chunk into the packet; and
18. If this flow or entry is considered Time Critical (real-time),
set the timeCritical flag in the packet header (Section 2.2.4).
Complete any other appropriate packet processing, and transmit the
packet to the far end.
3.6.2.3.1. Startup Options
If STARTUP_OPTIONS is not empty, then when assembling the FIRST User
Data chunk for this flow into a packet, add the encoded
STARTUP_OPTIONS to that chunk's option list.
3.6.2.3.2. Send Next Data
The Next User Data chunk (Section 2.3.12) is a compact encoding for a
user message fragment when multiple contiguous fragments are
assembled into one packet.
If, after assembling a user message fragment of a flow into a packet
(Section 3.6.2.3), the next eligible fragment to be selected for
assembly belongs to the same flow AND its sequence number is one
greater than that of the fragment just assembled, an implementation
SHOULD encode a Next User Data chunk instead of a User Data chunk.
The FIRST fragment of a flow assembled into a packet MUST be encoded
as a User Data chunk.
3.6.2.4. Processing Acknowledgements
A Data Acknowledgement Bitmap chunk (Section 2.3.13) or a Data
Acknowledgement Ranges chunk (Section 2.3.14) encodes the
acknowledgement of receipt of one or more sequence numbers of a flow,
as well as the receiver's current receive window advertisement.
On receipt of an acknowledgement chunk for a sending flow:
1. Set PRE_ACK_OUTSTANDING_BYTES to flow.OUTSTANDING_BYTES;
Thornburgh Expires July 8, 2013 [Page 71]

Internet-Draft Adobe RTMFP January 2013
2. Set flow.STARTUP_OPTIONS to empty;
3. Set flow.RX_BUFFER_SIZE to chunk.bufferBytesAvailable;
4. For each sequence number encoded in the acknowledgement: if there
is an entry in flow.SEND_QUEUE with that sequence number and its
IN_FLIGHT is true, then: remove entry from flow.SEND_QUEUE; and
5. Notify the congestion control and avoidance algorithms that
PRE_ACK_OUTSTANDING_BYTES - flow.OUTSTANDING_BYTES were
acknowledged. Note that Negative Acknowledgements
(Section 3.6.2.5) affect "TCP friendly" congestion control.
3.6.2.5. Negative Acknowledgement and Loss
A negative acknowledgement is inferred for an outstanding fragment if
an acknowledgement is received for any other fragments sent after it
in the same session.
An implementation SHOULD consider a fragment to be lost once that
fragment receives three negative acknowledgements. A lost fragment
is no longer outstanding in the network.
The following describes an OPTIONAL method for detecting negative
acknowledgements.
Let the session track the order in which fragments are transmitted
across all its sending flows by way of a monotonically increasing
Transmission Sequence Number (TSN) recorded with each fragment queue
entry each time that fragment is transmitted.
Let the session information context contain additional variables:
o NEXT_TSN: the next TSN to record with a fragment's queue entry
when it is transmitted, initially 1;
o MAX_TSN_ACK: the highest acknowledged TSN, initially 0.
Let each fragment queue entry contain an additional variable TSN,
initially 0, to track its transmission order.
On transmission of a message fragment into the network, set its
entry.TSN to session.NEXT_TSN, and increment session.NEXT_TSN.
On acknowledgement of an outstanding fragment, if its entry.TSN is
greater than session.MAX_TSN_ACK, set session.MAX_TSN_ACK to
entry.TSN.
Thornburgh Expires July 8, 2013 [Page 72]

Internet-Draft Adobe RTMFP January 2013
After processing all acknowledgements in a packet containing at least
one acknowledgement, then for each sending flow in that session, for
each entry in that flow's SEND_QUEUE, if entry.IN_FLIGHT is true and
entry.TSN is less than session.MAX_TSN_ACK: increment entry.NAK_COUNT
and notify the congestion control and avoidance algorithms that a
negative acknowledgement was detected in this packet.
For each sending flow in that session, for each entry in that flow's
SEND_QUEUE, if entry.IN_FLIGHT is true and entry.NAK_COUNT is at
least 3, that fragment was lost in the network and is no longer in
flight. Set entry.IN_FLIGHT to false. Notify the congestion control
and avoidance algorithms of the loss.
3.6.2.6. Timeout
A fragment is considered lost and no longer in flight in the network
if it has remained outstanding for at least ERTO.
The following describes an OPTIONAL method to manage transmission
timeouts. This method REQUIRES that either Burst Avoidance
(Section 3.5.2.2) is implemented, or that the implementation's
congestion control and avoidance algorithms will eventually stop
sending new fragments into the network if acknowledgements are
persistently not received.
Let the session information context contain an alarm TIMEOUT_ALARM,
initially unset.
On sending a packet containing at least one User Data chunk, set or
reset TIMEOUT_ALARM to fire in ERTO.
On receiving a packet containing at least one acknowledgement, reset
TIMEOUT_ALARM (if already set) to fire in ERTO.
When TIMEOUT_ALARM fires:
1. Set ANY_LOSS = false;
2. For each sending flow in the session, and for each entry in that
flow's SEND_QUEUE:
1. If entry.IN_FLIGHT is true: set ANY_LOSS = true; and
2. Set entry.IN_FLIGHT to false.
3. If ANY_LOSS is true: perform ERTO backoff (Section 3.5.2.1); and
Thornburgh Expires July 8, 2013 [Page 73]

Internet-Draft Adobe RTMFP January 2013
4. Notify the congestion control and avoidance algorithms of the
timeout and, if ANY_LOSS is true, that there was loss.
3.6.2.7. Abandoning Data
The application MAY abandon queued messages at any time and for any
reason. Example reasons include (but are not limited to): one or
more fragments of a message have remained in the SEND_QUEUE for
longer than a specified message lifetime; a fragment has been
retransmitted more than a specified retransmission limit; a prior
message on which this message depends (such as a key frame in a
prediction chain) was abandoned and not delivered.
To abandon a message fragment, set its SEND_QUEUE entry's ABANDON
flag to true. When abandoning a message fragment, abandon all
fragments of the message to which it belongs.
An abandoned fragment MUST NOT be un-abandoned.
3.6.2.7.1. Forward Sequence Number Update
Abandoned data may leave gaps in the sequence number space of a flow.
Gaps may cause the receiver to hold completely received messages for
ordered delivery to allow for retransmission of the missing
fragments. User Data chunks (Section 2.3.11) encode a Forward
Sequence Number (FSN) to instruct the receiver that sequence numbers
less than or equal to the FSN will not be transmitted or
retransmitted.
When the receiver has gaps in the received sequence number space and
no non-abandoned message fragments remain in the SEND_QUEUE, the
sender SHOULD transmit a Forward Sequence Number Update (FSN Update)
comprising a User Data chunk marked abandoned, whose sequence number
is the FSN and whose fsnOffset is 0. An FSN Update allows the
receiver to skip gaps that will not be repaired and deliver received
messages to the user. An FSN Update may be thought of as a
transmission or retransmission of abandoned sequence numbers without
actually sending the data.
The method described in Sending Data (Section 3.6.2.3) generates FSN
Updates when appropriate.
3.6.2.8. ExamplesThornburgh Expires July 8, 2013 [Page 74]

Internet-Draft Adobe RTMFP January 2013
(Section 3.6.2.3).
3.6.2.9.1. Buffer Probe
The flow sender is suspended if the most recently received buffer
advertisement is zero and the flow hasn't been rejected by the
receiver; that is, while RX_BUFFER_SIZE is zero AND EXCEPTION is
false. To guard against potentially lost acknowledgements that might
reopen the receive window, a suspended flow sender SHOULD send a
packet comprising a Buffer Probe chunk (Section 2.3.15) for this flow
from time to time.
If the receive window advertisement transitions from non-zero to
zero, the flow sender MAY send a Buffer Probe immediately and SHOULD
send a probe within one second.
The initial period between Buffer Probes SHOULD be at least one
second or ERTO, whichever is greater. The period between probes
SHOULD increase over time, but the period between probes SHOULD NOT
be more than one minute or ERTO, whichever is greater.
The flow sender SHOULD stop sending Buffer Probes if it is no longer
suspended.
3.6.2.10. Exception
The flow receiver can reject the flow at any time and for any reason.
The flow receiver sends a Flow Exception Report (Section 2.3.16) when
it has rejected a flow.
On receiving a Flow Exception Report for a sending flow:
1. If the flow is OPEN, close the flow (Section 3.6.2.11) and notify
the user that the far end reported an exception with the encoded
exception code;
2. Set the EXCEPTION flag to true; and
3. For each entry in SEND_QUEUE: set entry.ABANDONED = true.
3.6.2.11. Close
A sending flow is closed by the user or as a result of an exception.
To close an OPEN flow:
1. Move to the CLOSING state;
Thornburgh Expires July 8, 2013 [Page 77]

Internet-Draft Adobe RTMFP January 2013
2. If the SEND_QUEUE is not empty, AND the tail entry of the
SEND_QUEUE has a sequence number of NEXT_SN - 1, AND the tail
entry.EVER_SENT is false: set FINAL_SN to entry.SEQUENCE_NUMBER;
else
3. The SEND_QUEUE is empty, OR the tail entry does not have a
sequence number of NEXT_SN - 1, OR the tail entry.EVER_SENT is
true: enqueue a new SEND_QUEUE entry with entry.SEQUENCE_NUMBER =
flow.NEXT_SN, entry.FRA = 0, and entry.ABANDONED = true, and set
flow.FINAL_SN to entry.SEQUENCE_NUMBER.
A CLOSING sending flow is complete when its SEND_QUEUE transitions to
empty, indicating that all sequence numbers including the FINAL_SN
have been acknowledged by the other end.
When a CLOSING sending flow becomes complete, move to the
COMPLETE_LINGER state.
A sending flow MUST remain in the COMPLETE_LINGER state for at least
130 seconds. After at least 130 seconds, move to the CLOSED state.
The sending flow is now closed, its resources can be reclaimed, and
its FLOW_ID MAY be used for a new sending flow.
3.6.3. Receiver
Each receiving flow comprises the flow-specific information context
necessary to receive that flow's messages from the sending end and
deliver completed messages to the user. Each receiving flow context
includes at least:
o FLOW_ID: this flow's identifier;
o SEQUENCE_SET: the set of all sequence numbers seen in this
receiving flow, whether received or abandoned, initially empty;
o FINAL_SN: the final sequence number of the flow, initially having
no value;
o RECV_BUFFER: the message fragments waiting to be delivered to the
user, sorted by sequence number in ascending order, initially
empty; each message fragment entry comprising:
* SEQUENCE_NUMBER: the sequence number of this fragment;
* DATA: this fragment's user data; and
* FRA: the fragment control value for this message fragment,
having one of the values enumerated for that purpose in User
Thornburgh Expires July 8, 2013 [Page 78]

Internet-Draft Adobe RTMFP January 2013
Data (Section 2.3.11).
o BUFFERED_SIZE: the sum of the lengths of each fragment in
RECV_BUFFER plus any additional storage overhead for the fragments
incurred by the implementation, in bytes;
o BUFFER_CAPACITY: the desired maximum size for the receive buffer,
in bytes;
o PREV_RWND: the most recent receive window advertisement sent in an
acknowledgement, in 1024-byte blocks, initially having no value;
o SHOULD_ACK: whether or not an acknowledgement should be sent for
this flow, initially false;
o EXCEPTION_CODE: the exception code to report to the sender when
the flow has been rejected, initially 0;
o The state, at any time being one of the following values: OPEN,
REJECTED, COMPLETE_LINGER, CLOSED.
3.6.3.1. Startup
A new receiving flow starts on receipt of a User Data chunk
(Section 2.3.11) encoding a flow ID not belonging to any other
receiving flow in the same session in the OPEN, REJECTED, or
COMPLETE_LINGER states.
On receipt of such a User Data chunk:
1. Set temporary variables METADATA, ASSOCIATED_FLOWID, and
ASSOCIATION to each have no value;
2. Create a new receiving flow context in this session, setting its
FLOW_ID to the flow ID encoded in the opening User Data chunk,
and set to the OPEN state;
3. If the opening User Data chunk encodes a User's Per-Flow
Metadata option (Section 2.3.11.1.1), set METADATA to
option.userMetadata;
4. If the opening User Data chunk encodes a Return Flow Association
option (Section 2.3.11.1.2), set ASSOCIATED_FLOWID to
option.flowID;
5. If METADATA has no value, the receiver MUST reject the flow
(Section 3.6.3.7), moving it to the REJECTED state;
Thornburgh Expires July 8, 2013 [Page 79]

Internet-Draft Adobe RTMFP January 2013
6. If ASSOCIATED_FLOWID has a value, then if there is no sending
flow in the same session with a flow ID of ASSOCIATED_FLOWID,
the receiver MUST reject the flow, moving it to the REJECTED
state; otherwise set ASSOCIATION to the indicated sending flow;
7. If ASSOCIATION indicates a sending flow AND that sending flow's
state is not OPEN, the receiver MUST reject this receiving flow,
moving it to the REJECTED state;
8. If the opening User Data chunk encodes any unrecognized option
with a type code less than 8192 (Section 2.3.11.1), the receiver
MUST reject the flow, moving it to the REJECTED state;
9. If this new receiving flow is still OPEN, then: notify the user
that a new receiving flow has opened, including the METADATA
and, if present, the ASSOCIATION, and set flow.BUFFER_CAPACITY
according to the user;
10. Perform the normal data processing (Section 3.6.3.2) for the
opening User Data chunk; and
11. Set this session's ACK_NOW to true.
3.6.3.2. Receiving Data
A User Data chunk (Section 2.3.11) or a Next User Data chunk
(Section 2.3.12) encodes one fragment of a user data message of a
flow, as well as the flow's Forward Sequence Number and potentially
optional parameters (Section 2.3.11.1).
On receipt of a User Data or Next User Data chunk:
1. If chunk.flowID doesn't indicate an existing receiving flow in
the same session in the OPEN, REJECTED, or COMPLETE_LINGER
state, perform the steps at Startup (Section 3.6.3.1) to start a
new receiving flow;
2. Retrieve the receiving flow context for the flow indicated by
chunk.flowID;
3. Set flow.SHOULD_ACK to true;
4. If the flow is OPEN AND the chunk encodes any unrecognized
option with a type code less than 8192 (Section 2.3.11.1), the
flow MUST be rejected: notify the user of an exception, and
reject the flow (Section 3.6.3.7), moving it to the REJECTED
state;
Thornburgh Expires July 8, 2013 [Page 80]

Internet-Draft Adobe RTMFP January 2013
5. If the flow is not in the OPEN state: set session.ACK_NOW to
true;
6. If flow.PREV_RWND has a value and that value is less than 2
blocks, set session.ACK_NOW to true;
7. If chunk.abandon is true: set session.ACK_NOW to true;
8. If flow.SEQUENCE_SET has any gaps (that is, if it doesn't
contain every sequence number from 0 through and including the
highest sequence number in the set), set session.ACK_NOW to
true;
9. If flow.SEQUENCE_SET contains chunk.sequenceNumber, then this
chunk is a duplicate: set session.ACK_NOW to true;
10. If flow.SEQUENCE_SET doesn't contain chunk.sequenceNumber, AND
chunk.final is true, AND flow.FINAL_SN has no value, then: set
flow.FINAL_SN to chunk.sequenceNumber, and set session.ACK_NOW
to true;
11. If the flow is in the OPEN state, AND flow.SEQUENCE_SET doesn't
contain chunk.sequenceNumber, AND chunk.abandon is false, then:
create a new RECV_BUFFER entry for this chunk's data and set
entry.SEQUENCE_NUMBER to chunk.sequenceNumber, entry.DATA to
chunk.userData, and entry.FRA to chunk.fragmentControl, and
insert this new entry into flow.RECV_BUFFER;
12. Add to flow.SEQUENCE_SET the range of sequence numbers from 0
through and including the chunk.forwardSequenceNumber derived
field;
13. Add chunk.sequenceNumber to flow.SEQUENCE_SET;
14. If flow.SEQUENCE_SET now has any gaps, set session.ACK_NOW to
true;
15. If session.ACK_NOW is false and session.DELACK_ALARM is not set:
set session.DELACK_ALARM to fire in 200 milliseconds; and
16. Attempt delivery of completed messages in this flow's
RECV_BUFFER to the user (Section 3.6.3.3).
After processing all chunks in a packet containing at least one User
Data chunk, increment session.RX_DATA_PACKETS by one. If
session.RX_DATA_PACKETS is at least two, set session.ACK_NOW to true.
A receiving flow that is not in the CLOSED state is ready to send an
Thornburgh Expires July 8, 2013 [Page 81]

Internet-Draft Adobe RTMFP January 2013
acknowledgement if its SHOULD_ACK flag is set. Acknowledgements for
receiving flows that are ready are sent either opportunistically by
piggybacking on a packet that's already sending user data or an
acknowledgement (Section 3.6.3.4.6), or when the session's ACK_NOW
flag is set (Section 3.6.3.4.5).
3.6.3.3. Buffering and Delivering Data
A receiving flow's information context contains a RECV_BUFFER for
reordering, reassembling, and holding the user data messages of the
flow. Only complete messages are delivered to the user; an
implementation MAY also deliver partially received messages BUT ONLY
by special arrangement with the user.
Let the Cumulative Acknowledgement Sequence Number CSN be the highest
number in the contiguous range of numbers in SEQUENCE_SET starting
with 0. For example, if SEQUENCE_SET contains {0, 1, 2, 3, 5, 6},
the contiguous range starting with 0 is 0..3, so the CSN is 3.
A message is complete if all of its fragments are present in the
RECV_BUFFER. The fragments of one message have contiguous sequence
numbers. A message can either be a single fragment, whose fragment
control value is 0-whole, or can be two or more fragments where the
first's fragment control value is 1-begin, followed by zero or more
fragments with control value 3-middle, and terminated by a last
fragment with control value 2-end.
An incomplete message segment is a contiguous sequence of one or more
fragments that do not form a complete message; that is, a 1-begin
followed by zero or more 3-middle fragments but with no 2-end, or
zero or more 3-middle fragments followed by a 2-end but with no
1-begin, or one or more 3-middle fragments with neither a 1-begin nor
a 2-end.
Incomplete message segments can either be in progress or abandoned.
An incomplete segment is abandoned in the following cases:
o The sequence number of the segment's first fragment is less than
or equal to the CSN AND that fragment's control value is not
1-begin; or
o The sequence number of the segment's last fragment is less than
the CSN.
Abandoned message segments will never be completed, so they SHOULD be
removed from the RECV_BUFFER to make room in the advertised receive
window and the receiver's memory for messages that can be completed.
Thornburgh Expires July 8, 2013 [Page 82]

Internet-Draft Adobe RTMFP January 2013
The user can suspend delivery of a flow's messages. A suspended
receiving flow holds completed messages in its RECV_BUFFER until the
user resumes delivery. A suspended flow can cause the receive window
advertisement to go to zero even when the BUFFER_CAPACITY is non-
zero; this is described in detail in Flow Control (Section 3.6.3.5).
When the receiving flow is not suspended, the original queuing order
of the messages is recovered by delivering, in ascending sequence
number order, complete messages in the RECV_BUFFER whose sequence
numbers are less than or equal to the CSN.
The following describes a method for discarding abandoned message
segments and delivering complete messages in original queueing order
when the receiving flow is not suspended.
While the first fragment entry in the RECV_BUFFER has a sequence
number less than or equal to CSN and delivery is still possible:
1. If entry.FRA is 0-whole: deliver entry.DATA to the user, and
remove this entry from RECV_BUFFER; otherwise,
2. If entry.FRA is 2-end or 3-middle: this entry belongs to an
abandoned segment, so remove and discard this entry from
RECV_BUFFER; otherwise,
3. Entry.FRA is 1-begin. Let LAST_ENTRY be the last RECV_BUFFER
entry that is part of this message segment (LAST_ENTRY can be
entry if the segment has only one fragment so far). Then:
1. If LAST_ENTRY.FRA is 2-end: this segment is a complete
message, so concatenate the DATA fields of each fragment
entry of this segment in ascending sequence number order and
deliver the complete message to the user, then remove the
entries for this complete message from RECV_BUFFER;
otherwise,
2. If LAST_ENTRY.SEQUENCE_NUMBER is less than CSN: this segment
is incomplete and abandoned, so remove and discard the
entries for this segment from RECV_BUFFER; otherwise,
3. LAST_ENTRY.SEQUENCE_NUMBER is equal to CSN and LAST_ENTRY.FRA
is not 2-end: this segment is incomplete but still in
progress. Ordered delivery is no longer possible until at
least one more fragment is received. Stop.
If flow.FINAL_SN has a value and is equal to CSN, AND RECV_BUFFER is
empty: all complete messages have been delivered to the user, so
notify the user that the flow is complete.
Thornburgh Expires July 8, 2013 [Page 83]

Internet-Draft Adobe RTMFP January 20133.6.3.4. Acknowledging Data
A flow receiver SHOULD acknowledge all user data sequence numbers
seen in that flow. Acknowledgements drive the sender's congestion
control and avoidance algorithms, clear data from the sender's
buffers, and in some sender implementations clock new data into the
network, and therefore must be accurate and timely.
3.6.3.4.1. Timing
For similar reasons as discussed in RFC 1122 Section 4.2.3.2
[RFC1122], it is advantageous to delay sending acknowledgements for a
short time so that multiple data fragments can be acknowledged in a
single transmission. However, it is also advantageous for a sender
to receive timely notification about the receiver's disposition of
the flow, particularly in unusual or exceptional circumstances, so
that the circumstances can be addressed if possible.
Therefore, a flow receiver SHOULD send an acknowledgement for a flow
as soon as is practical in any of the following circumstances:
o On receipt of a User Data chunk that starts a new flow;
o On receipt of a User Data or Next User Data chunk if the flow is
not in the OPEN state;
o On receipt of a User Data chunk where, before processing the
chunk, the SEQUENCE_SET of the indicated flow does not contain
every sequence number between 0 and the highest sequence number in
the set (that is, if there was a sequence number gap before
processing the chunk);
o On receipt of a User Data chunk where, after processing the chunk,
the flow's SEQUENCE_SET does not contain every sequence number
between 0 and the highest sequence number in the set (that is, if
this chunk causes a sequence number gap);
o On receipt of a Buffer Probe for the flow;
o On receipt of a User Data chunk if the last acknowledgement sent
for the flow indicated fewer than two bufferBlocksAvailable;
o On receipt of a User Data or Next User Data chunk for the flow if,
after processing the chunk, the flow's BUFFER_CAPACITY is not at
least 1024 bytes greater than BUFFERED_SIZE;
o On receipt of a User Data or Next User Data chunk for any sequence
number that was already seen (that is, on receipt of a duplicate);
Thornburgh Expires July 8, 2013 [Page 84]

Internet-Draft Adobe RTMFP January 2013
o On the first receipt of the final sequence number of the flow;
o On receipt of two packets in the session containing user data for
any flows since an acknowledgement was last sent; the new
acknowledgements being for the flows having any User Data chunks
in the received packets (that is, for every second packet
containing user data);
o After receipt of a User Data chunk for the flow, if an
acknowledgement for any other flow is being sent (that is,
consolidate acknowledgements);
o After receipt of a User Data chunk for the flow, if any user data
for a sending flow is being sent in a packet and if there is space
available in the same packet (that is, attempt to piggyback an
acknowledgement with user data if possible);
o No longer than 200 milliseconds after receipt of a User Data chunk
for the flow.
3.6.3.4.2. Size and Truncation
Including an encoded acknowledgement in a packet might cause the
packet to exceed the path MTU. In that case:
o If the packet is being sent primarily to send an acknowledgement
AND this is the first acknowledgement in the packet, truncate the
acknowledgement so that the packet does not exceed the path MTU;
otherwise
o The acknowledgement is being piggybacked in a packet with user
data or with an acknowledgement for another flow: do not include
this acknowledgement in the packet, and send it later.
3.6.3.4.3. Constructing
The Data Acknowledgement Bitmap chunk (Section 2.3.13) and Data
Acknowledgement Ranges chunk (Section 2.3.14) encode a receiving
flow's SEQUENCE_SET and its receive window advertisement. The two
chunks are semantically equivalent; implementations SHOULD send
whichever provides the most compact encoding of the SEQUENCE_SET.
When assembling an acknowledgement for a receiving flow:
1. If the flow's state is REJECTED, first assemble a Flow Exception
Report chunk (Section 2.3.16) for flow.flowID;
Thornburgh Expires July 8, 2013 [Page 85]

Internet-Draft Adobe RTMFP January 2013
2. Choose the acknowledgement chunk type that most compactly encodes
flow.SEQUENCE_SET;
3. Use the method described in Flow Control (Section 3.6.3.5) to
determine the value for the acknowledgement chunk's
bufferBlocksAvailable field;
3.6.3.4.4. Delayed Acknowledgement
As discussed in Acknowledging Data (Section 3.6.3.4.1), a flow
receiver can delay sending an acknowledgement for up to 200
milliseconds after receiving user data. The method described in
Receiving Data (Section 3.6.3.2) sets the session's DELACK_ALARM.
When DELACK_ALARM fires: set ACK_NOW to true.
3.6.3.4.5. Obligatory Acknowledgement
One or more acknowledgements should be sent as soon as is practical
when the session's ACK_NOW flag is set. When the ACK_NOW flag is
set:
1. Choose a receiving flow that is ready to send an acknowledgement;
2. If there is no such flow: there is no work to do, set ACK_NOW to
false, set RX_DATA_PACKETS to 0, clear the DELACK_ALARM, and
stop; otherwise
3. Start a new packet;
4. Assemble an acknowledgement for the flow and include it in the
packet, truncating it if necessary so that the packet doesn't
exceed the path MTU;
5. Set flow.SHOULD_ACK to false;
6. Set flow.PREV_RWND to the bufferBlocksAvailable field of the
included acknowledgement chunk;
7. Attempt to piggyback acknowledgements for any other flows that
are ready to send an acknowledgement into the packet, as
described below; and
8. Send the packet.
Thornburgh Expires July 8, 2013 [Page 86]

Internet-Draft Adobe RTMFP January 20133.6.3.4.6. Opportunistic Acknowledgement
When sending a packet with user data or an acknowledgement, any other
receiving flows that are ready to send an acknowledgement should
include their acknowledgements in the packet if possible.
To piggyback acknowledgements in a packet that is already being sent,
where the packet contains user data or an acknowledgement: While
there is at least one receiving flow that is ready to send an
acknowledgement:
1. Assemble an acknowledgement for the flow;
2. If the acknowledgement cannot be included in the packet without
exceeding the path MTU: the packet is full, stop; otherwise
3. Include the acknowledgement in the packet;
4. Set flow.SHOULD_ACK to false;
5. Set flow.PREV_RWND to the bufferBlocksAvailable field of the
included acknowledgement chunk; and
6. If there are no longer any receiving flows in the session that
are ready to send an acknowledgement: set session.ACK_NOW to
false, set session.RX_DATA_PACKETS to 0, and clear
session.DELACK_ALARM.
3.6.3.4.7. ExampleThornburgh Expires July 8, 2013 [Page 87]

Internet-Draft Adobe RTMFP January 2013
Receiver
1 |<--- Data ID=3, seq#=29, fsnOff=11 (fsn=18)
2 |<--- Data ID=3, seq#=30, fsnOff=12 (fsn=18)
3 |---> Ack ID=3, seq:0-30
4 |<--- Data ID=3, seq#=32, fsnOff=12 (fsn=20)
5 |---> Ack ID=3, seq:0-30, 32
6 |<--- Data ID=3, seq#=34, fsnOff=12 (fsn=22)
7 |---> Ack ID=3, seq:0-30, 32, 34
| :
8 |<--- Data ID=3, seq#=46, fsnOff=16 (fsn=30)
9 |---> Ack ID=3, seq:0-30, 32, 34-46
10 |<--- Data ID=3, seq#=47, fsnOff=15 (fsn=32)
11 |---> Ack ID=3, seq:0-32, 34-47
12 |<--- Data ID=3, seq#=33, fsnOff=1 (fsn=32)
13 |---> Ack ID=3, seq#=0-47
14 |<--- Data ID=3, seq#=48, fsnOff=16 (fsn=32)
15 |<--- Data ID=3, seq#=49, fsnOff=17 (fsn=32)
16 |---> Ack ID=3, seq#=0-49
| :
Flow with sequence numbers 31 and 33 lost in transit, 31 abandoned
and 33 retransmitted.
3.6.3.5. Flow Control
The flow receiver maintains a buffer for reassembling and reordering
messages for delivery to the user (Section 3.6.3.3). The
implementation and the user may wish to limit the amount of resources
(including buffer memory) that a flow is allowed to use.
RTMFP provides a means for each receiving flow to govern the amount
of data sent by the sender, by way of the bufferBytesAvailable
derived field of acknowledgement chunks (Section 2.3.13,
Section 2.3.14). This derived field indicates the amount of data
that the sender is allowed to have outstanding in the network, until
instructed otherwise. This amount is also called the receive window.
The flow receiver can suspend the sender by advertising a closed
(zero length) receive window.
The user can suspend delivery of messages from the receiving flow
(Section 3.6.3.3). This can cause the receive buffer to fill.
In order for progress to be made on completing a fragmented message
or repairing a gap for sequenced delivery in a flow, the flow
receiver MUST advertise at least one buffer block in an
acknowledgement if it is not suspended, even if the amount of data in
the buffer exceeds the buffer capacity, unless the buffer capacity is
Thornburgh Expires July 8, 2013 [Page 88]

Internet-Draft Adobe RTMFP January 2013
0. Otherwise, deadlock can occur, as the receive buffer will stay
full and won't drain because of a gap or incomplete message, and the
gap or incomplete message can't be repaired or completed because the
sender is suspended.
The receive window is advertised in units of 1024-byte blocks. For
example, advertisements for 1 byte, 1023 bytes, and 1024 bytes each
require one block. An advertisement for 1025 bytes requires two
blocks.
The following describes the RECOMMENDED method of calculating the
bufferBlocksAvailable field of an acknowledgement chunk for a
receiving flow:
1. If BUFFERED_SIZE is greater than or equal to BUFFER_CAPACITY: set
ADVERTISE_BYTES to 0;
2. If BUFFERED_SIZE is less than BUFFER_CAPACITY: set
ADVERTISE_BYTES to BUFFER_CAPACITY - BUFFERED_SIZE;
3. Set ADVERTISE_BLOCKS to CEIL(ADVERTISE_BYTES / 1024);
4. If ADVERTISE_BLOCKS is 0, AND BUFFER_CAPACITY is greater than 0,
AND delivery to the user is not suspended: set ADVERTISE_BLOCKS
to 1; and
5. Set the acknowledgement's bufferBlocksAvailable field to
ADVERTISE_BLOCKS.
3.6.3.6. Receiving a Buffer Probe
A Buffer Probe chunk (Section 2.3.15) is sent by the flow sender
(Section 3.6.2.9.1) to request the current receive window
advertisement (in the form of an acknowledgement) from the flow
receiver.
On receipt of a Buffer Probe chunk:
1. If chunk.flowID doesn't belong to a receiving flow in the same
session in the OPEN, REJECTED, or COMPLETE_LINGER state: ignore
this Buffer Probe; otherwise,
2. Retrieve the receiving flow context for the flow indicated by
chunk.flowID; then
3. Set flow.SHOULD_ACK to true; and
Thornburgh Expires July 8, 2013 [Page 89]

Internet-Draft Adobe RTMFP January 2013
4. Set session.ACK_NOW to true.
3.6.3.7. Rejecting a Flow
A receiver can reject an OPEN flow at any time and for any reason.
To reject a receiving flow in the OPEN state:
1. Move to the REJECTED state;
2. Discard all entries in flow.RECV_BUFFER, as they are no longer
relevant;
3. If the user rejected the flow, set flow.EXCEPTION_CODE to the
exception code indicated by the user; otherwise the flow was
rejected automatically by the implementation, so the exception
code is 0;
4. Set flow.SHOULD_ACK to true; and
5. Set session.ACK_NOW to true.
The receiver indicates that it has rejected a flow by sending a Flow
Exception Report chunk (Section 2.3.16) with every acknowledgement
(Section 3.6.3.4.3) for a flow in the REJECTED state.
3.6.3.8. Close
A receiving flow is complete when every sequence number from 0
through and including the final sequence number has been received;
that is, when flow.FINAL_SN has a value and flow.SEQUENCE_SET
contains every sequence number from 0 through flow.FINAL_SN,
inclusive.
When an OPEN or REJECTED receiving flow becomes complete, move to the
COMPLETE_LINGER state, set flow.SHOULD_ACK to true, and set
session.ACK_NOW to true.
A receiving flow SHOULD remain in the COMPLETE_LINGER state for 120
seconds. After 120 seconds, move to the CLOSED state. The receiving
flow is now closed, and its resources can be reclaimed once all
complete messages in flow.RECV_BUFFER have been delivered to the user
(Section 3.6.3.3). The same flow ID might be used for a new flow by
the sender after this point.
Discussion: The flow sender detects that the flow is complete on
receiving an acknowledgement of all sequence numbers of the flow.
This can't happen until after the receiver has detected that the flow
is complete and acknowledged all of the sequence numbers. The
Thornburgh Expires July 8, 2013 [Page 90]

Internet-Draft Adobe RTMFP January 2013
receiver's COMPLETE_LINGER period is two minutes (one Maximum Segment
Lifetime (MSL)), which allows any in-flight packets to drain from the
network without being misidentified, and gives the sender an
opportunity to retransmit any sequence numbers if the completing
acknowledgement is lost. The sender's COMPLETE_LINGER period is at
least two minutes plus 10 seconds, and doesn't begin until the
completing acknowledgement is received; therefore, the same flow
identifier won't be re-used by the flow sender for a new sending flow
for at least 10 seconds after the flow receiver has closed the
receiving flow context. This ensures correct operation independent
of network delay and even when the sender's clock runs up to 8
percent faster than the receiver's.
4. IANA Considerations
This memo specifies chunk type code values (Section 2.3) and User
Data option type code values (Section 2.3.11.1). These type code
values are assigned and maintained by Adobe. Therefore, this memo
has no IANA actions.
5. Security Considerations
This memo specifies a general framework that can be used to establish
a confidential and authenticated session between endpoints. A
Cryptography Profile, not specified herein, defines the cryptographic
algorithms, data formats, and semantics as used within this
framework. Designing a Cryptography Profile to ensure that
communications are protected to the degree required by the
application-specific threat model is outside the scope of this
specification.
Section 3.5.4.2 describes an OPTIONAL method for processing a change
of network address of a communicating peer. Securely processing
address mobility using that or any substantially similar method
REQUIRES at least that the Packet Encryption function of the
Cryptography Profile (Section 2.2.3) employs a cryptographic
verification mechanism comprising secret information known only to
the two endpoints. Without this constraint, that or any
substantially similar method becomes "session hijacking support".
Flows and packet fragmentation imply semantics that could cause
unbounded resource utilization in receivers, causing a denial of
service. Implementations SHOULD guard against unbounded or excessive
resource use, and abort sessions that appear abusive.
A rogue but popular Redirector (Section 3.5.1.4) could direct session
Thornburgh Expires July 8, 2013 [Page 91]

Internet-Draft Adobe RTMFP January 2013
Initiators to flood a victim address or network with Initiator Hello
packets, potentially causing a denial of service.
An attacker that can passively observe an IHello and that possesses a
certificate matching the Endpoint Discriminator (without having to
know the private key, if any, associated with it) can deny the
Initiator access to the desired Responder by sending an RHello before
the desired Responder does, since only the first received RHello is
selected by the Initiator. The attacker needn't forge the desired
Responder's source address, since the RHello is selected based on the
tag echo and not the packet's source address. This can simplify the
attack in some network or host configurations.
6. Acknowledgements
Special thanks go to Matthew Kaufman for his contributions to the
creation and design of RTMFP.
7. Normative References
[RFC0768] Postel, J., "User Datagram Protocol", STD 6, RFC 768,
August 1980.
[RFC0791] Postel, J., "Internet Protocol", STD 5, RFC 791,
September 1981.
[RFC1122] Braden, R., "Requirements for Internet Hosts -
Communication Layers", STD 3, RFC 1122, October 1989.
[RFC2119] Bradner, S., "Key words for use in RFCs to Indicate
Requirement Levels", BCP 14, RFC 2119, March 1997.
[RFC2460] Deering, S. and R. Hinden, "Internet Protocol, Version 6
(IPv6) Specification", RFC 2460, December 1998.
[RFC2914] Floyd, S., "Congestion Control Principles", BCP 41,
RFC 2914, September 2000.
[RFC4821] Mathis, M. and J. Heffner, "Packetization Layer Path MTU
Discovery", RFC 4821, March 2007.
[RFC5681] Allman, M., Paxson, V., and E. Blanton, "TCP Congestion
Control", RFC 5681, September 2009.
Thornburgh Expires July 8, 2013 [Page 92]