Skip to main content

Adobe's Secure Real-Time Media Flow Protocol
draft-thornburgh-adobe-rtmfp-06

The information below is for an old version of the document.
Document Type
This is an older version of an Internet-Draft that was ultimately published as RFC 7016.
Author Michael C. Thornburgh
Last updated 2013-04-15
RFC stream Internet Engineering Task Force (IETF)
Formats
Reviews
Additional resources
Stream WG state (None)
Document shepherd (None)
IESG IESG state Became RFC 7016 (Informational)
Consensus boilerplate Unknown
Telechat date (None)
Responsible AD Martin Stiemerling
Send notices to mthornbu@adobe.com, draft-thornburgh-adobe-rtmfp@tools.ietf.org
draft-thornburgh-adobe-rtmfp-06
Thornburgh              Expires October 17, 2013               [Page 84]
Internet-Draft                 Adobe RTMFP                    April 2013

      *  FRA: the fragment control value for this message fragment,
         having one of the values enumerated for that purpose in User
         Data (Section 2.3.11).

   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              Expires October 17, 2013               [Page 85]
Internet-Draft                 Adobe RTMFP                    April 2013

    Note: this 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 21: Receiving flow state diagram

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;

Thornburgh              Expires October 17, 2013               [Page 86]
Internet-Draft                 Adobe RTMFP                    April 2013

   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;

   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:

Thornburgh              Expires October 17, 2013               [Page 87]
Internet-Draft                 Adobe RTMFP                    April 2013

   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 at Startup
        (Section 3.6.3.1) to start a new receiving flow;

   2.   Retrieve the receiving flow context for the flow indicated by
        chunk.flowID;

   3.   Set flow.SHOULD_ACK to true;

   4.   If the flow is 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;

   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;

Thornburgh              Expires October 17, 2013               [Page 88]
Internet-Draft                 Adobe RTMFP                    April 2013

   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.

   Let the Cumulative Acknowledgement Sequence Number CSN be the highest
   number in the contiguous range of numbers in SEQUENCE_SET starting
   with 0.  For example, if SEQUENCE_SET contains {0, 1, 2, 3, 5, 6},
   the contiguous range starting with 0 is 0..3, so the CSN is 3.

   A message is complete if all of its fragments are present in the
   RECV_BUFFER.  The fragments of one message have contiguous sequence
   numbers.  A message can either be a single fragment, whose fragment
   control value is 0-whole, or can be two or more fragments where the
   first's fragment control value is 1-begin, followed by zero or more
   fragments with control value 3-middle, and terminated by a last
   fragment with control value 2-end.

   An incomplete message segment is a contiguous sequence of one or more
   fragments that do not form a complete message; that is, a 1-begin
   followed by zero or more 3-middle fragments but with no 2-end, or
   zero or more 3-middle fragments followed by a 2-end but with no
   1-begin, or one or more 3-middle fragments with neither a 1-begin nor

Thornburgh              Expires October 17, 2013               [Page 89]
Internet-Draft                 Adobe RTMFP                    April 2013

   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 Flow Control (Section 3.6.3.5).

   When the receiving flow is not suspended, the original queuing order
   of the messages is recovered by delivering, in ascending sequence
   number order, complete messages in the RECV_BUFFER whose sequence
   numbers are less than or equal to the CSN.

   The following describes a method for discarding abandoned message
   segments and delivering complete messages in original queueing order
   when the receiving flow is not suspended.

   While the first fragment entry in the RECV_BUFFER has a sequence
   number less than or equal to CSN and delivery is still possible:

   1.  If entry.FRA is 0-whole: deliver entry.DATA to the user, and
       remove this entry from RECV_BUFFER; otherwise,

   2.  If entry.FRA is 2-end or 3-middle: this entry belongs to an
       abandoned segment, so remove and discard this entry from
       RECV_BUFFER; otherwise,

   3.  Entry.FRA is 1-begin.  Let LAST_ENTRY be the last RECV_BUFFER
       entry that is part of this message segment (LAST_ENTRY can be
       entry if the segment has only one fragment so far).  Then:

       1.  If LAST_ENTRY.FRA is 2-end: this segment is a complete
           message, so concatenate the DATA fields of each fragment
           entry of this segment in ascending sequence number order and

Thornburgh              Expires October 17, 2013               [Page 90]
Internet-Draft                 Adobe RTMFP                    April 2013

           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 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 sequence numbers
   seen in that flow.  Acknowledgements drive the sender's congestion
   control and avoidance algorithms, clear data from the sender's
   buffers, and in some sender implementations clock new data into the
   network, and therefore must be accurate and timely.

3.6.3.4.1.  Timing

   For similar reasons as discussed in RFC 1122 Section 4.2.3.2
   [RFC1122], it is advantageous to delay sending acknowledgements for a
   short time so that multiple data fragments can be acknowledged in a
   single transmission.  However, it is also advantageous for a sender
   to receive timely notification about the receiver's disposition of
   the flow, particularly in unusual or exceptional circumstances, so
   that the circumstances can be addressed if possible.

   Therefore, a flow receiver SHOULD send an acknowledgement for a flow
   as soon as is practical in any of the following circumstances:

   o  On receipt of a User Data chunk that starts a new flow;

   o  On receipt of a User Data or Next User Data chunk if the flow is
      not in the 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);

Thornburgh              Expires October 17, 2013               [Page 91]
Internet-Draft                 Adobe RTMFP                    April 2013

   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 containing user data for
      any flows since an acknowledgement was last sent; the new
      acknowledgements being for the flows having any User Data chunks
      in the received packets (that is, for every second packet
      containing user data);

   o  After receipt of a User Data chunk for the flow, if an
      acknowledgement for any other flow is being sent (that is,
      consolidate acknowledgements);

   o  After receipt of a User Data chunk for the flow, if any user data
      for a sending flow is being sent in a packet and if there is space
      available in the same packet (that is, attempt to piggyback an
      acknowledgement with user data if possible);

   o  No longer than 200 milliseconds after receipt of a User Data chunk
      for the flow.

3.6.3.4.2.  Size and Truncation

   Including an encoded acknowledgement in a packet might cause the
   packet to exceed the path MTU.  In that case:

   o  If the packet is being sent primarily to send an acknowledgement
      AND this is the first acknowledgement in the packet, truncate the
      acknowledgement so that the packet does not exceed the path MTU;
      otherwise

Thornburgh              Expires October 17, 2013               [Page 92]
Internet-Draft                 Adobe RTMFP                    April 2013

   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 Flow Control (Section 3.6.3.5) to
       determine the value for the acknowledgement chunk's
       bufferBlocksAvailable field;

3.6.3.4.4.  Delayed Acknowledgement

   As discussed in Acknowledging Data (Section 3.6.3.4.1), a flow
   receiver can delay sending an acknowledgement for up to 200
   milliseconds after receiving user data.  The method described in
   Receiving Data (Section 3.6.3.2) sets the session's DELACK_ALARM.

   When DELACK_ALARM fires: set ACK_NOW to true.

3.6.3.4.5.  Obligatory Acknowledgement

   One or more acknowledgements should be sent as soon as is practical
   when the session's ACK_NOW flag is set.  When the ACK_NOW flag is
   set:

   1.  Choose a receiving flow that is ready to send an acknowledgement;

   2.  If there is no such flow: there is no work to do, set ACK_NOW to
       false, set RX_DATA_PACKETS to 0, clear the DELACK_ALARM, and
       stop; otherwise

   3.  Start a new packet;

Thornburgh              Expires October 17, 2013               [Page 93]
Internet-Draft                 Adobe RTMFP                    April 2013

   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.

   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

Thornburgh              Expires October 17, 2013               [Page 94]
Internet-Draft                 Adobe RTMFP                    April 2013

   Receiver
    1 |<---  Data ID=3, seq#=29, fsnOff=11 (fsn=18)
    2 |<---  Data ID=3, seq#=30, fsnOff=12 (fsn=18)
    3 |--->  Ack  ID=3, seq:0-30
    4 |<---  Data ID=3, seq#=32, fsnOff=12 (fsn=20)
    5 |--->  Ack  ID=3, seq:0-30, 32
    6 |<---  Data ID=3, seq#=34, fsnOff=12 (fsn=22)
    7 |--->  Ack  ID=3, seq:0-30, 32, 34
      |                   :
    8 |<---  Data ID=3, seq#=46, fsnOff=16 (fsn=30)
    9 |--->  Ack  ID=3, seq:0-30, 32, 34-46
   10 |<---  Data ID=3, seq#=47, fsnOff=15 (fsn=32)
   11 |--->  Ack  ID=3, seq:0-32, 34-47
   12 |<---  Data ID=3, seq#=33, fsnOff=1 (fsn=32)
   13 |--->  Ack  ID=3, seq#=0-47
   14 |<---  Data ID=3, seq#=48, fsnOff=16 (fsn=32)
   15 |<---  Data ID=3, seq#=49, fsnOff=17 (fsn=32)
   16 |--->  Ack  ID=3, seq#=0-49
      |                   :

   Flow with sequence numbers 31 and 33 lost in transit, 31 abandoned
   and 33 retransmitted.

                                 Figure 22

3.6.3.5.  Flow Control

   The flow receiver maintains a buffer for reassembling and reordering
   messages for delivery to the user (Section 3.6.3.3).  The
   implementation and the user may wish to limit the amount of resources
   (including buffer memory) that a flow is allowed to use.

   RTMFP provides a means for each receiving flow to govern the amount
   of data sent by the sender, by way of the bufferBytesAvailable
   derived field of acknowledgement chunks (Section 2.3.13,
   Section 2.3.14).  This derived field indicates the amount of data
   that the sender is allowed to have outstanding in the network, until
   instructed otherwise.  This amount is also called the receive window.

   The flow receiver can suspend the sender by advertising a closed
   (zero length) receive window.

   The user can suspend delivery of messages from the receiving flow
   (Section 3.6.3.3).  This can cause the receive buffer to fill.

   In order for progress to be made on completing a fragmented message
   or repairing a gap for sequenced delivery in a flow, the flow
   receiver MUST advertise at least one buffer block in an

Thornburgh              Expires October 17, 2013               [Page 95]
Internet-Draft                 Adobe RTMFP                    April 2013

   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);

   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

Thornburgh              Expires October 17, 2013               [Page 96]
Internet-Draft                 Adobe RTMFP                    April 2013

   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.

   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 sequence numbers of the flow.

Thornburgh              Expires October 17, 2013               [Page 97]
Internet-Draft                 Adobe RTMFP                    April 2013

   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)), which allows any in-flight packets to drain
   from the network without being misidentified, and gives the sender an
   opportunity to retransmit any sequence numbers if the completing
   acknowledgement is lost.  The sender's 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 re-used by the flow sender for a new sending flow
   for at least 10 seconds after the flow receiver has closed the
   receiving flow context.  This ensures correct operation independent
   of network delay and even when the sender's clock runs up to 8
   percent faster than the receiver's.

4.  IANA Considerations

   This memo specifies chunk type code values (Section 2.3) and User
   Data option type code values (Section 2.3.11.1).  These type code
   values are assigned and maintained by Adobe.  Therefore, this memo
   has no IANA actions.

5.  Security Considerations

   This memo specifies a general framework that can be used to establish
   a confidential and authenticated session between endpoints.  A
   Cryptography Profile, not specified herein, defines the cryptographic
   algorithms, data formats, and semantics as used within this
   framework.  Designing a Cryptography Profile to ensure that
   communications are protected to the degree required by the
   application-specific threat model is outside the scope of this
   specification.

   The well-known Default Session Key of a Cryptography Profile serves
   multiple purposes, including: to scramble session startup packets to
   protect interior fields from undesirable modification by middleboxes
   such as NATs; to increase the effort required for casual passive
   observation of startup packets; to allow for 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

Thornburgh              Expires October 17, 2013               [Page 98]
Internet-Draft                 Adobe RTMFP                    April 2013

   address mobility using that or any substantially similar method
   REQUIRES at least that the Packet Encryption function of the
   Cryptography Profile (Section 2.2.3) employs a cryptographic
   verification mechanism comprising secret information known only to
   the two endpoints.  Without this constraint, that or any
   substantially similar method becomes "session hijacking support".

   Flows and packet fragmentation imply semantics that could cause
   unbounded resource utilization in receivers, causing a denial of
   service.  Implementations SHOULD guard against unbounded or excessive
   resource use, and abort sessions that appear abusive.

   A rogue but popular Redirector (Section 3.5.1.4) could direct session
   Initiators to flood a victim address or network with Initiator Hello
   packets, potentially causing a denial of service.

   An attacker that can passively observe an IHello and that possesses a
   certificate matching the Endpoint Discriminator (without having to
   know the private key, if any, associated with it) can deny the
   Initiator access to the desired Responder by sending an RHello before
   the desired Responder does, since only the first received RHello is
   selected by the Initiator.  The attacker needn't forge the desired
   Responder's source address, since the RHello is selected based on the
   tag echo and not the packet's source address.  This can simplify the
   attack in some network or host configurations.

6.  Acknowledgements

   Special thanks go to Matthew Kaufman for his contributions to the
   creation and design of RTMFP.

   Thanks to Wesley Eddy, Philipp Hancke, Bela Lubkin, and Martin
   Stiemerling for their detailed reviews of this memo.

7.  References

7.1.  Normative References

   [RFC0768]  Postel, J., "User Datagram Protocol", STD 6, RFC 768,
              August 1980.

   [RFC0791]  Postel, J., "Internet Protocol", STD 5, RFC 791,
              September 1981.

   [RFC1122]  Braden, R., "Requirements for Internet Hosts -
              Communication Layers", STD 3, RFC 1122, October 1989.

Thornburgh              Expires October 17, 2013               [Page 99]
Internet-Draft                 Adobe RTMFP                    April 2013

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

Appendix A.  Example Congestion Control Algorithm

   Section 3.5.2 mandates that an RTMFP use TCP-compatible congestion
   control, but allows flexibility in exact implementation 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

Thornburgh              Expires October 17, 2013              [Page 100]
Internet-Draft                 Adobe RTMFP                    April 2013

   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 RFC 5681 Section 3.1, which, when combined with
   the recommended behavior of acknowledging every other packet, causes
   the congestion window to grow at approximately half the rate as 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, which is approximately
   half of the typical maximum segment size of 1500 bytes while also
   being 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 every
   approximately 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 normal rate (incrementing at 384 bytes per round
   trip), both to compensate for the less aggressive loss response and
   to 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, both to yield capacity to the real-time flows and
   to 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 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

Thornburgh              Expires October 17, 2013              [Page 101]
Internet-Draft                 Adobe RTMFP                    April 2013

   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.

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 RFC 5681 Section 3.1, 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 to whether any loss has been detected in
      the current packet;

   o  ANY_NAKS: an indication to whether any negative acknowledgements
      have been detected in the current packet;

Thornburgh              Expires October 17, 2013              [Page 102]
Internet-Draft                 Adobe RTMFP                    April 2013

   o  ANY_ACKS: an indication to 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 (Section 2.2.4,
   Section 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 of Section 3.6.2.6 to manage transmission
   timeouts, including setting the TIMEOUT_ALARM.

   On being notified that the TIMEOUT_ALARM has fired, perform the
   function in Figure 23:

   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 23: 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              Expires October 17, 2013              [Page 103]
Internet-Draft                 Adobe RTMFP                    April 2013

   After processing all chunks in each received packet for this session,
   perform the function in Figure 24:

   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 SSHTRESH 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 24: Pseudocode for congestion window adjustment after
                            processing a packet

Thornburgh              Expires October 17, 2013              [Page 104]
Internet-Draft                 Adobe RTMFP                    April 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              Expires October 17, 2013              [Page 105]