GENWiki

Premier IT Outsourcing and Support Services within the UK

User Tools

Site Tools


rfc:rfc7016

Internet Engineering Task Force (IETF) M. Thornburgh Request for Comments: 7016 Adobe Category: Informational November 2013 ISSN: 2070-1721

            Adobe's Secure Real-Time Media Flow Protocol

Abstract

 This memo describes Adobe's 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
 that make 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 document is not an Internet Standards Track specification; it is
 published for informational purposes.
 This document is a product of the Internet Engineering Task Force
 (IETF).  It has been approved for publication by the Internet
 Engineering Steering Group (IESG).  Not all documents approved by the
 IESG are a candidate for any level of Internet Standard; see Section
 2 of RFC 5741.
 Information about the current status of this document, any errata,
 and how to provide feedback on it may be obtained at
 http://www.rfc-editor.org/info/rfc7016.

IESG Note

 This document represents technology developed outside the processes
 of the IETF and the IETF community has determined that it is useful
 to publish it as an RFC in its current form.  It is a product of the
 IETF only in that it has received public review and has been approved
 for publication by the Internet Engineering Steering Group (IESG),
 but the content of the document does not represent a consensus of the
 IETF.

Thornburgh Informational [Page 1] RFC 7016 Adobe RTMFP November 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
 carefully, as they describe your rights and restrictions with respect
 to this document.  Code Components extracted from this document must
 include Simplified BSD License text as described in Section 4.e of
 the Trust Legal Provisions and are provided without warranty as
 described in the Simplified BSD License.
 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.

Table of Contents

 1. Introduction ....................................................5
    1.1. Design Highlights of RTMFP .................................6
    1.2. Terminology ................................................7
 2. Syntax ..........................................................8
    2.1. Common Elements ............................................8
         2.1.1. Elementary Types and Constructs .....................8
         2.1.2. Variable Length Unsigned Integer (VLU) .............10
         2.1.3. Option .............................................10
         2.1.4. Option List ........................................11
         2.1.5. Internet Socket Address (Address) ..................12
    2.2. Network Layer .............................................13
         2.2.1. Encapsulation ......................................13
         2.2.2. Multiplex ..........................................13
         2.2.3. Encryption .........................................14
         2.2.4. Packet .............................................15
    2.3. Chunks ....................................................18
         2.3.1. Packet Fragment Chunk ..............................20
         2.3.2. Initiator Hello Chunk (IHello) .....................21
         2.3.3. Forwarded Initiator Hello Chunk (FIHello) ..........22
         2.3.4. Responder Hello Chunk (RHello) .....................23
         2.3.5. Responder Redirect Chunk (Redirect) ................24
         2.3.6. RHello Cookie Change Chunk .........................26
         2.3.7. Initiator Initial Keying Chunk (IIKeying) ..........27
         2.3.8. Responder Initial Keying Chunk (RIKeying) ..........29
         2.3.9. Ping Chunk .........................................31
         2.3.10. Ping Reply Chunk ..................................32

Thornburgh Informational [Page 2] RFC 7016 Adobe RTMFP November 2013

         2.3.11. User Data Chunk ...................................33
                2.3.11.1. Options for User Data ....................35
                         2.3.11.1.1. User's Per-Flow Metadata ......35
                         2.3.11.1.2. Return Flow Association .......36
         2.3.12. Next User Data Chunk ..............................37
         2.3.13. Data Acknowledgement Bitmap Chunk (Bitmap Ack) ....39
         2.3.14. Data Acknowledgement Ranges Chunk (Range Ack) .....41
         2.3.15. Buffer Probe Chunk ................................43
         2.3.16. Flow Exception Report Chunk .......................43
         2.3.17. Session Close Request Chunk (Close) ...............44
         2.3.18. Session Close Acknowledgement Chunk (Close Ack) ...44
 3. Operation ......................................................45
    3.1. Overview ..................................................45
    3.2. Endpoint Identity .........................................46
    3.3. Packet Multiplex ..........................................48
    3.4. Packet Fragmentation ......................................48
    3.5. Sessions ..................................................50
         3.5.1. Startup ............................................53
                3.5.1.1. Normal Handshake ..........................53
                         3.5.1.1.1. Initiator ......................54
                         3.5.1.1.2. Responder ......................55
                3.5.1.2. Cookie Change .............................57
                3.5.1.3. Glare .....................................59
                3.5.1.4. Redirector ................................60
                3.5.1.5. Forwarder .................................61
                3.5.1.6. Redirector and Forwarder with NAT .........63
                3.5.1.7. Load Distribution and Fault Tolerance .....66
         3.5.2. Congestion Control .................................67
                3.5.2.1. Time Critical Reverse Notification ........68
                3.5.2.2. Retransmission Timeout ....................68
                3.5.2.3. Burst Avoidance ...........................71
         3.5.3. Address Mobility ...................................71
         3.5.4. Ping ...............................................72
                3.5.4.1. Keepalive .................................72
                3.5.4.2. Address Mobility ..........................73
                3.5.4.3. Path MTU Discovery ........................74
         3.5.5. Close ..............................................74
    3.6. Flows .....................................................75
         3.6.1. Overview ...........................................75
                3.6.1.1. Identity ..................................75
                3.6.1.2. Messages and Sequencing ...................76
                3.6.1.3. Lifetime ..................................77

Thornburgh Informational [Page 3] RFC 7016 Adobe RTMFP November 2013

         3.6.2. Sender .............................................78
                3.6.2.1. Startup ...................................80
                3.6.2.2. Queuing Data ..............................80
                3.6.2.3. Sending Data ..............................81
                         3.6.2.3.1. Startup Options ................83
                         3.6.2.3.2. Send Next Data .................83
                3.6.2.4. Processing Acknowledgements ...............83
                3.6.2.5. Negative Acknowledgement and Loss .........84
                3.6.2.6. Timeout ...................................85
                3.6.2.7. Abandoning Data ...........................86
                         3.6.2.7.1. Forward Sequence Number
                                    Update .........................86
                3.6.2.8. Examples ..................................87
                3.6.2.9. Flow Control ..............................89
                         3.6.2.9.1. Buffer Probe ...................89
                3.6.2.10. Exception ................................89
                3.6.2.11. Close ....................................90
         3.6.3. Receiver ...........................................90
                3.6.3.1. Startup ...................................93
                3.6.3.2. Receiving Data ............................94
                3.6.3.3. Buffering and Delivering Data .............95
                3.6.3.4. Acknowledging Data ........................97
                         3.6.3.4.1. Timing .........................98
                         3.6.3.4.2. Size and Truncation ............99
                         3.6.3.4.3. Constructing ...................99
                         3.6.3.4.4. Delayed Acknowledgement .......100
                         3.6.3.4.5. Obligatory Acknowledgement ....100
                         3.6.3.4.6. Opportunistic
                                    Acknowledgement ...............100
                         3.6.3.4.7. Example .......................101
                3.6.3.5. Flow Control .............................102
                3.6.3.6. Receiving a Buffer Probe .................103
                3.6.3.7. Rejecting a Flow .........................103
                3.6.3.8. Close ....................................104
 4. IANA Considerations ...........................................104
 5. Security Considerations .......................................105
 6. Acknowledgements ..............................................106
 7. References ....................................................107
    7.1. Normative References .....................................107
    7.2. Informative References ...................................107
 Appendix A. Example Congestion Control Algorithm .................108
   A.1. Discussion ................................................108
   A.2. Algorithm .................................................110

Thornburgh Informational [Page 4] RFC 7016 Adobe RTMFP November 2013

1. Introduction

 Adobe's Secure Real-Time Media Flow Protocol (RTMFP) is intended for
 use as a general purpose 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 that 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.
 RTMFP is implemented in Flash Player, Adobe Integrated Runtime (AIR),
 and Adobe Media Server (AMS, formerly Flash Media Server or FMS), all
 from Adobe Systems Incorporated, and is used as the foundation
 transport protocol for real-time video, audio, and data
 communication, both client-server and P2P, in those products.  At the
 time of writing, the Adobe Flash Player runtime is installed on more
 than one billion end-user desktop computers.
 RTMFP was developed by Adobe Systems Incorporated and is not the
 product of an IETF activity.
 This memo describes the syntax and operation of the Secure Real-Time
 Media Flow Protocol.
 This memo describes a general security framework that, when combined
 with an application-specific Cryptography Profile, can be used to
 establish a confidential and authenticated session between endpoints.
 The application-specific Cryptography Profile, not defined herein,
 would detail the specific cryptographic algorithms, data formats, and
 semantics to be used within this framework.  Interoperation between
 applications of RTMFP requires common or compatible Cryptography
 Profiles.
 Note to implementers: at the time of writing, the Cryptography
 Profile used by the above-mentioned Adobe products is not publicly
 described by Adobe.  Implementers should investigate the availability
 of documentation of that Cryptography Profile prior to implementing
 RTMFP for the purpose of interoperation with the above-mentioned
 Adobe products.

Thornburgh Informational [Page 5] RFC 7016 Adobe RTMFP November 2013

1.1. Design Highlights of RTMFP

 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 can have concurrent sessions with multiple
 other far endpoints.
 Design highlights of RTMFP include the following:
 o  The security framework is an inherent part of the basic protocol.
    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
    according to the Cryptography Profile.
 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).
 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.

Thornburgh Informational [Page 6] RFC 7016 Adobe RTMFP November 2013

 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) are 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).
 The syntax of the protocol is detailed in Section 2.  The operation
 of the protocol is detailed in Section 3.

1.2. Terminology

 The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
 "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and
 "OPTIONAL" in this document are to be interpreted as described in
 [RFC2119].

Thornburgh Informational [Page 7] RFC 7016 Adobe RTMFP November 2013

2. Syntax

 Definitions of types and structures in this specification use
 traditional text diagrams paired with procedural descriptions using a
 C-like syntax.  The C-like procedural descriptions SHALL be construed
 as definitive.
 Structures are packed to take only as many bytes as explicitly
 indicated.  There is no 32-bit alignment constraint, and fields are
 not padded for alignment unless explicitly indicated or described.
 Text diagrams may include a bit ruler across the top; this is a
 convenience for counting bits in individual fields and does not
 necessarily imply field alignment on a multiple of the ruler width.
 Unless specified otherwise, reserved fields SHOULD be set to 0 by a
 sender and MUST be ignored by a receiver.
 The procedural syntax of this specification defines correct and
 error-free encoded inputs to a parser.  The procedural syntax does
 not describe a fully featured parser, including error detection and
 handling.  Implementations MUST include means to identify error
 circumstances, including truncations causing elementary or composed
 types to not fit inside containing structures, fields, or elements.
 Unless specified otherwise, an error circumstance SHALL abort the
 parsing and processing of an element and its enclosing elements, up
 to the containing packet.

2.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.

Thornburgh Informational [Page 8] RFC 7016 Adobe RTMFP November 2013

 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 (1 or set) or false (0 or
    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.
 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.

Thornburgh Informational [Page 9] RFC 7016 Adobe RTMFP November 2013

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;
                            +-------------/-+
                            |             \ |
                            +-------------/-+
             Figure 1: VLU Depiction in Following Diagrams
 Unless stated otherwise in this specification, implementations SHOULD
 handle VLUs encoding unsigned integers at least 64 bits in length
 (that is, encoding a maximum value of at least 2^64 - 1).

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.

Thornburgh Informational [Page 10] RFC 7016 Adobe RTMFP November 2013

 An Option can 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   |
                           +---/---/-------+
           Figure 2: Option Depiction in Following Diagrams

2.1.4. Option List

 An Option List is a sequence of zero or more non-empty Options
 terminated by a Marker.
 +~~~/~~~/~~~~~~~+               +~~~/~~~/~~~~~~~+-------------/-+
 | L \ T \   V   |...............| L \ T \   V   |       0     \ |
 +~~~/~~~/~~~~~~~+               +~~~/~~~/~~~~~~~+-------------/-+
 ^                                               ^     Marker
 +------- zero or more non-empty Options --------+ (empty Option)
 struct optionList_t
 {
     do
     {
         option_t option :variable*8;
     } while(option.length > 0);
 } :variable*8;

Thornburgh Informational [Page 11] RFC 7016 Adobe RTMFP November 2013

2.1.5. Internet Socket Address (Address)

 When communicating an Internet socket address (a combination of a
 32-bit IPv4 [RFC0791] or 128-bit IPv6 [RFC2460] address and a 16-bit
 port number) to another RTMFP, this encoding is used.  This encoding
 additionally allows an address to be tagged with an origin type,
 which an RTMFP MAY use to modify the use or disposition of the
 address.
                                                      1
  0 1 2 3 4 5 6 7                 0 1 2 3 4 5 6 7|8 9 0 1 2 3 4 5
 +-+-+-+-+-+-+-+-+-----/.../-----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |I|         | O |    Internet   |                               |
 |P|0 0 0 0 0| R |    address    |              port             |
 |6|   rsv   | I |32 or 128 bits |                               |
 +-+-+-+-+-+-+-+-+-----/.../-----+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 struct address_t
 {
     bool_t  inet6    :1;     // "IP6"
     uintn_t reserved :5 = 0; // "rsv"
     uintn_t origin   :2;     // "ORI"
     if(inet6)
         uint128_t ipAddress;
     else
         uint32_t ipAddress;
     uint16_t port;
 } :variable*8;
 inet6:  If set, the Internet address is a 128-bit IPv6 address.  If
    clear, the Internet address is a 32-bit IPv4 address.
 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 observed to be the source address from which a
          packet was received (a "reflexive transport address" in the
          terminology of [RFC5389])
    3:    Address is a relay, proxy, or introducer (a Redirector
          and/or Forwarder)

Thornburgh Informational [Page 12] RFC 7016 Adobe RTMFP November 2013

 ipAddress:  The Internet address, in network byte order.
 port:  The 16-bit port number, in network byte order.

2.2. Network Layer

2.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.

2.2.2. Multiplex

  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                 Scrambled Session ID (SSID)                   |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |             e             first32[0]                          |
 |- - - - - -  n  - - - - - - - - - - - - - - - - - - - - - - - -|
 |             c             first32[1]                          |
 +- - - - - -  r  - - - - - - - - - - - - - - - - - - - - - - - -+
 |             y                                                 |
 |             pted packet                                       |
 +---------------------------------------------------------------/
 struct multiplex_t
 {
     uint32_t scrambledSessionID; // "SSID"
     union {
         uint32_t first32[2]; // see note
         uint8_t  encryptedPacket[remainder()];
     } :(encapsulation.length - 4)*8;
     // if encryptedPacket is less than 8 bytes long, treat it
     // as if it were end-padded with 0s for the following:
     sessionID = scrambledSessionID XOR first32[0] XOR first32[1];
 } :encapsulation.length*8;

Thornburgh Informational [Page 13] RFC 7016 Adobe RTMFP November 2013

 The 32-bit Scrambled Session ID is the 32-bit session ID modified by
 performing a bitwise exclusive-or with the bitwise exclusive-or of
 the first two 32-bit words of the encrypted packet.
 The session ID is a 32-bit value that the receiver has requested to
 be used by the sender when sending packets to this receiver
 (Sections 2.3.7 and 2.3.8).  The session ID identifies the session to
 which this packet belongs and the decryption key to be used to
 decrypt the encrypted packet.
 Note: Session ID 0 (prior to scrambling) denotes the startup pseudo-
 session and implies the Default Session Key.
 Note: If the encrypted packet is less than 8 bytes long, then for the
 scrambling operation, perform the exclusive-or as though the
 encrypted packet were end-padded with enough 0-bytes to bring its
 length to 8.

2.2.3. Encryption

 RTMFP packets are encrypted according to a Cryptography Profile.
 This specification doesn't define a Cryptography Profile or mandate a
 particular choice of cryptography.  The application defines the
 cryptographic syntax and algorithms.
 Packet encryption is RECOMMENDED to be a block cipher operating in
 Cipher Block Chaining [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 of packets, for example by means of a checksum or
 cryptographic message authentication code.  To mitigate replay
 attacks, data integrity SHOULD comprise duplicate packet detection,
 for example by means of a session-wide packet sequence number.  The
 packet encryption layer SHALL discard a received packet that does not
 pass integrity or authenticity tests.
 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

Thornburgh Informational [Page 14] RFC 7016 Adobe RTMFP November 2013

 non-zero session IDs during the latter phases of session startup
 (Sections 2.3.6 and 2.3.8).  See Security Considerations (Section 5)
 for more about the Default Session Key.

2.2.4. Packet

 An (unencrypted, plain) RTMFP packet consists of a variable sized
 common header, zero or more chunks, and padding.  Padding can 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 Informational [Page 15] RFC 7016 Adobe RTMFP November 2013

  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+
 |T|T| r |T|T| M |
 |C|C| s |S|S| O |
 | |R| v | |E| D |
 +-+-+-+-+-+-+-+-+
 +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+
 |        if(TS) timestamp       |     if(TSE) timestampEcho     |
 +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                             Chunk                             |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
                                 :
                                 :
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                             Chunk                             |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                            padding                            |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 struct packet_t
 {
     bool_t  timeCritical         :1; // "TC"
     bool_t  timeCriticalReverse  :1; // "TCR"
     uintn_t reserved             :2; // "rsv"
     bool_t  timestampPresent     :1; // "TS"
     bool_t  timestampEchoPresent :1; // "TSE"
     uintn_t mode                 :2; // "MOD"
     if(0 != mode)
     {
         if(timestampPresent)
             uint16_t timestamp;
         if(timestampEchoPresent)
             uint16_t timestampEcho;
         while(remainder() > 2)
         {
             uint8_t  chunkType;
             uint16_t chunkLength;
             if(remainder() < chunkLength)
                 break;
             uint8_t  chunkPayload[chunkLength];
         } // chunks
         uint8_t padding[remainder()];
     }
 } :plainPacket.length*8;

Thornburgh Informational [Page 16] RFC 7016 Adobe RTMFP November 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.  See below for additional discussion
    of packet modes.  Possible 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.2.
 chunks:  Zero or more chunks follow the header.  It is RECOMMENDED
    that a packet 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 what would be the current chunk header

indicates that the hypothetical chunk payload wouldn't fit in

       the remaining bytes of the packet.

Thornburgh Informational [Page 17] RFC 7016 Adobe RTMFP November 2013

 Packet mode 0 is not allowed.  Packets marked with this mode are
 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 are
 only allowed in packets with this mode.
 Chunks that are not for session startup are only allowed in packets
 with modes 1 or 2.

2.3. Chunks

  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |   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).

Thornburgh Informational [Page 18] RFC 7016 Adobe RTMFP November 2013

 Defined chunk types are enumerated here in the order they might be
 encountered in the course of a typical session.  The following chunk
 type codes are defined:
 0x7f:  Packet Fragment (Section 2.3.1)
 0x30:  Initiator Hello (Section 2.3.2)
 0x0f:  Forwarded Initiator Hello (Section 2.3.3)
 0x70:  Responder Hello (Section 2.3.4)
 0x71:  Responder Redirect (Section 2.3.5)
 0x79:  RHello Cookie Change (Section 2.3.6)
 0x38:  Initiator Initial Keying (Section 2.3.7)
 0x78:  Responder Initial Keying (Section 2.3.8)
 0x01:  Ping (Section 2.3.9)
 0x41:  Ping Reply (Section 2.3.10)
 0x10:  User Data (Section 2.3.11)
 0x11:  Next User Data (Section 2.3.12)
 0x50:  Data Acknowledgement Bitmap (Section 2.3.13)
 0x51:  Data Acknowledgement Ranges (Section 2.3.14)
 0x18:  Buffer Probe (Section 2.3.15)
 0x5e:  Flow Exception Report (Section 2.3.16)
 0x0c:  Session Close Request (Section 2.3.17)
 0x4c:  Session Close Acknowledgement (Section 2.3.18)
 0x00:  Ignore/Padding
 0xff:  Ignore/Padding
 A receiver MUST ignore a chunk having an unrecognized chunk type
 code.  A receiver MUST ignore a chunk appearing in a packet having a
 mode inappropriate to that chunk type.

Thornburgh Informational [Page 19] RFC 7016 Adobe RTMFP November 2013

 Unless specified otherwise, if a chunk has a syntax or processing
 error (for example, the chunk's payload field is not long enough to
 contain the specified syntax elements), the chunk SHALL be ignored as
 though it was not present in the packet, and parsing and processing
 SHALL commence with the next chunk in the packet, if any.

2.3.1. Packet Fragment Chunk

 This chunk is used to divide a plain RTMFP packet (Section 2.2.4)
 that is unavoidably larger than the path MTU (such as session startup
 packets containing Responder Hello (Section 2.3.4) or Initiator
 Initial Keying (Section 2.3.7) chunks with large certificates) into
 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 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      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 MUST be index 0.
    Fragments are numbered consecutively.

Thornburgh Informational [Page 20] RFC 7016 Adobe RTMFP November 2013

 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 is only allowed in a packet with
 Session ID 0, encrypted with the Default Session Key, and having
 packet mode 3 (Startup).
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      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.

Thornburgh Informational [Page 21] RFC 7016 Adobe RTMFP November 2013

2.3.3. Forwarded Initiator Hello Chunk (FIHello)

 This chunk is sent on behalf of an initiator by a Forwarder.  It is
 only allowed in packets of 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).
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x0f     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-------------/-+-----------------------------------------------+
 |  epdLength  \ |    endpointDiscriminator (epdLength bytes)    |
 +-------------/-+-----------------------------------------------/
 +---------------------------------------------------------------+
 |                          replyAddress                         |
 +---------------------------------------------------------------/
 +---------------------------------------------------------------+
 |                              tag                              |
 +---------------------------------------------------------------/
 struct fihelloChunkPayload_t
 {
     vlu_t     epdLength :variable*8;
     uint8_t   endpointDiscriminator[epdLength];
     address_t replyAddress :variable*8;
     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 original initiator wants to communicate, copied
    from the original Initiator Hello.
 replyAddress:  Address format (Section 2.1.5), the address that the
    forwarding node derived from the received Initiator Hello, to
    which the receiver should respond.
 tag:  Copied from the original Initiator Hello.
 The use of FIHello is detailed in Section 3.5.1.5.

Thornburgh Informational [Page 22] RFC 7016 Adobe RTMFP November 2013

2.3.4. Responder Hello Chunk (RHello)

 This chunk is sent by a responder in response to an Initiator Hello
 or Forwarded Initiator Hello if the Endpoint Discriminator indicates
 the responder's identity.  This chunk is only allowed in a packet
 with Session ID 0, encrypted with the Default Session Key, and having
 packet mode 3 (Startup).
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x70     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-------------/-+-----------------------------------------------+
 |  tagLength  \ |            tagEcho (tagLength bytes)          |
 +-------------/-+-----------------------------------------------/
 +-------------/-+-----------------------------------------------+
 | cookieLength\ |           cookie (cookieLength bytes)         |
 +-------------/-+-----------------------------------------------/
 +---------------------------------------------------------------+
 |                     responderCertificate                      |
 +---------------------------------------------------------------/
 struct rhelloChunkPayload_t
 {
     vlu_t   tagLength :variable*8;
     uint8_t tagEcho[tagLength];
     vlu_t   cookieLength :variable*8;
     uint8_t cookie[cookieLength];
     uint8_t responderCertificate[remainder()];
 } :chunkLength*8;
 tagLength:  VLU, the length of the following tagEcho field in bytes.
 tagEcho:  The tag from the Initiator Hello, unaltered.
 cookieLength:  VLU, the length of the following cookie field
    in bytes.
 cookie:  Responder-created state data to authenticate a future
    Initiator Initial Keying message (in order to prevent denial-of-
    service attacks).
 responderCertificate:  The responder's cryptographic credentials.

Thornburgh Informational [Page 23] RFC 7016 Adobe RTMFP November 2013

 Note: This specification doesn't mandate a specific choice of
 certificate format.  The Cryptography Profile determines the syntax,
 algorithms, and interpretation of the responderCertificate.
 The use of RHello is detailed in Section 3.5.1.

2.3.5. Responder Redirect Chunk (Redirect)

 This chunk is sent in response to an Initiator Hello or Forwarded
 Initiator Hello to indicate that the requested endpoint can be
 reached at one or more of the indicated addresses.  A receiver can
 add none, some, or all of the indicated addresses to the set of
 addresses to which it is sending Initiator Hello messages for the
 opening session associated with tagEcho.  This chunk is only allowed
 in a packet with Session ID 0, encrypted with the Default Session
 Key, and having packet mode 3 (Startup).

Thornburgh Informational [Page 24] RFC 7016 Adobe RTMFP November 2013

  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x71     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-------------/-+-----------------------------------------------+
 |  tagLength  \ |            tagEcho (tagLength bytes)          |
 +-------------/-+-----------------------------------------------/
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                     redirectDestination 1                     |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
                                 :
                                 :
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                     redirectDestination N                     |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 struct responderRedirectChunkPayload_t
 {
     vlu_t   tagLength :variable*8;
     uint8_t tagEcho[tagLength];
     addressCount = 0;
     while(remainder() > 0)
     {
         address_t redirectDestination :variable*8;
         addressCount++;
     }
     if(0 == addressCount)
         redirectDestination = packetSourceAddress();
 } :chunkLength*8;
 tagLength:  VLU, the length of the following tagEcho field in bytes.
 tagEcho:  The tag from the Initiator Hello, unaltered.
 redirectDestination:  (Zero or more) Address format (Section 2.1.5)
    addresses to add to the opening set for the indicated session.
 If this chunk lists zero redirectDestination addresses, then this is
 an Implied Redirect, and the indicated address is the address from
 which the packet containing this chunk was received.
 The use of Redirect is detailed in Sections 3.5.1.1.1, 3.5.1.1.2,
 and 3.5.1.4.

Thornburgh Informational [Page 25] RFC 7016 Adobe RTMFP November 2013

2.3.6. RHello Cookie Change Chunk

 This chunk SHOULD 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 that elicited the
 Responder Hello containing the original cookie).
 This chunk is only allowed 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 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      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 Informational [Page 26] RFC 7016 Adobe RTMFP November 2013

2.3.7. Initiator Initial Keying Chunk (IIKeying)

 This chunk is sent by an initiator to establish a session with a
 responder.  The initiator MUST have obtained a valid cookie to use
 with the responder, typically by receiving a Responder Hello from it.
 This chunk is only allowed in a packet with Session ID 0, encrypted
 with the Default Session Key, and having packet mode 3 (Startup).
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x38     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                       initiatorSessionID                      |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-------------/-+-----------------------------------------------+
 | cookieLength\ |                  cookieEcho                   |
 +-------------/-+-----------------------------------------------/
 +-------------/-+-----------------------------------------------+
 |  certLength \ |             initiatorCertificate              |
 +-------------/-+-----------------------------------------------/
 +-------------/-+-----------------------------------------------+
 |  skicLength \ |          sessionKeyInitiatorComponent         |
 +-------------/-+-----------------------------------------------/
 +---------------------------------------------------------------+
 |                           signature                           |
 +---------------------------------------------------------------/
 struct iikeyingChunkPayload_t
 {
     struct
     {
         uint32_t initiatorSessionID;
         vlu_t    cookieLength :variable*8;
         uint8_t  cookieEcho[cookieLength];
         vlu_t    certLength :variable*8;
         uint8_t  initiatorCertificate[certLength];
         vlu_t    skicLength :variable*8;
         uint8_t  sessionKeyInitiatorComponent[skicLength];
     } initiatorSignedParameters :variable*8;
     uint8_t signature[remainder()];
 } :chunkLength*8;
 initiatorSessionID:  The session ID to be used by the responder when
    sending packets to the initiator.

Thornburgh Informational [Page 27] RFC 7016 Adobe RTMFP November 2013

 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.

Thornburgh Informational [Page 28] RFC 7016 Adobe RTMFP November 2013

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 is only
 allowed 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.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x78     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                       responderSessionID                      |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-------------/-+-----------------------------------------------+
 |  skrcLength \ |         sessionKeyResponderComponent          |
 +-------------/-+-----------------------------------------------/
 +---------------------------------------------------------------+
 |                           signature                           |
 +---------------------------------------------------------------/
 struct rikeyingChunkPayload_t
 {
     struct
     {
         uint32_t responderSessionID;
         vlu_t    skrcLength :variable*8;
         uint8_t  sessionKeyResponderComponent[skrcLength];
     } responderSignedParametersPortion :variable*8;
     uint8_t  signature[remainder()];
 } :chunkLength*8;
 struct
 {
     responderSignedParametersPortion;
     sessionKeyInitiatorComponent;
 } responderSignedParameters;
 responderSessionID:  The session ID to be used by the initiator when
    sending packets to the responder.
 skrcLength:  VLU, the length of the following
    sessionKeyResponderComponent field in bytes.
 sessionKeyResponderComponent:  The responder's portion of the session
    key negotiation according to the Cryptography Profile.

Thornburgh Informational [Page 29] RFC 7016 Adobe RTMFP November 2013

 responderSignedParametersPortion:  The payload portion of this chunk
    up to the signature field.
 signature:  The responder's digital signature of the
    responderSignedParameters (see below) according to the
    Cryptography Profile.
 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.

Thornburgh Informational [Page 30] RFC 7016 Adobe RTMFP November 2013

2.3.9. Ping Chunk

 This chunk is sent in order to elicit a Ping Reply from the receiver.
 It is only allowed in a packet belonging to an established session
 and having packet mode 1 or 2.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x01     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                             message                           |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 struct pingChunkPayload_t
 {
     uint8_t message[chunkLength];
 } :chunkLength*8;
 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.

Thornburgh Informational [Page 31] RFC 7016 Adobe RTMFP November 2013

2.3.10. Ping Reply Chunk

 This chunk is sent in response to a Ping chunk.  It is only allowed
 in a packet belonging to an established session and having packet
 mode 1 or 2.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      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.

Thornburgh Informational [Page 32] RFC 7016 Adobe RTMFP November 2013

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.  It is only allowed in a packet belonging to an
 established session and having packet mode 1 or 2.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x10     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-+-+-+-+-+-+-+-+
 |O|r| F | r |A|F|
 |P|s| R | s |B|I|
 |T|v| A | v |N|N|
 +-+-+-+-+-+-+-+-+
 +-------------/-+-------------/-+-------------/-+
 |   flowID    \ |     seq#    \ |  fsnOffset  \ |
 +-------------/-+-------------/-+-------------/-+
 +~~~/~~~/~~~~~~~+               +~~~/~~~/~~~~~~~+-------------/-+
 | L \ T \   V   |... options ...| L \ T \   V   |       0     \ |
 \~~~/~~~/~~~~~~~+   [if(OPT)]   +~~~/~~~/~~~~~~~+-------------/-/
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                            userData                           |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 struct userDataChunkPayload_t
 {
     bool_t  optionsPresent :1;  // "OPT"
     uintn_t reserved1 :1;       // "rsv"
     uintn_t fragmentControl :2; // "FRA"
         // 0=whole, 1=begin, 2=end, 3=middle
     uintn_t reserved2 :2;       // "rsv"
     bool_t  abandon :1;         // "ABN"
     bool_t  final :1;           // "FIN"
     vlu_t   flowID :variable*8;
     vlu_t   sequenceNumber :variable*8; // "seq#"
     vlu_t   fsnOffset :variable*8;
     forwardSequenceNumber = sequenceNumber - fsnOffset;
     if(optionsPresent)
         optionList_t options :variable*8;
     uint8_t userData[remainder()];
 } :chunkLength*8;
 optionsPresent:  If set, indicates the presence of an option list
    before the user data.  If clear, there is no option list in this
    chunk.

Thornburgh Informational [Page 33] RFC 7016 Adobe RTMFP November 2013

 fragmentControl:  Indicates how this fragment is assembled,
    potentially with others, into a complete user message.  Possible
    values:
    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 fragment.
 The use of User Data is detailed in Section 3.6.2.

Thornburgh Informational [Page 34] RFC 7016 Adobe RTMFP November 2013

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.
 A flow receiver MUST reject a flow containing a flow option that is
 not understood if the option type is less than 8192 (0x2000).  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:  User'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.

Thornburgh Informational [Page 35] RFC 7016 Adobe RTMFP November 2013

2.3.11.1.2. Return Flow Association

 A new flow can 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.
 +-------------/-+-------------/-+-------------/-+
 |   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 F_OPEN sending flow.

Thornburgh Informational [Page 36] RFC 7016 Adobe RTMFP November 2013

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 follow a
 User Data chunk or another Next User Data chunk in the same packet.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x11     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-+-+-+-+-+-+-+-+
 |O|r| F | r |A|F|
 |P|s| R | s |B|I|
 |T|v| A | v |N|N|
 +-+-+-+-+-+-+-+-+
 +~~~/~~~/~~~~~~~+               +~~~/~~~/~~~~~~~+-------------/-+
 | L \ T \   V   |... options ...| L \ T \   V   |       0     \ |
 \~~~/~~~/~~~~~~~+   [if(OPT)]   +~~~/~~~/~~~~~~~+-------------/-/
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
 |                            userData                           |
 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
 struct nextUserDataChunkPayload_t
 {
     bool_t  optionsPresent :1;  // "OPT"
     uintn_t reserved1 :1;       // "rsv"
     uintn_t fragmentControl :2; // "FRA"
         // 0=whole, 1=begin, 2=end, 3=middle
     uintn_t reserved2 :2;       // "rsv"
     bool_t  abandon :1;         // "ABN"
     bool_t  final :1;           // "FIN"
     if(optionsPresent)
         optionList_t options :variable*8;
     uint8_t userData[remainder()];
 } :chunkLength*8;
 This chunk is considered to be for the same flowID as the most
 recently preceding User Data or Next User Data chunk in the same
 packet, having the same Forward Sequence Number, and having the next
 sequence number.  The optionsPresent, fragmentControl, abandon, and
 final flags, and the options (if present), have the same
 interpretation as for the User Data chunk.

Thornburgh Informational [Page 37] RFC 7016 Adobe RTMFP November 2013

             ...
             ----------+------------------------------------
             10 00 07  | User Data chunk, length=7
             00        | OPT=0, FRA=0 "whole", ABN=0, FIN=0
             02 05 03  | flowID=2, seq#=5, fsn=(5-3)=2
             00 01 02  | data 3 bytes: 00, 01, 02
             ----------+------------------------------------
             11 00 04  | Next User Data chunk,length=4
             00        | OPT=0, FRA=0 "whole", ABN=0, FIN=0
                       | flowID=2, seq#=6, fsn=2
             03 04 05  | data 3 bytes: 03, 04, 05
             ----------+------------------------------------
             11 00 04  | Next User Data chunk, length=4
             00        | OPT=0, FRA=0 "whole", ABN=0, FIN=0
                       | flowID=2, seq#=7, fsn=2
             06 07 08  | data 3 bytes: 06, 07, 08
             ----------+------------------------------------
   Figure 3: Sequential Messages in One Packet Using Next User Data
 The use of Next User Data is detailed in Section 3.6.2.3.2.

Thornburgh Informational [Page 38] RFC 7016 Adobe RTMFP November 2013

2.3.13. Data Acknowledgement Bitmap Chunk (Bitmap Ack)

 This chunk is sent by the flow receiver to indicate to the flow
 sender the User Data fragment sequence numbers that have been
 received for one flow.  It is only allowed in a packet belonging to
 an established session and having packet mode 1 or 2.
 The flow receiver can choose to acknowledge User Data with this chunk
 or with a Range Ack.  It SHOULD choose whichever format has the most
 compact encoding of the sequence numbers received.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x50     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-------------/-+-------------/-+-------------/-+
 |   flowID    \ |   bufAvail  \ |    cumAck   \ |
 +-------------/-+-------------/-+-------------/-+
 +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+
 |C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|C|
 |+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|+|
 |9|8|7|6|5|4|3|2|1|1|1|1|1|1|1|1|2|2|2|2|2|2|1|1| ....
 | | | | | | | | |7|6|5|4|3|2|1|0|5|4|3|2|1|0|9|8|
 +~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+~+
 struct dataAckBitmapChunkPayload_t
 {
     vlu_t flowID :variable*8;
     vlu_t bufferBlocksAvailable :variable*8; // "bufAvail"
     vlu_t cumulativeAck :variable*8; // "cumAck"
     bufferBytesAvailable = bufferBlocksAvailable * 1024;
     acknowledge(0 through cumulativeAck);
     ackCursor = cumulativeAck + 1;
     while(remainder() > 0)
     {
         for(bitPosition = 8; bitPosition > 0; bitPosition--)
         {
             bool_t bit :1;
             if(bit)
                 acknowledge(ackCursor + bitPosition);
         }
         ackCursor += 8;
     }
 } :chunkLength*8;

Thornburgh Informational [Page 39] RFC 7016 Adobe RTMFP November 2013

 flowID:  VLU, the flow identifier.
 bufferBlocksAvailable:  VLU, the number of 1024-byte blocks of User
    Data that the receiver is currently able to accept.
    Section 3.6.3.5 describes how to calculate this value.
 cumulativeAck:  VLU, the acknowledgement of every fragment sequence
    number in this flow that is less than or equal to this value.
    This MUST NOT be less than the highest Forward Sequence Number
    received in this flow.
 bit field:  A sequence of zero or more bytes representing a bit field
    of received fragment 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.
    Figure 4 shows an example Bitmap Ack indicating acknowledgement of
    fragment sequence numbers 0 through 16, 18, 21 through 24, 27,
    and 28.
       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
                     Figure 4: Example Bitmap Ack

Thornburgh Informational [Page 40] RFC 7016 Adobe RTMFP November 2013

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 fragment sequence numbers that have been
 received for one flow.  It is only allowed in a packet belonging to
 an established session and having packet mode 1 or 2.
 The flow receiver can 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.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x51     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-------------/-+-------------/-+-------------/-+
 |   flowID    \ |   bufAvail  \ |    cumAck   \ |
 +-------------/-+-------------/-+-------------/-+
 +~~~~~~~~~~~~~/~+~~~~~~~~~~~~~/~+
 |   #holes-1  \ |   #recv-1   \ |
 +~~~~~~~~~~~~~/~+~~~~~~~~~~~~~/~+
                 :
                 :
 +~~~~~~~~~~~~~/~+~~~~~~~~~~~~~/~+
 |   #holes-1  \ |   #recv-1   \ |
 +~~~~~~~~~~~~~/~+~~~~~~~~~~~~~/~+
 struct dataAckRangesChunkPayload_t
 {
     vlu_t flowID :variable*8;
     vlu_t bufferBlocksAvailable :variable*8; // "bufAvail"
     vlu_t cumulativeAck :variable*8; // "cumAck"
     bufferBytesAvailable = bufferBlocksAvailable * 1024;
     acknowledge(0 through cumulativeAck);
     ackCursor = cumulativeAck;
     while(remainder() > 0)
     {
         vlu_t holesMinusOne :variable*8; // "#holes-1"
         vlu_t receivedMinusOne :variable*8; // "#recv-1"
         ackCursor++;
         rangeFrom = ackCursor + holesMinusOne + 1;
         rangeTo = rangeFrom + receivedMinusOne;
         acknowledge(rangeFrom through rangeTo);
         ackCursor = rangeTo;
     }
 } :chunkLength*8;

Thornburgh Informational [Page 41] RFC 7016 Adobe RTMFP November 2013

 flowID:  VLU, the flow identifier.
 bufferBlocksAvailable:  VLU, the number of 1024-byte blocks of User
    Data that the receiver is currently able to accept.
    Section 3.6.3.5 describes how to calculate this value.
 cumulativeAck:  VLU, the acknowledgement of every fragment sequence
    number in this flow that is less than or equal to this value.
    This MUST NOT be less than the highest Forward Sequence Number
    received in this flow.
 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.
    NOTE: If a parser syntax error is encountered here (that is, if
    the chunk is truncated such that not enough bytes remain to
    completely encode both VLUs of the acknowledgement range), then
    treat and process this chunk as though it was properly formed up
    to the last completely encoded range.
    Figure 5 shows an example Range Ack indicating acknowledgement of
    fragment sequence numbers 0 through 16, 18, 21, 22, 23, and 24.
    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
                      Figure 5: Example Range Ack
    Figure 6 shows an example Range Ack indicating acknowledgement of
    fragment sequence numbers 0 through 16 and 18, with a truncated
    last range.  Note that the truncation and parse error does not
    abort the entire chunk in this case.
     51 00 07  | Range Ack, length=9
     05 7f 10  | flowID=5, bufAvail=127*1024 bytes, cumAck=0..16
     00 00     | holes=1, received=1 -- missing 17, received 18
     01 83     | holes=2, received=VLU parse error, ignore this range
                 Figure 6: Example Truncated Range Ack

Thornburgh Informational [Page 42] RFC 7016 Adobe RTMFP November 2013

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 is only allowed in a packet belonging to an established
 session and having packet mode 1 or 2.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      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.
 This chunk is only allowed in a packet belonging to an established
 session and having packet mode 1 or 2.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x5e     |          chunkLength          |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 +-------------/-+-------------/-+
 |   flowID    \ |  exception  \ |
 +-------------/-+-------------/-+
 struct flowExceptionReportChunkPayload_t
 {
     vlu_t flowID :variable*8;
     vlu_t exception :variable*8;
 } :chunkLength*8;

Thornburgh Informational [Page 43] RFC 7016 Adobe RTMFP November 2013

 flowID:  VLU, the flow identifier.
 exception:  VLU, the application-defined exception code being
    reported.
 A receiving RTMFP might reject a flow automatically, for example if
 it is missing metadata, or if an invalid return association is
 specified.  In circumstances where an RTMFP rejects a flow
 automatically, the exception code MUST be 0.  The application can
 specify any exception code, including 0, when rejecting a flow.  All
 non-zero exception codes are reserved for the application.

2.3.17. Session Close Request Chunk (Close)

 This chunk is sent to cleanly terminate a session.  It is only
 allowed in a packet belonging to an established or closing session
 and having packet mode 1 or 2.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x0c     |               0               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 This chunk has no payload.
 The use of Close is detailed in Section 3.5.5.

2.3.18. Session Close Acknowledgement Chunk (Close Ack)

 This chunk is sent in response to a Session Close Request to indicate
 that the sender has terminated the session.  It is only allowed in a
 packet belonging to an established or closing session and having
 packet mode 1 or 2.
  0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7|0 1 2 3 4 5 6 7
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |      0x4c     |               0               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 This chunk has no payload.
 The use of Close Ack is detailed in Section 3.5.5.

Thornburgh Informational [Page 44] RFC 7016 Adobe RTMFP November 2013

3. Operation

3.1. Overview

            +--------+                             +--------+
            | Peer A |        S E S S I O N        | Peer B |
            |        /=============================\        |
            |       ||            Flows            ||       |
            |       ||---------------------------->||       |
            |       ||---------------------------->||       |
            |       ||<----------------------------||       |
            |       ||<----------------------------||       |
            |       ||<----------------------------||       |
            |        \=============================/        |
            |        |                             |        |
            |        |                             +--------+
            |        |
            |        |                             +--------+
            |        |        S E S S I O N        | Peer C |
            |        /=============================\        |
            |       ||            Flows            ||       |
            |       ||---------------------------->||       |
            |       ||<----------------------------||       |
            |       ||<----------------------------||       |
            |        \=============================/        |
            |        |                             |        |
            +--------+                             +--------+
      Figure 7: Sessions between Pairs of Communicating Endpoints
 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 it 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

Thornburgh Informational [Page 45] RFC 7016 Adobe RTMFP November 2013

 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
 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.

Thornburgh Informational [Page 46] RFC 7016 Adobe RTMFP November 2013

 Multiple distinct Endpoint Discriminators MAY match one certificate.
 It is RECOMMENDED that multiple endpoints not have the same identity.
 Entities with the same identity are indistinguishable during session
 startup; this situation could be undesirable in some applications.
 An endpoint MAY have more than one address.
 The Cryptography Profile implements the following functions for
 identities, certificates, and Endpoint Discriminators, whose
 operation MUST be deterministic:
 o  Test whether a given certificate is authentic.  Authenticity can
    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.  If two distinct identities have
    the same Canonical Endpoint Discriminator, an initiator might
    abort a new opening session to the second identity
    (Section 3.5.1.1.1); this behavior might not be desirable.
 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 can comprise performing a
    lexicographic ordering of the binary certificates, 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.

Thornburgh Informational [Page 47] RFC 7016 Adobe RTMFP November 2013

 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.  It is RECOMMENDED that the test comprise
    testing whether the certificates are bitwise 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
 (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 allows 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 by using the Packet Fragment chunk (Section 2.3.1).

Thornburgh Informational [Page 48] RFC 7016 Adobe RTMFP November 2013

 The packet fragmentation mechanism SHOULD be used only to segment
 unavoidably large packets.  Accordingly, this mechanism SHOULD be
 employed only 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 the socket address from which the packet
 containing the fragment was received, as well as the indicated
 packetID.
 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 200 ms.
 To avoid resource exhaustion, a receiver SHOULD limit the number of
 concurrent packet reassembly buffers and the size of each buffer.
 Limits can depend, for example, on the expected size of reassembled
 packets, on the rate at which fragmented packets are expected to be
 received, on the expected degree of interleaving, and on the expected
 function of the receiver.  Limits can depend on the available
 resources of the receiver.  There can be different limits for packets
 with Session ID 0 and packets for established sessions.  For example,

Thornburgh Informational [Page 49] RFC 7016 Adobe RTMFP November 2013

 a busy server might need to allow for several hundred concurrent
 packet reassembly buffers to accommodate hundreds of connection
 requests per second with potentially interleaved fragments, but a
 client device with constrained resources could allow just a few
 reassembly buffers.  In the absence of specific information regarding
 the expected size of reassembled packets, a receiver should set the
 limit for each packet reassembly buffer to 65536 bytes.

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;
 o  Cryptographic near and far nonces according to the Cryptography
    Profile, where the near nonce is 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 destination socket address to use when sending
    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);

Thornburgh Informational [Page 50] RFC 7016 Adobe RTMFP November 2013

 o  The transmission budget, which controls the rate at which data is
    sent into the network (for example, a congestion window);
 o  S_OUTSTANDING_BYTES: the total amount of user message data
    outstanding, or in flight, in the network -- that is, the sum of
    the F_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 S_IHELLO_SENT and S_KEYING_SENT, the open state
    S_OPEN, the closing states S_NEARCLOSE and S_FARCLOSE_LINGER, and
    the closed states S_CLOSED and S_OPEN_FAILED; and
 o  The role -- either Initiator or Responder -- of this end of the
    session.

Thornburgh Informational [Page 51] RFC 7016 Adobe RTMFP November 2013

 Note: The following diagram is only a summary of state transitions
 and their causing events, and is not a complete operational
 specification.
        rcv IIKeying Glare
        far prevails +-------------+   ultimate open timeout
      +--------------|S_IHELLO_SENT|-------------+
      |              +-------------+             |
      |                     |rcv RHello          |
      |                     |                    v
      |                     v             +-------------+
      |<-----------(duplicate session?)   |S_OPEN_FAILED|
      |         yes         |no           +-------------+
      |                     |                    ^
      | rcv IIKeying Glare  v                    |
      | far prevails +-------------+             |
      |<-------------|S_KEYING_SENT|-------------+
      |              +-------------+   ultimate open timeout
      |                     |rcv RIKeying
      |                     |
      |       rcv           v
      |   +-+ IIKeying  +--------+ rcv Close Request
      |   |X|---------->| S_OPEN |--------------------+
      |   +-+           +--------+                    |
      |                   |    |ABRUPT CLOSE          |
      |      ORDERLY CLOSE|    |or rcv Close Ack      |
      |                   |    |or rcv IIKeying       |
      |                   |    |   session override   |
      |                   |    +-------+              |
      |                   v            |              v
      |             +-----------+      |     +-----------------+
      |             |S_NEARCLOSE|      |     |S_FARCLOSE_LINGER|
      |             +-----------+      |     +-----------------+
      |      rcv Close Ack|            |              |rcv Close Ack
      |      or 90 seconds|            v              |or 19 seconds
      |                   |       +--------+          |
      |                   +------>|S_CLOSED|<---------+
      +-------------------------->|        |
                                  +--------+
                    Figure 8: Session State Diagram

Thornburgh Informational [Page 52] RFC 7016 Adobe RTMFP November 2013

3.5.1. Startup

3.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 S_OPEN session with the initiator and
 sends an RIKeying.  The initiator receives the RIKeying and, if it is
 acceptable, computes the shared session keying and session nonces.
 The initiator's session is now S_OPEN.
      .     Initiator                                Responder     .
                    | IHello                         |
                    |(EPD,Tag)                       |
      S_IHELLO_SENT |(SID=0)                         |
                    |------------------------------->|
                    |                                |
                    |                         RHello |
                    |              (Tag,Cookie,RCert)|
                    |                         (SID=0)|
                    |<-------------------------------|
      S_KEYING_SENT |                                |
                    | IIKeying                       |
                    |(ISID,Cookie,ICert,SKIC,ISig)   |
                    |(SID=0)                         |
                    |------------------------------->|
                    |                                |
                    |                       RIKeying |
                    |                (RSID,SKRC,RSig)|
                    |          (SID=ISID,Key=Default)| S_OPEN
                    |<-------------------------------|
             S_OPEN |                                |
                    |          S E S S I O N         |
                    |<-------------------(SID=ISID)--|
                    |--(SID=RSID)------------------->|
                      Figure 9: Normal Handshake
 In the following sections, the handshake is detailed from the
 perspectives of the initiator and responder.

Thornburgh Informational [Page 53] RFC 7016 Adobe RTMFP November 2013

3.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 S_IHELLO_SENT state.
 If the session does not move to the S_OPEN state before an ultimate
 open timeout, the session has failed and moves to the S_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.  It is RECOMMENDED that the tag be cryptographically
 pseudorandom and be at least 8 bytes in length, so that it is hard to
 guess.  The initiator constructs an IHello chunk (Section 2.3.2) with
 the Endpoint Discriminator and the tag.
 While the initiator is in the S_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 S_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 S_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 S_KEYING_SENT or S_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,

Thornburgh Informational [Page 54] RFC 7016 Adobe RTMFP November 2013

 2.  Move to the S_KEYING_SENT state.  Set DESTADDR, the far-end
     address for the session, to the address from which this RHello
     was 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 S_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 S_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 S_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 (the
 recommended ultimate session open timeout).

Thornburgh Informational [Page 55] RFC 7016 Adobe RTMFP November 2013

 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
 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 S_IHELLO_SENT or S_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 S_OPEN state, then:
     1.  If the receiver was the Responder for the S_OPEN session and
         the session identifier, certificate, and Session Key
         Initiator Component are identical to those of the S_OPEN
         session, this IIKeying is a retransmission, so resend the
         S_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 S_OPEN session, ignore this IIKeying;
         otherwise,

Thornburgh Informational [Page 56] RFC 7016 Adobe RTMFP November 2013

     3.  The certificate from this IIKeying overrides the certificate
         of the S_OPEN session; this is a new opening session from the
         same identity, and the existing S_OPEN session is stale.
         Move the existing S_OPEN session to S_CLOSED and abort all of
         its flows (signaling exceptions to the user), then continue
         processing this IIKeying.
     Otherwise,
 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 S_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 address to reach a Forwarder (Section 3.5.1.5) but another to
 reach the responder.

Thornburgh Informational [Page 57] RFC 7016 Adobe RTMFP November 2013

 Consider the following example:
 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 =========================>|
                Figure 10: Handshake with Cookie Change
 The 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.  The responder has one interface with address
 Ry = 198.51.100.200:51000, on the same network as the initiator's
 second interface.  The initiator uses its first interface to reach a
 Forwarder.  The Forwarder observes the initiator's address of Ix and
 sends a Forwarded IHello (Section 2.3.3) to the responder.  The
 responder treats this as if it were an IHello from Ix, calculates a
 corresponding cookie, and sends an RHello to Ix.  The 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, the
 initiator uses its second interface Iy to send the IIKeying.  The
 responder, on receiving the IIKeying, will compare the cookie to the

Thornburgh Informational [Page 58] RFC 7016 Adobe RTMFP November 2013

 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, the responder will reject the IIKeying.
 If the responder determines that it generated the cookie in the
 IIKeying but the cookie doesn't match the sender's address (for
 example, if 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), the 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 S_KEYING_SENT state, AND the old cookie matches the one
 originally sent to the responder, then the initiator adopts the new
 cookie, constructs and signs a new IIKeying chunk, and sends the new
 IIKeying to the responder.  The initiator SHOULD NOT change the
 cookie for a session more than once.

3.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 that 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).

Thornburgh Informational [Page 59] RFC 7016 Adobe RTMFP November 2013

3.5.1.4. Redirector

      +-----------+           +------------+          +-----------+
      | Initiator |---------->| Redirector |          | Responder |
      |           |<----------|            |          |           |
      |           |           +------------+          |           |
      |           |<=================================>|           |
      +-----------+                                   +-----------+
                         Figure 11: 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, the Redirector constructs
 and sends back to the initiator a Responder Redirect chunk
 (Section 2.3.5) containing one or more additional candidate addresses
 for the indicated endpoint.
 Initiator                   Redirector                     Responder
 | IHello                         |                                 |
 |------------------------------->|                                 |
 |                                |                                 |
 |                       Redirect |                                 |
 |<-------------------------------|                                 |
 |                                                                  |
 | IHello                                                           |
 |----------------------------------------------------------------->|
 |                                                                  |
 |                                                           RHello |
 |<-----------------------------------------------------------------|
 |                                                                  |
 | IIKeying                                                         |
 |----------------------------------------------------------------->|
 |                                                                  |
 |                                                         RIKeying |
 |<-----------------------------------------------------------------|
 |                                                                  |
 |<======================== S E S S I O N =========================>|
                Figure 12: Handshake Using a Redirector

Thornburgh Informational [Page 60] RFC 7016 Adobe RTMFP November 2013

 Deployment Design Note: Redirectors SHOULD NOT initiate new sessions
 to endpoints that 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

       +-----------+     +-----------+     +---+     +-----------+
       | Initiator |---->| Forwarder |<===>| N |<===>| Responder |
       |           |     +-----------+     | A |     |           |
       |           |<=====================>| T |<===>|           |
       +-----------+                       +---+     +-----------+
                         Figure 13: 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
 S_OPEN session with an endpoint whose certificate matches the desired
 Endpoint Discriminator, the Forwarder constructs and sends an FIHello
 chunk (Section 2.3.3) to the selected endpoint over the S_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.

Thornburgh Informational [Page 61] RFC 7016 Adobe RTMFP November 2013

 On receipt of an FIHello chunk, a responder might send an RHello or
 Implied Redirect to the original source of the IHello
 (Section 3.5.1.1.2), potentially allowing future packets to flow
 directly between the initiator and responder through the NAT or
 firewall.
 Initiator                    Forwarder           NAT       Responder
 | IHello                         |                |                |
 |------------------------------->|                |                |
 |                                | FIHello        |                |
 |                                |--------------->|--------------->|
 |                                                 |                |
 |                                                 |         RHello |
 |                                                 :<---------------|
 |<------------------------------------------------:                |
 |                                                 :                |
 | IIKeying                                        :                |
 |-------------------------------------------------:--------------->|
 |                                                 :                |
 |                                                 :       RIKeying |
 |                                                 :<---------------|
 |<------------------------------------------------:                |
 |                                                 :                |
 |<======================== S E S S I O N ========>:<==============>|
    Figure 14: Forwarder Handshake where Responder Sends an RHello

Thornburgh Informational [Page 62] RFC 7016 Adobe RTMFP November 2013

 Initiator                    Forwarder           NAT       Responder
 | IHello                         |                |                |
 |------------------------------->|                |                |
 |                                | FIHello        |                |
 |                                |--------------->|--------------->|
 |                                                 |                |
 |                                                 |       Redirect |
 |                                                 | (Implied,RD={})|
 |                                                 :<---------------|
 |<------------------------------------------------:                |
 |                                                 :                |
 | IHello                                          :                |
 |------------------------------------------------>:--------------->|
 |                                                 :                |
 |                                                 :         RHello |
 |                                                 :<---------------|
 |<------------------------------------------------:                |
 |                                                 :                |
 | IIKeying                                        :                |
 |------------------------------------------------>:--------------->|
 |                                                 :                |
 |                                                 :       RIKeying |
 |                                                 :<---------------|
 |<------------------------------------------------:                |
 |                                                 :                |
 |<======================== S E S S I O N ========>:<==============>|
        Figure 15: Forwarder Handshake where Responder Sends an
                           Implied Redirect

3.5.1.6. Redirector and Forwarder with NAT

           +---+       +---+       +---+      +---+      +---+
           | I |       | N |       | I |      | N |      | R |
           | n |------>| A |------>| n |      | A |      | e |
           | i |       | T |       | t |<====>| T |<====>| s |
           | t |<------|   |<------| r |      |   |      | p |
           | i |       |   |       | o |      |   |      | o |
           | a |       |   |       +---+      |   |      | n |
           | t |       |   |                  |   |      | d |
           | o |<=====>|   |<================>|   |<====>| e |
           | r |       |   |                  |   |      | r |
           +---+       +---+                  +---+      +---+
      Figure 16: Introduction Service for Initiator and Responder
                              behind NATs

Thornburgh Informational [Page 63] RFC 7016 Adobe RTMFP November 2013

 An initiator and responder might each be behind distinct NATs or
 firewalls that don't allow inbound packets to reach the respective
 endpoints until each first sends an outbound packet for a particular
 far-endpoint address.
 An introduction service comprising Redirector and Forwarder functions
 may facilitate direct communication between endpoints each behind
 a NAT.
 The responder is registered with the introduction service via an
 S_OPEN session to it.  The service observes and records the
 responder's public NAT address as the DESTADDR of the S_OPEN session.
 The service MAY record other addresses for the responder, for example
 addresses that the responder self-reports as being directly attached.
 The initiator begins with an address of the introduction service as
 an initial candidate.  The Redirector portion of the service sends to
 the initiator a Responder Redirect containing at least the
 responder's public NAT address as previously recorded.  The Forwarder
 portion of the service sends to the responder a Forwarded IHello
 containing the initiator's public NAT address as observed to be the
 source of the IHello.
 The responder sends an RHello to the initiator's public NAT address
 in response to the FIHello.  This will allow inbound packets to the
 responder through its NAT from the initiator's public NAT address.
 The initiator sends an IHello to the responder's public NAT address
 in response to the Responder Redirect.  This will allow inbound
 packets to the initiator through its NAT from the responder's public
 NAT address.
 With transit paths created in both NATs, normal session startup can
 proceed.

Thornburgh Informational [Page 64] RFC 7016 Adobe RTMFP November 2013

 Initiator     NAT-I    Redirector+Forwarder     NAT-R      Responder
 |               |                |                |                |
 | IHello        |                |                |                |
 |(Dst=Intro)    |                |                |                |
 |-------------->|                |                |                |
 |               |--------------->|                |                |
 |               |                | FIHello        |                |
 |               |                |(RA=NAT-I-Pub)  |                |
 |               |                |--------------->|--------------->|
 |               |       Redirect |                |                |
 |               | (RD={NAT-R-Pub,|                |                |
 |               |           ...})|                |                |
 |<--------------|<---------------|                |                |
 |               |                                 |         RHello |
 |               |                                 | (Dst=NAT-I-Pub)|
 |               |                                 :<---------------|
 |               | (*)  <--------------------------:                |
 | IHello        |                                 :                |
 |(Dst=NAT-R-Pub)|                                 :                |
 |-------------->:                                 :                |
 |               :-------------------------------->:--------------->|
 |               :                                 :                |
 |               :                                 :         RHello |
 |               :                                 :<---------------|
 |<--------------:<--------------------------------:                |
 |               :                                 :                |
 | IIKeying      :                                 :                |
 |-------------->:                                 :                |
 |               :-------------------------------->:--------------->|
 |               :                                 :                |
 |               :                                 :       RIKeying |
 |               :                                 :<---------------|
 |<--------------:<--------------------------------:                |
 |               :                                 :                |
 |<=============>:<======== S E S S I O N ========>:<==============>|
          Figure 17: Handshake with Redirector and Forwarder
 At the point in Figure 17 marked (*), the responder's RHello from the
 FIHello might arrive at the initiator's NAT before or after the
 initiator's IHello is sent outbound to the responder's public NAT
 address.  If it arrives before, it may be dropped by the NAT.  If it
 arrives after, it will transit the NAT and trigger keying without
 waiting for another round-trip time.  The timing of this race
 depends, among other factors, on the relative distances of the
 initiator and responder from each other and from the introduction
 service.

Thornburgh Informational [Page 65] RFC 7016 Adobe RTMFP November 2013

3.5.1.7. Load Distribution and Fault Tolerance

           +---+    IHello/RHello    +-------------+
           | I |<------------------->| Responder 1 |
           | n |                     +-------------+
           | i |  SESSION  +-------------+
           | t |<=========>| Responder 2 |
           | i |           +-------------+
           | a |   IHello...                 +----------------+
           | t |-------------------------> X | Dead Responder |
           | o |                             +----------------+
           | r |  IHello/RHello   +-------------+
           |   |<---------------->| Responder N |
           +---+                  +-------------+
            Figure 18: Parallel Open to Multiple Endpoints
 As specified in Section 3.2, more than one endpoint is allowed to be
 selected by one Endpoint Discriminator.  This will typically be the
 case for a set of servers, any of which could accommodate a
 connecting client.
 As specified in Section 3.5.1.1.1, an initiator is allowed to use
 multiple candidate endpoint addresses when starting a session, and
 the sender of the first acceptable RHello chunk to be received is
 selected to complete the session, with later responses ignored.  An
 initiator can start with the multiple candidate endpoint addresses,
 or it may learn them during startup from one or more Redirectors
 (Section 3.5.1.4).
 Parallel open to multiple endpoints for the same Endpoint
 Discriminator, combined with selection by earliest RHello, can be
 used for load distribution and fault tolerance.  The cost at each
 endpoint that is not selected is limited to receiving and processing
 an IHello, and generating and sending an RHello.
 In one circumstance, multiple servers of similar processing and
 networking capacity may be located in near proximity to each other,
 such as in a data center.  In this circumstance, a less heavily
 loaded server can respond to an IHello more quickly than more heavily
 loaded servers and will tend to be selected by a client.
 In another circumstance, multiple servers may be located in different
 physical locations, such as different data centers.  In this
 circumstance, a server that is located nearer (in terms of network
 distance) to the client can respond earlier than more distant servers
 and will tend to be selected by the client.

Thornburgh Informational [Page 66] RFC 7016 Adobe RTMFP November 2013

 Multiple servers, in proximity or distant from one another, can form
 a redundant pool of servers.  A client can perform a parallel open to
 the multiple servers.  In normal operation, the multiple servers will
 all respond, and the client will select one of them as described
 above.  If one of the multiple servers fails, other servers in the
 pool can still respond to the client, allowing the client to succeed
 to an S_OPEN session with one of them.

3.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 in
 sending data than those described in "TCP Congestion Control"
 [RFC5681] and MUST NOT be more aggressive in sending data than the
 "slow start algorithm" described in Section 3.1 of RFC 5681.
 An endpoint maintains a transmission budget in the session
 information context of each S_OPEN session (Section 3.5), 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.  Transmission is allowed when S_OUTSTANDING_BYTES
 (Section 3.5) is less than the congestion window (Section 3.6.2.3).
 See Appendix A for an experimental window-based congestion control
 algorithm for real-time and bulk data.
 An endpoint avoids sending large bursts of data or packets into the
 network (Section 3.5.2.3).
 A sending endpoint increases and decreases its transmission budget in
 response to acknowledgements (Section 3.6.2.4) and loss according to
 the congestion control and avoidance algorithms.  Loss is detected by
 negative acknowledgement (Section 3.6.2.5) and timeout
 (Section 3.6.2.6).
 Timeout is determined by the Effective Retransmission Timeout (ERTO)
 (Section 3.5.2.2).  The ERTO is measured using the Timestamp and
 Timestamp Echo packet header fields (Section 2.2.4).
 A receiving endpoint acknowledges all received data (Section 3.6.3.4)
 to enable the sender to measure receipt of data, or lack thereof.
 A receiving endpoint may be receiving time critical (or real-time)
 data from a first sender while receiving data from other senders.
 The receiving endpoint can signal its other senders (Section 2.2.4)

Thornburgh Informational [Page 67] RFC 7016 Adobe RTMFP November 2013

 to cause them to decrease the aggressiveness of their congestion
 control and avoidance algorithms, in order to yield network capacity
 to the time critical data (Section 3.5.2.1).

3.5.2.1. Time Critical Reverse Notification

 A sender can increase its transmission budget at a rate compatible
 with (but not exceeding) the "slow start algorithm" specified in
 RFC 5681 (with which the transmission rate is doubled every round
 trip when beginning or restarting transmission, until loss is
 detected).  However, a sender MUST behave as though the slow start
 threshold SSTHRESH is clamped to 0 (disabling the slow start
 algorithm's exponential increase behavior) on a session where a Time
 Critical Reverse Notification (Section 2.2.4) indication has been
 received from the far end within the last 800 milliseconds, unless
 the sender is itself currently sending time critical data to the
 far end.
 During each round trip, a sender SHOULD NOT increase the transmission
 budget by more than 0.5% or by 384 bytes per round trip (whichever is
 greater) on a session where a Time Critical Reverse Notification
 indication has been received from the far end within the last 800
 milliseconds, unless the sender is itself currently sending time
 critical data to the far end.

3.5.2.2. Retransmission Timeout

 RTMFP uses the 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:
 o  On a session entering the S_OPEN state, initialize TS_RX_TIME to
    negative infinity, and initialize TS_RX and TS_ECHO_TX to have no
    value.

Thornburgh Informational [Page 68] RFC 7016 Adobe RTMFP November 2013

 o  On receipt of a packet in an S_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 S_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 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 Informational [Page 69] RFC 7016 Adobe RTMFP November 2013

 On sending a packet to the far end of an S_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 S_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 MRTO or 250 milliseconds, whichever is greater.
 A retransmission timeout occurs when the most recently transmitted
 user data fragment has remained outstanding in the network for ERTO.
 When this timeout occurs, increase ERTO on an exponential backoff
 with an ultimate backoff cap of 10 seconds:
 1.  Calculate ERTO_BACKOFF = ERTO * 1.4142;
 2.  Calculate ERTO_CAPPED to be ERTO_BACKOFF or 10 seconds, whichever
     is less;
 3.  Set ERTO to ERTO_CAPPED or MRTO, whichever is greater.

Thornburgh Informational [Page 70] RFC 7016 Adobe RTMFP November 2013

3.5.2.3. Burst Avoidance

 An application's sending patterns may cause the transmission budget
 to grow to a large value, but at times its sending patterns will
 result in 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 is undesirable, however, because it
 can jam interfaces, links, and buffers.
 Accordingly, in any session, an endpoint SHOULD NOT send more than
 six packets containing user data between receiving any
 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 (Sections 2.3.13 and 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 S_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 S_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 Informational [Page 71] RFC 7016 Adobe RTMFP November 2013

3.5.4. Ping

 If an endpoint receives a Ping chunk (Section 2.3.9) in a session in
 the S_OPEN state, it SHOULD construct and send a Ping Reply chunk
 (Section 2.3.10) in response if possible, copying the message
 unaltered.  The Ping Reply 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 can 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 be sent only 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 can use a Ping to test for live bidirectional
 connectivity, to test that the far end of a session is still in the
 S_OPEN state, to keep NAT translations alive, and to keep firewall
 holes open.
 An endpoint can use a Ping to hasten detection of a near-end address
 change by the far end.
 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 Section 3.5.2
 ("Congestion Control").

Thornburgh Informational [Page 72] RFC 7016 Adobe RTMFP November 2013

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
 cryptographically pseudorandom value not less than 128 bits in length
 and known only to this end.
 On receipt of a packet for an S_OPEN session, after processing all
 chunks in the packet: if the session is still in the S_OPEN state,
 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 the following: a marking to
     indicate (to this end when returned in a Ping Reply) that it is a
     mobility check (for example, the first byte being ASCII 'M' for
     "Mobility"), a timestamp set to MOB_TX_TS, and a cryptographic
     hash over the following: the preceding items, 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 S_OPEN session, if the Ping Reply's
 message satisfies all of these conditions:
 o  it has this end's expected marking to indicate that it is a
    mobility check, and
 o  the timestamp in the message is not more than 120 seconds in the
    past, and
 o  the timestamp in the message is greater than MOB_RX_TS, and
 o  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,

Thornburgh Informational [Page 73] RFC 7016 Adobe RTMFP November 2013

 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 described in RFC 4821 can 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
 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 S_OPEN session in a reliable and orderly fashion, an
 endpoint moves the session to the S_NEARCLOSE state.
 On a session transitioning from S_OPEN to S_NEARCLOSE and every
 5 seconds thereafter while still in the S_NEARCLOSE state, send a
 Session Close Request chunk (Section 2.3.17).
 A session that has been in the S_NEARCLOSE state for at least
 90 seconds (allowing time to retransmit the Session Close Request
 multiple times) SHOULD move to the S_CLOSED state.
 On a session transitioning from S_OPEN to the S_NEARCLOSE,
 S_FARCLOSE_LINGER or S_CLOSED state, immediately abort and terminate
 all open or closing flows.  Flows only exist in S_OPEN sessions.
 To close an S_OPEN session abruptly, send a Session Close
 Acknowledgement chunk (Section 2.3.18), then move to the S_CLOSED
 state.

Thornburgh Informational [Page 74] RFC 7016 Adobe RTMFP November 2013

 On receipt of a Session Close Request chunk for a session in the
 S_OPEN, S_NEARCLOSE, or S_FARCLOSE_LINGER states, send a Session
 Close Acknowledgement chunk; then, if the session is in the S_OPEN
 state, move to the S_FARCLOSE_LINGER state.
 A session that has been in the S_FARCLOSE_LINGER state for at least
 19 seconds (allowing time to answer 3 retransmissions of a Session
 Close Request) SHOULD move to the S_CLOSED state.
 On receipt of a Session Close Acknowledgement chunk for a session in
 the S_OPEN, S_NEARCLOSE, or S_FARCLOSE_LINGER states, move to the
 S_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. Overview

3.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
 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 at flow startup with the
 Return Flow Association option (Section 2.3.11.1.2).  An endpoint can
 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.  Note: Closure of one flow in an association does not
 automatically close other flows in the association, except as
 specified in Section 3.6.3.1.

Thornburgh Informational [Page 75] RFC 7016 Adobe RTMFP November 2013

 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, by means of the messages' fragment sequence
 numbers.  Flows are the basic units of message sequencing; each flow
 is sequenced independently of all other flows; inter-flow message
 arrival and delivery sequencing are 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, fragment
 sequence numbers are unique and monotonically increasing; that is,
 the fragment sequence numbers for any message MUST be greater than
 the fragment sequence numbers of all messages previously queued in
 that flow.  Receipt of fragments out of sequence number order within
 a flow creates discontiguous gaps at the receiver, causing it to send
 an acknowledgement for every packet and also causing the size of the
 encoded acknowledgements to grow.  Therefore, for any flow, the
 sender SHOULD send lower sequence numbers first.
 A sender can abandon a queued message at any time, even if some
 fragments of that message have been received by the other end.  A
 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

Thornburgh Informational [Page 76] RFC 7016 Adobe RTMFP November 2013

 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 can reject a receiving flow at any time in the flow's
 lifetime.  To reject the flow, the receiving endpoint sends a Flow
 Exception Report 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
 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.

Thornburgh Informational [Page 77] RFC 7016 Adobe RTMFP November 2013

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  F_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 the
    following:
  • 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

       Section 2.3.11 ("User Data Chunk");
  • 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 outstanding, or 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.
 o  F_OUTSTANDING_BYTES: the sum of the TRANSMIT_SIZE of each entry in
    SEND_QUEUE where entry.IN_FLIGHT is true;

Thornburgh Informational [Page 78] RFC 7016 Adobe RTMFP November 2013

 o  RX_BUFFER_SIZE: the most recent available buffer advertisement
    from the other end (Sections 2.3.13 and 2.3.14), initially
    65536 bytes;
 o  NEXT_SN: the next sequence number to assign to a message fragment,
    initially 1;
 o  F_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: the open
    state F_OPEN; the closing states F_CLOSING and F_COMPLETE_LINGER;
    and the closed state F_CLOSED.
 Note: The following diagram is only a summary of state transitions
 and their causing events, and is not a complete operational
 specification.
                               +--------+
                               | F_OPEN |
                               +--------+
                                    |CLOSE or
                                    |rcv Flow Exception
                                    |
                                    v
                               +---------+
                               |F_CLOSING|
                               +---------+
                                    |rcv Data Ack
                                    |  0..F_FINAL_SN
                                    v
                           +-----------------+
                           |F_COMPLETE_LINGER|
                           +-----------------+
                                    | 130 seconds
                                    v
                                +--------+
                                |F_CLOSED|
                                +--------+
                 Figure 19: Sending Flow State Diagram

Thornburgh Informational [Page 79] RFC 7016 Adobe RTMFP November 2013

3.6.2.1. Startup

 The application opens a new sending flow to the other end in an
 S_OPEN session.  The implementation chooses a new flow ID that is not
 assigned to any other sending flow in that session in the F_OPEN,
 F_CLOSING, or F_COMPLETE_LINGER states.  The flow starts in the
 F_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 a 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.  A new
 sending flow SHOULD NOT be opened in response to a receiving flow
 from the other end that is not in the RF_OPEN state when the sending
 flow is opened.
 At this point, the flow exists in the sender but not in the receiver.
 The flow begins when user data fragments are transmitted to the
 receiver.  A sender can 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 F_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).
 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.

Thornburgh Informational [Page 80] RFC 7016 Adobe RTMFP November 2013

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 F_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.F_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 the 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,
 4.  The first entry in the SEND_QUEUE is abandoned and either is 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
 outstanding.  The FSN MUST NOT be equal to any sequence number
 currently outstanding that was not abandoned when sent.

Thornburgh Informational [Page 81] RFC 7016 Adobe RTMFP November 2013

 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 the 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.F_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.F_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;
 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;

Thornburgh Informational [Page 82] RFC 7016 Adobe RTMFP November 2013

 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.  Using this chunk where possible can
 conserve space in a packet, potentially reducing transmission
 overhead or allowing additional information to be sent in a 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 into that packet belongs to the same flow, AND its sequence
 number is one greater than that of the fragment just assembled, it is
 RECOMMENDED that an implementation 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.F_OUTSTANDING_BYTES;
 2.  Set flow.STARTUP_OPTIONS to empty;
 3.  Set flow.RX_BUFFER_SIZE to chunk.bufferBytesAvailable;

Thornburgh Informational [Page 83] RFC 7016 Adobe RTMFP November 2013

 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 the entry from
     flow.SEND_QUEUE; and
 5.  Notify the congestion control and avoidance algorithms that
     PRE_ACK_OUTSTANDING_BYTES - flow.F_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.
 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

Thornburgh Informational [Page 84] RFC 7016 Adobe RTMFP November 2013

 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
 considered to be 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.3) is implemented or 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 WAS_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 WAS_LOSS = true; and
     2.  Set entry.IN_FLIGHT to false.
 3.  If WAS_LOSS is true, perform ERTO backoff (Section 3.5.2.2); and
 4.  Notify the congestion control and avoidance algorithms of the
     timeout and, if WAS_LOSS is true, that there was loss.

Thornburgh Informational [Page 85] RFC 7016 Adobe RTMFP November 2013

3.6.2.7. Abandoning Data

 The application can abandon queued messages at any time and for any
 reason.  Example reasons include (but are not limited to) the
 following: 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 fragments with
 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 Section 3.6.2.3 ("Sending Data") generates
 FSN Updates when appropriate.

Thornburgh Informational [Page 86] RFC 7016 Adobe RTMFP November 2013

3.6.2.8. Examples

  Sender
    |                   :
  1 |<---  Ack  ID=2, seq:0-16
  2 |--->  Data ID=2, seq#=25, fsnOff=9 (fsn=16)
  3 |--->  Data ID=2, seq#=26, fsnOff=10 (fsn=16)
  4 |<---  Ack  ID=2, seq:0-18
  5 |--->  Data ID=2, seq#=27, fsnOff=9 (fsn=18)
  6 |--->  Data ID=2, seq#=28, fsnOff=10 (fsn=18)
    |                   :
 There are 9 sequence numbers in flight with delayed acknowledgements.
                  Figure 20: Normal Flow with No Loss

Thornburgh Informational [Page 87] RFC 7016 Adobe RTMFP November 2013

  Sender
    |                   :
  1 |<---  Ack  ID=3, seq:0-30
  2 |--->  Data ID=3, seq#=45, fsnOff=15 (fsn=30)
  3 |<---  Ack  ID=3, seq:0-30, 32 (nack 31:1)
  4 |--->  Data ID=3, seq#=46, fsnOff=16 (fsn=30)
  5 |<---  Ack  ID=3, seq:0-30, 32, 34 (nack 31:2, 33:1)
  6 |<---  Ack  ID=3, seq:0-30, 32, 34-35 (nack 31:3=lost, 33:2)
  7 |--->  Data ID=3, seq#=47, fsnOff=15 (fsn=32, abandon 31)
  8 |<---  Ack  ID=3, seq:0-30, 32, 34-36 (nack 33:3=lost)
  9 |--->  Data ID=3, seq#=33, fsnOff=1 (fsn=32, retransmit 33)
 10 |<---  Ack  ID=3, seq:0-30, 32, 34-37
 11 |--->  Data ID=3, seq#=48, fsnOff=16 (fsn=32)
    |                   :
    |      (continues through seq#=59)
    |                   :
 12 |--->  Data ID=3, seq#=60, fsnOff=28(fsn=32)
 13 |<---  Ack  ID=3, seq:0-30, 34-46
 14 |--->  Data ID=3, seq#=61, fsnOff=29 (fsn=32)
 15 |<---  Ack  ID=3, seq:0-32, 34-47
 16 |--->  Data ID=3, seq#=62, fsnOff=30 (fsn=32)
 17 |<---  Ack  ID=3, seq:0-47
 18 |--->  Data ID=3, seq#=63, fsnOff=16 (fsn=47)
 19 |<---  Ack  ID=3, seq:0-49
 20 |--->  Data ID=3, seq#=64, fsnOff=15 (fsn=49)
    |                   :
 21 |<---  Ack  ID=3, seq:0-59
 22 |<---  Ack  ID=3, seq:0-59, 61 (nack 60:1)
 23 |<---  Ack  ID=3, seq:0-59, 61-62 (nack 60:2)
 24 |<---  Ack  ID=3, seq:0-59, 61-63 (nack 60:3=lost)
 25 |--->  Data ID=3, ABN=1, seq#=60, fsnOff=0 (fsn=60, abandon 60)
 26 |<---  Ack  ID=3, seq:0-59, 61-64
    |                   :
 27 |<---  Ack  ID=3, seq:0-64
 Flow with sequence numbers 31, 33, and 60 lost in transit, and a
 pause at 64.  33 is retransmitted; 31 and 60 are abandoned.  Note
 that line 25 is a Forward Sequence Number Update (Section 3.6.2.7.1).
                       Figure 21: Flow with Loss

Thornburgh Informational [Page 88] RFC 7016 Adobe RTMFP November 2013

3.6.2.9. Flow Control

 The flow receiver advertises the amount of new data it's willing to
 accept from the flow sender with the bufferBytesAvailable derived
 field of an acknowledgement (Sections 2.3.13 and 2.3.14).
 The flow sender MUST NOT send new data into the network if
 flow.F_OUTSTANDING_BYTES is greater than or equal to the most
 recently received buffer advertisement, unless flow.EXCEPTION is true
 (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 F_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.

Thornburgh Informational [Page 89] RFC 7016 Adobe RTMFP November 2013

3.6.2.11. Close

 A sending flow is closed by the user or as a result of an exception.
 To close an F_OPEN flow:
 1.  Move to the F_CLOSING state;
 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 F_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.F_FINAL_SN to entry.SEQUENCE_NUMBER.
 An F_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 an F_CLOSING sending flow becomes complete, move to the
 F_COMPLETE_LINGER state.
 A sending flow MUST remain in the F_COMPLETE_LINGER state for at
 least 130 seconds.  After at least 130 seconds, move to the F_CLOSED
 state.  The sending flow is now closed, its resources can be
 reclaimed, and its F_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  RF_FLOW_ID: this flow's identifier;
 o  SEQUENCE_SET: the set of all fragment sequence numbers seen in
    this receiving flow, whether received or abandoned, initially
    empty;
 o  RF_FINAL_SN: the final fragment sequence number of the flow,
    initially having no value;

Thornburgh Informational [Page 90] RFC 7016 Adobe RTMFP November 2013

 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 the following:
  • 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

       Section 2.3.11 ("User Data Chunk").
 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: the open
    state RF_OPEN; the closing states RF_REJECTED and
    RF_COMPLETE_LINGER; and the closed state RF_CLOSED.

Thornburgh Informational [Page 91] RFC 7016 Adobe RTMFP November 2013

 Note: The following diagram is only a summary of state transitions
 and their causing events, and is not a complete operational
 specification.
                                     +-+
                                     |X|
                                     +-+
                                      |rcv User Data for
                                      |  no existing flow
                                      v
                                 +---------+
                                 | RF_OPEN |
                                 +---------+
            rcv all sequence numbers|   |user reject,
                    0..RF_FINAL_SN  |   |rcv bad option,
                                    |   |no metadata at open,
                                    |   |association specified
                                    |   |  but not F_OPEN at open
                                +---+   |
                                |       v
                                |  +-----------+
                                |  |RF_REJECTED|
                                |  +-----------+
                                |       |rcv all sequence numbers
                                |       |  0..RF_FINAL_SN
                                v       v
                           +------------------+
                           |RF_COMPLETE_LINGER|
                           +------------------+
                                    | 120 seconds
                                    v
                               +---------+
                               |RF_CLOSED|
                               +---------+
                Figure 22: Receiving Flow State Diagram

Thornburgh Informational [Page 92] RFC 7016 Adobe RTMFP November 2013

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 RF_OPEN, RF_REJECTED, or
 RF_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
      RF_FLOW_ID to the flow ID encoded in the opening User Data
      chunk, and set to the RF_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 RF_REJECTED state;
 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 RF_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 F_OPEN, the receiver MUST reject this receiving
      flow, moving it to the RF_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 RF_REJECTED state;
 9.   If this new receiving flow is still RF_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;

Thornburgh Informational [Page 93] RFC 7016 Adobe RTMFP November 2013

 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 RF_OPEN, RF_REJECTED, or
      RF_COMPLETE_LINGER state, perform the steps of Section 3.6.3.1
      ("Startup") 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 RF_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 RF_REJECTED
      state;
 5.   If the flow is not in the RF_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;

Thornburgh Informational [Page 94] RFC 7016 Adobe RTMFP November 2013

 10.  If flow.SEQUENCE_SET doesn't contain chunk.sequenceNumber, AND
      chunk.final is true, AND flow.RF_FINAL_SN has no value, then set
      flow.RF_FINAL_SN to chunk.sequenceNumber, and set
      session.ACK_NOW to true;
 11.  If the flow is in the RF_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 RF_CLOSED state is ready to send
 an 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 MUST NOT deliver partially received messages, except
 by special arrangement with the user.

Thornburgh Informational [Page 95] RFC 7016 Adobe RTMFP November 2013

 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 be either a single fragment, whose fragment
 control value is 0-whole, or 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.
 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 Section 3.6.3.5
 ("Flow Control").
 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.

Thornburgh Informational [Page 96] RFC 7016 Adobe RTMFP November 2013

 The following describes a method for discarding abandoned message
 segments and delivering complete messages in original queuing 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 the 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.RF_FINAL_SN has a value and is equal to the CSN, AND
 RECV_BUFFER is empty, all complete messages have been delivered to
 the user, so notify the user that the flow is complete.

3.6.3.4. Acknowledging Data

 A flow receiver SHOULD acknowledge all user data fragment 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; therefore, the acknowledgements must be accurate
 and timely.

Thornburgh Informational [Page 97] RFC 7016 Adobe RTMFP November 2013

3.6.3.4.1. Timing

 For reasons similar to those discussed in Section 4.2.3.2 of RFC 1122
 [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 RF_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);
 o  On the first receipt of the final sequence number of the flow;
 o  On receipt of two packets in the session that contain 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);

Thornburgh Informational [Page 98] RFC 7016 Adobe RTMFP November 2013

 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 RF_REJECTED, first assemble a Flow
     Exception Report chunk (Section 2.3.16) for flow.flowID;
 2.  Choose the acknowledgement chunk type that most compactly encodes
     flow.SEQUENCE_SET;
 3.  Use the method described in Section 3.6.3.5 ("Flow Control") to
     determine the value for the acknowledgement chunk's
     bufferBlocksAvailable field.

Thornburgh Informational [Page 99] RFC 7016 Adobe RTMFP November 2013

3.6.3.4.4. Delayed Acknowledgement

 As discussed in Section 3.6.3.4.1 ("Timing"), a flow receiver can
 delay sending an acknowledgement for up to 200 milliseconds after
 receiving user data.  The method described in Section 3.6.3.2
 ("Receiving Data") 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.  While 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.

3.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.

Thornburgh Informational [Page 100] RFC 7016 Adobe RTMFP November 2013

 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. Example

 Figure 23 shows an example flow with sequence numbers 31 and 33 lost
 in transit; 31 is abandoned, and 33 is retransmitted.
 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
    |                   :
                   Figure 23: Flow Example with Loss

Thornburgh Informational [Page 101] RFC 7016 Adobe RTMFP November 2013

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 (Sections 2.3.13 and 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
 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);

Thornburgh Informational [Page 102] RFC 7016 Adobe RTMFP November 2013

 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 RF_OPEN, RF_REJECTED, or RF_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
 4.  Set session.ACK_NOW to true.

3.6.3.7. Rejecting a Flow

 A receiver can reject an RF_OPEN flow at any time and for any reason.
 To reject a receiving flow in the RF_OPEN state:
 1.  Move to the RF_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.

Thornburgh Informational [Page 103] RFC 7016 Adobe RTMFP November 2013

 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 RF_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.RF_FINAL_SN has a value and flow.SEQUENCE_SET
 contains every sequence number from 0 through flow.RF_FINAL_SN,
 inclusive.
 When an RF_OPEN or RF_REJECTED receiving flow becomes complete, move
 to the RF_COMPLETE_LINGER state, set flow.SHOULD_ACK to true, and set
 session.ACK_NOW to true.
 A receiving flow SHOULD remain in the RF_COMPLETE_LINGER state for
 120 seconds.  After 120 seconds, move to the RF_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 fragment 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 receiver's RF_COMPLETE_LINGER period is two minutes (one Maximum
 Segment Lifetime (MSL)); this period 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 F_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 reused 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, 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.

Thornburgh Informational [Page 104] RFC 7016 Adobe RTMFP November 2013

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.
 A block cipher in CBC mode is RECOMMENDED for packet encryption
 (Section 2.2.3).  An attacker can predict the values of some fields
 from one plain RTMFP packet to the next or predict that some fields
 may be the same from one packet to the next.  This SHOULD be
 considered in choosing and implementing a packet encryption cipher
 and mode.
 The well-known Default Session Key of a Cryptography Profile serves
 multiple purposes, including the scrambling of session startup
 packets to protect interior fields from undesirable modification by
 middleboxes such as NATs, increasing the effort required for casual
 passive observation of startup packets, and allowing different
 applications of RTMFP using different Default Session Keys to
 (intentionally or not) share network transport addresses without
 interference.  The Default Session Key, being well known, MUST NOT be
 construed to contribute to the security of session startup; session
 startup is essentially in the clear.
 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 method, 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 method, 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
 initiators to flood a victim address or network with Initiator Hello
 packets, potentially causing a denial of service.

Thornburgh Informational [Page 105] RFC 7016 Adobe RTMFP November 2013

 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.
 An attacker that can passively observe and record the packets of an
 established session can use traffic analysis techniques to infer the
 start and completion of flows without decrypting the packets.  The
 User Data fragments of flows have unique sequence numbers, so flows
 are immune to replay while they are open.  However, once a flow has
 completed and the linger period has concluded, the attacker could
 replay the recorded packets, opening a new flow in the receiver and
 duplicating the flow's data; this replay might have undesirable
 effects on the receiver's application.  The attacker could also infer
 that a new flow has begun reusing the recorded flow's identifier and
 replay the final sequence number or any of the other fragments in the
 flow, potentially denying or interfering with legitimate traffic to
 the receiver.  Therefore, the data integrity aspect of packet
 encryption SHOULD comprise anti-replay measures.

6. Acknowledgements

 Special thanks go to Matthew Kaufman for his contributions to the
 creation and design of RTMFP.
 Thanks to Jari Arkko, Ben Campbell, Wesley Eddy, Stephen Farrell,
 Philipp Hancke, Bela Lubkin, Hilarie Orman, Richard Scheffenegger,
 and Martin Stiemerling for their detailed reviews of this memo.

Thornburgh Informational [Page 106] RFC 7016 Adobe RTMFP November 2013

7. References

7.1. Normative References

 [CBC]      Dworkin, M., "Recommendation for Block Cipher Modes of
            Operation", NIST Special Publication 800-38A,
            December 2001, <http://csrc.nist.gov/publications/
            nistpubs/800-38a/sp800-38a.pdf>.
 [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.

7.2. Informative References

 [RFC5389]  Rosenberg, J., Mahy, R., Matthews, P., and D. Wing,
            "Session Traversal Utilities for NAT (STUN)", RFC 5389,
            October 2008.
 [ScalableTCP]
            Kelly, T., "Scalable TCP: Improving Performance in
            Highspeed Wide Area Networks", December 2002,
            <http://datatag.web.cern.ch/datatag/papers/
            pfldnet2003-ctk.pdf>.

Thornburgh Informational [Page 107] RFC 7016 Adobe RTMFP November 2013

Appendix A. Example Congestion Control Algorithm

 As mandated in Section 3.5.2, an RTMFP is required to use TCP-
 compatible congestion control, but flexibility in exact
 implementation is allowed, within certain limits.  This section
 describes an experimental window-based congestion control algorithm
 that is appropriate for real-time and bulk data transport in RTMFP.
 The algorithm includes slow start and congestion avoidance phases,
 including modified increase and decrease parameters.  These
 parameters are further adjusted according to whether real-time data
 is being sent and whether Time Critical Reverse Notifications are
 received.

A.1. Discussion

 RFC 5681 defines the standard window-based congestion control
 algorithms for TCP.  These algorithms are appropriate for delay-
 insensitive bulk data transport but have undesirable behaviors for
 delay- and loss-sensitive applications.  Among the undesirable
 behaviors are the cutting of the congestion window in half during a
 loss event, and the rapidity of the slow start algorithm's
 exponential growth.  Cutting the congestion window in half requires a
 large channel headroom to support a real-time application and can
 cause a large amount of jitter from sender-side buffering.  Doubling
 the congestion window during the slow start phase can lead to the
 congestion window temporarily growing to twice the size it should be,
 causing a period of excessive loss in the path.
 We found that a number of deployed TCP implementations use the method
 of equation (3) from Section 3.1 of RFC 5681; this method, when
 combined with the recommended behavior of acknowledging every other
 packet, causes the congestion window to grow at approximately half
 the rate that the recommended method specifies.  In order to compete
 fairly with these deployed TCPs, we choose 768 bytes per round trip
 as the increment during the normal congestion avoidance phase; this
 is approximately half of the typical maximum segment size of
 1500 bytes and is also easily subdivided.
 The sender may be sending real-time data to the far end.  When
 sending real-time data, a smoother response to congestion is desired
 while still competing with reasonable fairness to other flows in the
 Internet.  In order to scale the sending rate quickly, the slow start
 algorithm is desired, but slow start's normal rate of increase can
 cause excessive loss in the last round trip.  Accordingly, slow
 start's exponential increase rate is adjusted to double approximately
 every 3 round trips instead of every round trip.  The multiplicative
 decrease cuts the congestion window by one eighth on loss to maintain
 a smoother sending rate.  The additive increase is done at half the

Thornburgh Informational [Page 108] RFC 7016 Adobe RTMFP November 2013

 normal rate (incrementing at 384 bytes per round trip), to both
 compensate for the less aggressive loss response and probe the path
 capacity more gently.
 The far end may report that it is receiving real-time data from other
 peers, or the sender may be sending real-time data to other far ends.
 In these circumstances (if not sending real-time data to this far
 end), it is desirable to respond differently than the standard TCP
 algorithms specify, to both yield capacity to the real-time flows and
 avoid excessive losses while probing the path capacity.  Slow start's
 exponential increase is disabled, and the additive increase is done
 at half the normal rate (incrementing at 384 bytes per round trip).
 Multiplicative decrease is left at the normal rate (cutting by half)
 to yield to other flows.
 Since real-time messages may be small, and sent regularly, it is
 advantageous to spread congestion window increases out across the
 round-trip time instead of doing them all at once.  We divide the
 round trip into 16 segments with an additive increase of a useful
 size (48 bytes) per segment.
 Scalable TCP [ScalableTCP] describes experimental methods of
 modifying the additive increase and multiplicative decrease of the
 congestion window in large delay-bandwidth scenarios.  The congestion
 window is increased by 1% each round trip and decreased by one eighth
 on loss in the congestion avoidance phase in certain circumstances
 (specifically, when a 1% increase is larger than the normal additive-
 increase amount).  Those methods are adapted here.  The scalable
 increase amount is 48 bytes for every 4800 bytes acknowledged, to
 spread the increase out over the round trip.  The congestion window
 is decreased by one eighth on loss when it is at least 67200 bytes
 per round trip, which is seven eighths of 76800 (the point at which
 1% is greater than 768 bytes per round trip).  When sending real-time
 data to the far end, the scalable increase is 1% or 384 bytes per
 round trip, whichever is greater.  Otherwise, when notified that the
 far end is receiving real-time data from other peers, the scaled
 increase is adjusted to 0.5% or 384 bytes per round trip, whichever
 is greater.

Thornburgh Informational [Page 109] RFC 7016 Adobe RTMFP November 2013

A.2. Algorithm

 Let SMSS denote the Sender Maximum Segment Size [RFC5681], for
 example 1460 bytes.  Let CWND_INIT denote the Initial Congestion
 Window (IW) according to Section 3.1 of RFC 5681, for example
 4380 bytes.  Let CWND_TIMEDOUT denote the congestion window after a
 timeout indicating lost data, being 1*SMSS (for example, 1460 bytes).
 Let the session information context contain additional variables:
 o  CWND: the congestion window, initialized to CWND_INIT;
 o  SSTHRESH: the slow start threshold, initialized to positive
    infinity;
 o  ACKED_BYTES_ACCUMULATOR: a count of acknowledged bytes,
    initialized to 0;
 o  ACKED_BYTES_THIS_PACKET: a count of acknowledged bytes observed in
    the current packet;
 o  PRE_ACK_OUTSTANDING: the number of bytes outstanding in the
    network before processing any acknowledgements in the current
    packet;
 o  ANY_LOSS: an indication of whether any loss has been detected in
    the current packet;
 o  ANY_NAKS: an indication of whether any negative acknowledgements
    have been detected in the current packet;
 o  ANY_ACKS: an indication of whether any acknowledgement chunks have
    been received in the current packet.
 Let FASTGROW_ALLOWED indicate whether the congestion window is
 allowed to grow at the normal rate versus a slower rate, being false
 if a Time Critical Reverse Notification has been received on this
 session within the last 800 milliseconds (Sections 2.2.4 and 3.5.2.1)
 or if a Time Critical Forward Notification has been sent on ANY
 session in the last 800 milliseconds, and otherwise being true.
 Let TC_SENT indicate whether a Time Critical Forward Notification has
 been sent on this session within the last 800 milliseconds.
 Implement the method described in Section 3.6.2.6 to manage
 transmission timeouts, including setting the TIMEOUT_ALARM.

Thornburgh Informational [Page 110] RFC 7016 Adobe RTMFP November 2013

 On being notified that the TIMEOUT_ALARM has fired, perform the
 function shown in Figure 24:
 on TimeoutNotification(WAS_LOSS):
     set SSTHRESH to MAX(SSTHRESH, CWND * 3/4).
     set ACKED_BYTES_ACCUMULATOR to 0.
     if WAS_LOSS is true:
         set CWND to CWND_TIMEDOUT.
     else:
         set CWND to CWND_INIT.
       Figure 24: Pseudocode for Handling a Timeout Notification
 Before processing each received packet in this session:
 1.  Set ANY_LOSS to false;
 2.  Set ANY_NAKS to false;
 3.  Set ACKED_BYTES_THIS_PACKET to 0; and
 4.  Set PRE_ACK_OUTSTANDING to S_OUTSTANDING_BYTES.
 On notification of loss (Section 3.6.2.5), set ANY_LOSS to true.
 On notification of negative acknowledgement (Section 3.6.2.5), set
 ANY_NAKS to true.
 On notification of acknowledgement of data (Section 3.6.2.4), set
 ANY_ACKS to true, and add the count of acknowledged bytes to
 ACKED_BYTES_THIS_PACKET.

Thornburgh Informational [Page 111] RFC 7016 Adobe RTMFP November 2013

 After processing all chunks in each received packet for this session,
 perform the function shown in Figure 25:
 if ANY_LOSS is true:
     if (TC_SENT is true) OR (PRE_ACK_OUTSTANDING > 67200 AND \
     FASTGROW_ALLOWED is true):
         set SSTHRESH to MAX(PRE_ACK_OUTSTANDING * 7/8, CWND_INIT).
     else:
         set SSTHRESH to MAX(PRE_ACK_OUTSTANDING * 1/2, CWND_INIT).
     set CWND to SSTHRESH.
     set ACKED_BYTES_ACCUMULATOR to 0.
 else if (ANY_ACKS is true) AND (ANY_NAKS is false) AND \
 (PRE_ACK_OUTSTANDING >= CWND):
     set var INCREASE to 0.
     var AITHRESH.
     if FASTGROW_ALLOWED is true:
         if CWND < SSTHRESH:
             set INCREASE to ACKED_BYTES_THIS_PACKET.
         else:
             add ACKED_BYTES_THIS_PACKET to ACKED_BYTES_ACCUMULATOR.
             set AITHRESH to MIN(MAX(CWND / 16, 64), 4800).
             while ACKED_BYTES_ACCUMULATOR >= AITHRESH:
                 subtract AITHRESH from ACKED_BYTES_ACCUMULATOR.
                 add 48 to INCREASE.
     else FASTGROW_ALLOWED is false:
         if CWND < SSTHRESH AND TC_SENT is true:
             set INCREASE to CEIL(ACKED_BYTES_THIS_PACKET / 4).
         else:
             var AITHRESH_CAP.
             if TC_SENT is true:
                 set AITHRESH_CAP to 2400.
             else:
                 set AITHRESH_CAP to 4800.
             add ACKED_BYTES_THIS_PACKET to ACKED_BYTES_ACCUMULATOR.
             set AITHRESH to MIN(MAX(CWND / 16, 64), AITHRESH_CAP).
             while ACKED_BYTES_ACCUMULATOR >= AITHRESH:
                 subtract AITHRESH from ACKED_BYTES_ACCUMULATOR.
                 add 24 to INCREASE.
     set CWND to MAX(CWND + MIN(INCREASE, SMSS), CWND_INIT).
        Figure 25: Pseudocode for Congestion Window Adjustment
                       after Processing a Packet

Thornburgh Informational [Page 112] RFC 7016 Adobe RTMFP November 2013

Author's Address

 Michael C. Thornburgh
 Adobe Systems Incorporated
 345 Park Avenue
 San Jose, CA  95110-2704
 US
 Phone: +1 408 536 6000
 EMail: mthornbu@adobe.com
 URI:   http://www.adobe.com/

Thornburgh Informational [Page 113]

/data/webs/external/dokuwiki/data/pages/rfc/rfc7016.txt · Last modified: 2013/11/27 19:46 by 127.0.0.1

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki