Network Working Group                                      M. Thornburgh
Internet-Draft                                                     Adobe
Intended status: Informational                         February 14,                             April 5, 2013
Expires: August 18, October 7, 2013

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

Abstract

   This memo describes the Secure Real-Time Media Flow Protocol (RTMFP),
   an endpoint-to-endpoint communication protocol designed to securely
   transport parallel flows of real-time video, audio, and data
   messages, as well as bulk data, over IP networks.  RTMFP has features
   making it effective for peer-to-peer (P2P) as well as client-server
   communications, even when Network Address Translators (NATs) are
   used.

Status of this Memo

   This Internet-Draft is submitted in full conformance with the
   provisions of BCP 78 and BCP 79.  This document may not be modified,
   and derivative works of it may not be created, except to format it
   for publication as an RFC or to translate it into languages other
   than English.

   Internet-Drafts are working documents of the Internet Engineering
   Task Force (IETF).  Note that other groups may also distribute
   working documents as Internet-Drafts.  The list of current Internet-
   Drafts is at http://datatracker.ietf.org/drafts/current/.

   Internet-Drafts are draft documents valid for a maximum of six months
   and may be updated, replaced, or obsoleted by other documents at any
   time.  It is inappropriate to use Internet-Drafts as reference
   material or to cite them other than as "work in progress."

   This Internet-Draft will expire on August 18, October 7, 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.

Table of Contents

   1.  Introduction  . . . . . . . . . . . . . . . . . . . . . . . . .   5
     1.1.  Design Highlights of RTMFP  . . . . . . . . . . . . . . . .   5
     1.2.  Terminology . . . . . . . . . . . . . . . . . . . . . . .   6
   2.  Syntax  . . . . . . . . . . . . . . . . . . . . . . . . . . . .   7
     2.1.  Common Elements . . . . . . . . . . . . . . . . . . . . .   7
       2.1.1.  Elementary Types and Constructs . . . . . . . . . . .   7
       2.1.2.  Variable Length Unsigned Integer (VLU)  . . . . . . . .   8
       2.1.3.  Option  . . . . . . . . . . . . . . . . . . . . . . . .   9
       2.1.4.  Option List . . . . . . . . . . . . . . . . . . . . .  10
       2.1.5.  Internet Socket Address (Address) . . . . . . . . . .  11
     2.2.  Network Layer . . . . . . . . . . . . . . . . . . . . . .  12
       2.2.1.  Encapsulation . . . . . . . . . . . . . . . . . . . .  12
       2.2.2.  Multiplex . . . . . . . . . . . . . . . . . . . . . .  13
       2.2.3.  Encryption  . . . . . . . . . . . . . . . . . . . . . .  14
       2.2.4.  Packet  . . . . . . . . . . . . . . . . . . . . . . . .  14
     2.3.  Chunks  . . . . . . . . . . . . . . . . . . . . . . . . . .  17
       2.3.1.  Packet Fragment Chunk . . . . . . . . . . . . . . . .  18
       2.3.2.  Initiator Hello Chunk (IHello)  . . . . . . . . . . . .  19
       2.3.3.  Forwarded Initiator Hello Chunk (FIHello) . . . . . .  20
       2.3.4.  Responder Hello Chunk (RHello)  . . . . . . . . . . . .  21
       2.3.5.  Responder Redirect Chunk (Redirect) . . . . . . . . .  22
       2.3.6.  RHello Cookie Change Chunk  . . . . . . . . . . . . . .  24
       2.3.7.  Initiator Initial Keying Chunk (IIKeying) . . . . . .  25
       2.3.8.  Responder Initial Keying Chunk (RIKeying) . . . . . .  26
       2.3.9.  Ping Chunk  . . . . . . . . . . . . . . . . . . . . . .  28
       2.3.10. Ping Reply Chunk  . . . . . . . . . . . . . . . . . . .  29
       2.3.11. User Data Chunk . . . . . . . . . . . . . . . . . . .  29
         2.3.11.1.  Options for User Data  . . . . . . . . . . . . . .  31
           2.3.11.1.1.  User's Per-Flow Metadata . . . . . . . . . .  32
           2.3.11.1.2.  Return Flow Association  . . . . . . . . . . .  32
       2.3.12. Next User Data Chunk  . . . . . . . . . . . . . . . . .  33
       2.3.13. Data Acknowledgement Bitmap Chunk (Bitmap Ack)  . . . .  35
       2.3.14. Data Acknowledgement Ranges Chunk (Range Ack) . . . .  37
       2.3.15. Buffer Probe Chunk  . . . . . . . . . . . . . . . . . .  39
       2.3.16. Flow Exception Report Chunk . . . . . . . . . . . . .  39
       2.3.17. Session Close Request Chunk (Close) . . . . . . . . .  40
       2.3.18. Session Close Acknowledgement Chunk (Close Ack) . . .  40
   3.  Operation . . . . . . . . . . . . . . . . . . . . . . . . . .  41
     3.1.  Overview  . . . . . . . . . . . . . . . . . . . . . . . . .  41
     3.2.  Endpoint Identity . . . . . . . . . . . . . . . . . . . .  43
     3.3.  Packet Multiplex  . . . . . . . . . . . . . . . . . . . . .  44
     3.4.  Packet Fragmentation  . . . . . . . . . . . . . . . . . . .  44
     3.5.  Sessions  . . . . . . . . . . . . . . . . . . . . . . . . .  46
       3.5.1.  Startup . . . . . . . . . . . . . . . . . . . . . . .  48
         3.5.1.1.   Normal Handshake . . . . . . . . . . . . . . . .  48
           3.5.1.1.1.   Initiator  . . . . . . . . . . . . . . . . . .  49
           3.5.1.1.2.   Responder  . . . . . . . . . . . . . . . . . .  51
         3.5.1.2.   Cookie Change  . . . . . . . . . . . . . . . . . .  53
         3.5.1.3.   Glare  . . . . . . . . . . . . . . . . . . . . . .  54
         3.5.1.4.   Redirector . . . . . . . . . . . . . . . . . . .  55
         3.5.1.5.   Forwarder  . . . . . . . . . . . . . . . . . . . .  56
         3.5.1.6.   Redirector and Forwarder with NAT  . . . . . . . .  58
         3.5.1.7.   Load Distribution and Fault Tolerance  . . . . .  61
       3.5.2.  Congestion Control  . . . . . . . . . . . . . . . . . . 61  62
         3.5.2.1.   Time Critical Reverse Notification . . . . . . . 61  63
         3.5.2.2.   Retransmission Timeout . . . . . . . . . . . . . 62  63
         3.5.2.3.   Burst Avoidance  . . . . . . . . . . . . . . . . . 64  65
       3.5.3.  Address Mobility  . . . . . . . . . . . . . . . . . . . 65  66
       3.5.4.  Ping  . . . . . . . . . . . . . . . . . . . . . . . . . 65  66
         3.5.4.1.   Keepalive  . . . . . . . . . . . . . . . . . . . . 66  67
         3.5.4.2.   Address Mobility . . . . . . . . . . . . . . . . 66  67
         3.5.4.3.   Path MTU Discovery . . . . . . . . . . . . . . . 67  68
       3.5.5.  Close . . . . . . . . . . . . . . . . . . . . . . . . 67  68
     3.6.  Flows . . . . . . . . . . . . . . . . . . . . . . . . . . 68  69
       3.6.1.  Overview  . . . . . . . . . . . . . . . . . . . . . . . 68  69
         3.6.1.1.   Identity . . . . . . . . . . . . . . . . . . . . 68  70
         3.6.1.2.   Messages and Sequencing  . . . . . . . . . . . . . 69  70
         3.6.1.3.   Lifetime . . . . . . . . . . . . . . . . . . . . 70  71
       3.6.2.  Sender  . . . . . . . . . . . . . . . . . . . . . . . . 71  72
         3.6.2.1.   Startup  . . . . . . . . . . . . . . . . . . . . . 72  74
         3.6.2.2.   Queuing Data . . . . . . . . . . . . . . . . . . 73  75
         3.6.2.3.   Sending Data . . . . . . . . . . . . . . . . . . 73  75
           3.6.2.3.1.   Startup Options  . . . . . . . . . . . . . . . 75  77
           3.6.2.3.2.   Send Next Data . . . . . . . . . . . . . . . 75  77
         3.6.2.4.   Processing Acknowledgements  . . . . . . . . . . . 76  78
         3.6.2.5.   Negative Acknowledgement and Loss  . . . . . . . . 76  78
         3.6.2.6.   Timeout  . . . . . . . . . . . . . . . . . . . . . 77  79
         3.6.2.7.   Abandoning Data  . . . . . . . . . . . . . . . . . 78  80
           3.6.2.7.1.   Forward Sequence Number Update . . . . . . . 78  80
         3.6.2.8.   Examples . . . . . . . . . . . . . . . . . . . . 79  81
         3.6.2.9.   Flow Control . . . . . . . . . . . . . . . . . . 80  82
           3.6.2.9.1.   Buffer Probe . . . . . . . . . . . . . . . . 81  83
         3.6.2.10.  Exception  . . . . . . . . . . . . . . . . . . . . 81  83
         3.6.2.11.  Close  . . . . . . . . . . . . . . . . . . . . . . 81  83
       3.6.3.  Receiver  . . . . . . . . . . . . . . . . . . . . . . . 82  84
         3.6.3.1.   Startup  . . . . . . . . . . . . . . . . . . . . . 84  86
         3.6.3.2.   Receiving Data . . . . . . . . . . . . . . . . . 85  87
         3.6.3.3.   Buffering and Delivering Data  . . . . . . . . . . 87  89
         3.6.3.4.   Acknowledging Data . . . . . . . . . . . . . . . 89  91
           3.6.3.4.1.   Timing . . . . . . . . . . . . . . . . . . . 89  91
           3.6.3.4.2.   Size and Truncation  . . . . . . . . . . . . . 90  92
           3.6.3.4.3.   Constructing . . . . . . . . . . . . . . . . 91  93
           3.6.3.4.4.   Delayed Acknowledgement  . . . . . . . . . . . 91  93
           3.6.3.4.5.   Obligatory Acknowledgement . . . . . . . . . 91  93
           3.6.3.4.6.   Opportunistic Acknowledgement  . . . . . . . . 92  94
           3.6.3.4.7.   Example  . . . . . . . . . . . . . . . . . . . 92  94
         3.6.3.5.   Flow Control . . . . . . . . . . . . . . . . . . 93  95
         3.6.3.6.   Receiving a Buffer Probe . . . . . . . . . . . . 94  96
         3.6.3.7.   Rejecting a Flow . . . . . . . . . . . . . . . . 95  97
         3.6.3.8.   Close  . . . . . . . . . . . . . . . . . . . . . . 95  97
   4.  IANA Considerations . . . . . . . . . . . . . . . . . . . . . 96  98
   5.  Security Considerations . . . . . . . . . . . . . . . . . . . 96  98
   6.  Acknowledgements  . . . . . . . . . . . . . . . . . . . . . . . 97  99
   7.  References  . . . . . . . . . . . . . . . . . . . . . . . . . . 97  99
     7.1.  Normative References  . . . . . . . . . . . . . . . . . . . 97  99
     7.2.  Informative References  . . . . . . . . . . . . . . . . . 100
   Appendix A.  Example Congestion Control Algorithm . . 98 . . . . . . 100
     A.1.  Discussion  . . . . . . . . . . . . . . . . . . . . . . . 100
     A.2.  Algorithm . . . . . . . . . . . . . . . . . . . . . . . . 102
   Author's Address  . . . . . . . . . . . . . . . . . . . . . . . . . 98 104

1.  Introduction

   Adobe's Secure Real-Time Media Flow Protocol (RTMFP) is intended for
   use as an endpoint-to-endpoint data transport service in IP networks.
   It has features that make it well suited to the transport of real-
   time media (such as low-delay video, audio, and data) as well as bulk
   data, and for client-server as well as peer-to-peer (P2P)
   communication.  These features include independent parallel message
   flows which may have different delivery priorities, variable message
   reliability (from TCP-like full reliability to UDP-like best effort),
   multi-point congestion control, and built-in security.  Session
   multiplexing and facilities to support UDP hole-punching simplify
   Network Address Translator (NAT) traversal in peer-to-peer systems.

   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 and P2P communication in those
   products.  At the time of writing, the Adobe Flash Player runtime is
   installed on more than one billion end-user desktop computers.

   This memo describes the syntax and operation of the Secure Real-Time
   Media Flow Protocol.

1.1.  Design Highlights of RTMFP

   o  The security framework is an in-band part of the basic protocol
      and is always on.  The application designer chooses the
      cryptographic formats and algorithms to suit the needs of the
      application, and may update them as the state of the security arts
      progresses.

   o  Cryptographic Endpoint Discriminators can resist port scanning.

   o  All header, control, and framing information, except for network
      addressing information and a session identifier, is encrypted.

   o  There is a single session and associated congestion control state
      between a pair of endpoints.

   o  Each session may have zero or more unidirectional message-oriented
      flows in each direction.  All of a session's sending flows share
      the session's congestion control state.

   o  Return Flow Association (Section 2.3.11.1.2) generalizes
      bidirectional communication to arbitrarily complex trees of flows.

   o  Messages in flows can be arbitrarily large and are fragmented for
      transmission.

   o  Messages of any size may be sent with full, partial, or no
      reliability (sender's choice).  Messages may be delivered to the
      receiving user in original queuing order or network arrival order
      (receiver's choice).

   o  Flows are named with arbitrary, user-defined metadata
      (Section 2.3.11.1.1) rather than port or stream numbers.

   o  The sequence numbers of each flow are independent of all other
      flows, and are not permanently bound to a session-wide
      transmission ordering.  This allows real-time priority decisions
      to be made at transmission or retransmission time.

   o  Each flow has its own receive window, and therefore independent
      flow control.

   o  Round-trips are expensive, and are minimized or eliminated when
      possible.

   o  After a session is established, flows begin by sending the flow's
      messages with no additional handshake (and associated round-
      trips).

   o  Transmitting bytes on the network is much more expensive than
      moving bytes in a CPU or memory.  Wasted bytes are minimized or
      eliminated when possible and practical, and variable length
      encodings are used, even at the expense of breaking 32-bit
      alignment and making the text diagrams in this specification look
      awkward.

   o  P2P lookup and peer introduction (including UDP hole punching for
      NAT and firewall traversal) is supported directly by the session
      startup handshake.

   o  Session identifiers allow an endpoint to multiplex many sessions
      over a single local transport address while allowing sessions to
      survive changes in transport address (as may happen in mobile or
      wireless deployments).

1.2.  Terminology

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

2.  Syntax

   Definitions of types and structures in this specification use
   traditional text diagrams paired with procedural descriptions using a
   C-like syntax.

   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.

   The C-like procedural descriptions SHALL be construed as definitive.

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.

   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.

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.

   An option may have a length of zero, in which case it has no type and
   no value and is empty.  An empty option is called a "Marker".

   +-------------/-+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
   |   length    \ |    type     \ |            value              |
   +-------------/-+~~~~~~~~~~~~~/~+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
                   ^                                               ^
                   +-------- length bytes long (may be 0) ---------+

   struct option_t
   {
       vlu_t length :variable*8; // "L"
       if(length > 0)
       {
           struct {
               vlu_t   type :variable*8;   // "T"
               uint8_t value[remainder()]; // "V"
           } payload :length*8;
       }
   } :variable*8;

                             +---/---/-------+
                             | L \ T \   V   |
                             +---/---/-------+

             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;

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)

   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;

   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
   (Section 2.3.7, Section 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 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
   CBC (or similar) mode.  Encrypted packets MUST be decipherable
   without inter-packet dependency, since packets may be lost,
   duplicated, or reordered in the network.

   The packet encryption layer is responsible for data integrity and
   authenticity, for example by means of a checksum or cryptographic
   message authentication code.

   Note that the structures described below are of plain, unencrypted
   packets.  Encrypted packets MUST be decrypted according to the
   Session Key associated with the Multiplex Session ID before being
   interpreted according to this specification.

   The cryptography profile defines a well-known Default Session Key
   that is used at session startup, during which per-session key(s) are
   negotiated by the two endpoints.  A Session ID of zero denotes use of
   the Default Session Key. The Default Session Key is also used with
   non-zero Session IDs during the latter phases of session startup
   (Section 2.3.6, Section 2.3.8).  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.

    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;
   timeCritical :  Time Critical Forward Notification.  If set,
      indicates that this packet contains real-time user data.

   timeCriticalReverse :  Time Critical Reverse Notification.  If set,
      indicates that the sender is currently receiving packets on other
      sessions that have the timeCritical flag set.

   timestampPresent :  If set, indicates that the timestamp field is
      present.  If clear, there is no timestamp field.

   timestampEchoPresent :  If set, indicates that the timestamp echo
      field is present.  If clear, there is no timestamp echo field.

   mode :  The mode of this packet.  Values are:

      0 :  Forbidden value

      1 :  Initiator Mark

      2 :  Responder Mark

      3 :  Startup

   timestamp :  If the timestampPresent flag is set, this field is
      present and contains the low 16 bits of the sender's 250 Hz clock
      (4 milliseconds per tick) at transmit time.  The sender's clock
      MAY have its origin at any time in the past.

   timestampEcho :  If the timestampEchoPresent flag is set, this field
      is present and contains the sender's estimate of what the
      timestamp field of a packet received from the other end would be
      at the time this packet was transmitted, using the method
      described in Section 3.5.2.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 the current chunk indicates that the
         chunk payload wouldn't fit in the remaining bytes of the
         packet.

   Packet mode 0 is not allowed.  Packets marked with this mode are
   invalid and MUST be discarded.

   The original initiator of a session MUST mark all non-startup packets
   it sends in that session with packet mode 1 "Initiator Mark".  It
   SHOULD ignore any packet received in that session with packet mode 1.

   The original responder of a session MUST mark all non-startup packets
   it sends in that session with packet mode 2 "Responder Mark".  It
   SHOULD ignore any packet received in that session with packet mode 2.

   Packet mode 3 is for session startup.  Session startup chunks MUST
   ONLY be in packets with this mode.

   Chunks that are not for session startup MUST ONLY be in packets with
   modes 1 or 2.

2.3.  Chunks

    0 1 2 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).

   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)

   0x08 :  Reserved for future use

   0x48 :  Reserved for future use

   0x00 :  Ignore/Padding

   0xff :  Ignore/Padding

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.

   packetFragment :  The bytes of the indicated segment of the indicated
      original plain RTMFP packet.  A packetFragment MUST NOT be empty.

   The use of this mechanism is detailed in Section 3.4.

2.3.2.  Initiator Hello Chunk (IHello)

   This chunk is sent by the initiator of a new session to begin the
   startup handshake.  This chunk MUST ONLY be in a packet with Session
   ID 0, encrypted with the default session key, and having packet mode
   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.

2.3.3.  Forwarded Initiator Hello Chunk (FIHello)

   This chunk is sent on behalf of an initiator by a Forwarder.  It MUST
   ONLY be sent in an established session having packet mode 1 or 2.  A
   receiver MAY treat this chunk as though it was an Initiator Hello
   received directly from replyAddress.  Alternatively, if the receiver
   is selected by the Endpoint Discriminator, it MAY respond to
   replyAddress with an Implied Redirect (Section 2.3.5).

    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.

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 MUST ONLY be 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.

   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 address(es).  A receiver can
   add none, some, or all of the indicated address(es) to the set of
   addresses to which it is sending Initiator Hello messages for the
   opening session associated with tagEcho.  This chunk MUST ONLY be 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
   +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
   |      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 Section 3.5.1.1.1,
   Section 3.5.1.1.2, and Section 3.5.1.4.

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 which elicited the
   Responder Hello containing the original cookie).

   This chunk MUST ONLY be sent in a packet encrypted with the default
   session key and having packet mode 3, and with the Session ID
   indicated in the initiatorSessionID field of the Initiator Initial
   Keying to which this is a response.

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

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 MUST ONLY be 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.

   cookieLength :  VLU, the length of the following cookieEcho field in
      bytes.

   cookieEcho :  The cookie from the Responder Hello, unaltered.

   certLength :  VLU, the length of the following initiatorCertificate
      field in bytes.

   initiatorCertificate :  The initiator's identity credentials.

   skicLength :  VLU, the length of the following
      sessionKeyInitiatorComponent field in bytes.

   sessionKeyInitiatorComponent :  The initiator's portion of the
      session key negotiation according to the Cryptography Profile.

   initiatorSignedParameters :  The payload portion of this chunk up to
      the signature field.

   signature :  The initiator's digital signature of the
      initiatorSignedParameters according to the Cryptography Profile.

   Note: this specification doesn't mandate a specific choice of
   cryptography.  The Cryptography Profile determines the syntax,
   algorithms, and interpretation of the initiatorCertificate,
   responderCertificate, sessionKeyInitiatorComponent,
   sessionKeyResponderComponent, and signature, and how the
   sessionKeyInitiatorComponent and sessionKeyResponderComponent are
   combined to derive the session keys.

   The use of IIKeying is detailed in Section 3.5.1.

2.3.8.  Responder Initial Keying Chunk (RIKeying)

   This chunk is sent by a responder in response to an Initiator Initial
   Keying as the final phase of session startup.  This chunk MUST ONLY
   be in a packet encrypted with the default session key, having packet
   mode 3 (Startup), and sent to the initiator with the Session ID
   specified by the initiatorSessionID field from the Initiator Initial
   Keying.

    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.

   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.

2.3.9.  Ping Chunk

   This chunk is sent in order to elicit a Ping Reply from the receiver.
   It MUST ONLY be in a packet belonging to an established session and
   having packet mode 1 or 2.

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

2.3.10.  Ping Reply Chunk

   This chunk is sent in response to a Ping chunk.  It MUST ONLY be in a
   packet belonging to an established session and having packet mode 1
   or 2.

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

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 MUST ONLY be 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.

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

   The use of User Data is detailed in Section 3.6.2.

2.3.11.1.  Options for User Data

   This section lists options that may appear in User Data option lists.
   A conforming implementation MUST support the options in this section.

   A flow receiver MUST reject a flow containing a flow option that is
   not understood if the option type is less than 8192.  A flow receiver
   MUST ignore any flow option that is not understood if the option type
   is 8192 or greater.

   The following option type codes are defined for User Data:

   0x00 :  Users's Per-Flow Metadata (Section 2.3.11.1.1)

   0x0a :  Return Flow Association (Section 2.3.11.1.2)

2.3.11.1.1.  User's Per-Flow Metadata

   This option conveys the user's per-flow metadata for the flow to
   which it's attached.

   +-------------/-+-------------/-+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+
   |   length    \ |     0x00    \ |         userMetadata          |
   +-------------/-+-------------/-+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/

   struct userMetadataOptionValue_t
   {
       uint8_t userMetadata[remainder()];
   } :remainder()*8;

   The user associates application-defined metadata with each flow.  The
   metadata does not change over the life of the flow.  Every flow MUST
   have metadata.  A flow sender MUST send this option with the first
   User Data chunk for this flow in each packet until an acknowledgement
   for this flow is received.  A flow sender SHOULD NOT send this option
   more than once for each flow in any one packet.  A flow sender SHOULD
   NOT send this option for a flow once the flow has been acknowledged.

   This specification doesn't mandate the encoding, syntax, or
   interpretation of the user's per-flow metadata; this is determined by
   the application.

   The userMetadata SHOULD NOT exceed 512 bytes.  The userMetadata MAY
   be 0 bytes in length.

2.3.11.1.2.  Return Flow Association

   A new flow 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.

2.3.12.  Next User Data Chunk

   This chunk is equivalent to the User Data Chunk for purposes of
   sending the user messages of a flow.  When used, it MUST ONLY follow
   a User Data or another Next User Data chunk in the same packet.

    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.

              ...
              ----------+------------------------------------
              10 00 07  | User Data chunk, length=7
              10        | OPT=0, FRA=1 "begin", 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
              30        | OPT=0, FRA=3 "middle", 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
              20        | OPT=0, FRA=2 "end", ABN=0, FIN=0
                        | flowID=2, seq#=7, fsn=2
              06 07 08  | data 3 bytes: 06, 07, 08
              ----------+------------------------------------

       flowID=2, seq#=5, #frags=3, data: 00 01 02 03 04 05 06 07 08

               Figure 3: A fragmented message in one packet

   The use of Next User Data is detailed in Section 3.6.2.3.2.

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 sequence numbers that have been received for one
   flow.  It MUST ONLY be in a packet belonging to an established
   session and having packet mode 1 or 2.

   The flow receiver 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;

   flowID :  VLU, the flow identifier.

   bufferBlocksAvailable :  VLU, The number of 1024-byte blocks of User
      Data that the receiver is currently able to accept.

   cumulativeAck :  VLU, the acknowledgement of every 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 sequence numbers after the cumulative
      acknowledgement, least significant bit first.  A set bit indicates
      receipt of a sequence number.  A clear bit indicates that sequence
      number was not received.  The least significant bit of the first
      byte is the second sequence number following the cumulative
      acknowledgement, the next bit is the third sequence number
      following, and so on.

        50 00 05  | Bitmap Ack, length=5 bytes
        05 7f 10  | flowID=5, bufAvail=127*1024 bytes, cumAck=0..16
        79 06     | 01111001 00000110 = 18, 21, 22, 23, 24, 27, 28

    Example bitmap ack indicating acknowledgement of sequence numbers 0
                 through 16, 18, 21 through 24, 27 and 28.

                                 Figure 4

2.3.14.  Data Acknowledgement Ranges Chunk (Range Ack)

   This chunk is sent by the flow receiver to indicate to the flow
   sender the User Data sequence numbers that have been received for one
   flow.  It MUST ONLY be in a packet belonging to an established
   session and having packet mode 1 or 2.

   The flow receiver 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;

   flowID :  VLU, the flow identifier.

   bufferBlocksAvailable :  VLU, The number of 1024-byte blocks of User
      Data that the receiver is currently able to accept.

   cumulativeAck :  VLU, the acknowledgement of every 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.

     51 00 07  | Range Ack, length=7
     05 7f 10  | flowID=5, bufAvail=127*1024 bytes, cumAck=0..16
     00 00     | holes=1, received=1 -- missing 17, received 18
     01 03     | holes=2, received=4 -- missing 19..20, received 21..24

    Example range ack indicating acknowledgement of sequence numbers 0
                      through 16, 18, 21, 22, 23, 24.

                                 Figure 5

2.3.15.  Buffer Probe Chunk

   This chunk is sent by the flow sender in order to request the current
   available receive buffer (in the form of a Data Acknowledgement) for
   a flow.  It MUST ONLY be in a packet belonging to an established
   session and having packet mode 1 or 2.

    0 1 2 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 MUST ONLY be 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;

   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 MUST ONLY be
   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
   the sender has terminated the session.  It MUST ONLY be in a packet
   belonging to an established or closing session and having packet mode
   1 or 2.

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

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 6: 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 may learn and try more candidate addresses
   during startup handshaking.  Eventually a first suitable response is
   received, and that endpoint is selected.  Startup proceeds to the
   selected endpoint.  In the case of session startup glare, one
   endpoint is the prevailing initiator and the other assumes the role
   of responder.  Encryption keys and session identifiers are negotiated
   between the endpoints, and the session is established.

   Each endpoint may begin sending message flows to the other end.  For
   each flow, the far end may accept it and deliver its messages to the
   user, or it may reject the flow and transmit an exception to the
   sender.  The flow receiver may close and reject a flow at a later
   time, after first accepting it.  The flow receiver acknowledges all
   data sent to it regardless of whether the flow was accepted.
   Acknowledgements drive a congestion control mechanism.

   An endpoint may have concurrent sessions with other far endpoints.
   The multiple sessions are distinguished by a session identifier
   rather than by socket address.  This allows an endpoint's address to
   change mid-session without having to tear down and re-establish a
   session.  The existing cryptographic state for a session can be used
   to verify a change of address while protecting against session
   hijacking or denial-of-service.

   A sender may indicate to a receiver that some user messages are of a
   time-critical or real-time nature.  A receiver may indicate to
   senders on concurrent sessions that it is receiving time-critical
   messages from another endpoint.  The other senders SHOULD modify
   their congestion control parameters to yield capacity to the session
   carrying time-critical messages.

   A sender may close a flow.  The flow is completed when the receiver
   has no outstanding gaps before the final fragment of the flow.  The
   sender and receiver reserve a completed flow's identifier for a time
   to allow in-flight messages to drain from the network.

   Eventually, neither end will have any flows open to the other.  The
   session will be idle and quiescent.  Either end may reliably close
   the session to recover its resources.

   In certain circumstances, an endpoint may be ceasing operation and
   not have time to wait for acknowledgement of a reliable session
   close.  In this case the halting endpoint may send an abrupt session
   close to advise the far end that it is halting immediately.

3.2.  Endpoint Identity

   Each RTMFP endpoint has an identity.  The identity is encoded in a
   certificate.  This specification doesn't mandate any particular
   certificate format, cryptographic algorithms, or cryptographic
   properties for certificates.

   An endpoint is named by an Endpoint Discriminator.  This
   specification doesn't mandate any particular format for Endpoint
   Discriminators.

   An Endpoint Discriminator MAY select more than one identity, and MAY
   match more than one distinct certificate.

   Multiple distinct Endpoint Discriminators MAY match one certificate.

   Multiple endpoints SHOULD NOT have the same identity.

   An endpoint MAY have more than one address.

   The Cryptography Profile implements the following functions for
   identities, certificates, and Endpoint Discriminators, whose
   operation MUST be deterministic:

   o  Test whether a given certificate is authentic.  Authenticity MAY
      comprise verifying an issuer signature chain in a public key
      infrastructure.

   o  Test whether a given Endpoint Discriminator selects a given
      certificate.

   o  Test whether a given Endpoint Discriminator selects the local
      endpoint.

   o  Generate a Canonical Endpoint Discriminator for a given
      certificate.  Canonical Endpoint Discriminators for distinct
      identities SHOULD be distinct.

   o  Given a certificate, a message, and a digital signature over the
      message, test whether the signature is valid and generated by the
      owner of the certificate.

   o  Generate a digital signature for a given message corresponding to
      the near identity.

   o  Given the near identity and a far certificate, determine which one
      shall prevail as Initiator and which shall assume the Responder
      role in the case of startup glare.  The far end MUST arrive at the
      same conclusion.  A comparison function MAY comprise performing a
      lexicographic ordering of the binary certificates, and declaring
      the far identity the prevailing endpoint if the far certificate is
      ordered before the near certificate, and otherwise declaring the
      near identity to be the prevailing endpoint.

   o  Given a first certificate and a second certificate, test whether a
      new incoming session from the second shall override an existing
      session with the first.  A test SHOULD comprise testing whether
      the certificates are identical.

   All other semantics for certificates and Endpoint Discriminators are
   determined by the Cryptography Profile and the application.

3.3.  Packet Multiplex

   An RTMFP typically has one or more interfaces through which it
   communicates with other RTMFP endpoints.  RTMFP can communicate with
   multiple distinct other RTMFP endpoints through each local interface.
   Session multiplexing over a shared interface can facilitate peer-to-
   peer communications through a NAT, by enabling third party endpoints
   such as Forwarders (Section 3.5.1.5) and Redirectors
   (Section 3.5.1.4) to observe the translated public address and inform
   peers of the translation.

   An interface is typically a UDP socket (Section 2.2.1), but MAY be
   any suitable datagram transport service where endpoints can be
   addressed by IPv4 or IPv6 socket addresses.

   RTMFP uses a session ID to multiplex and demultiplex communications
   with distinct endpoints (Section 2.2.2), in addition to the endpoint
   socket address.  This allows an RTMFP to detect a far-end address
   change (as might happen for example in mobile and wireless scenarios)
   and for communication sessions to survive address changes.  This also
   allows an RTMFP to act as a Forwarder or Redirector for an endpoint
   with which it has an active session, by distinguishing startup
   packets from those of the active session.

   On receiving a packet, an RTMFP decodes the session ID to look up the
   corresponding session information context and decryption key.
   Session ID 0 is reserved for session startup and MUST NOT be used for
   an active session.  A packet for session ID 0 uses the Default
   Session Key as defined by the Cryptography Profile.

3.4.  Packet Fragmentation

   When an RTMFP packet (Section 2.2.4) is unavoidably larger than the
   path MTU (such as a startup packet containing an RHello
   (Section 2.3.4) or IIKeying (Section 2.3.7) chunk with a large
   certificate), it can be fragmented into segments that do not exceed
   the path MTU using the Packet Fragment chunk (Section 2.3.1).

   The packet fragmentation mechanism SHOULD ONLY be used to segment
   unavoidably large packets.  Accordingly, this mechanism SHOULD ONLY
   be employed during session startup with session ID 0.  This mechanism
   MUST NOT be used instead of the natural fragmentation mechanism of
   the User Data (Section 2.3.11) and Next User Data (Section 2.3.12)
   chunks for dividing the messages of the user's data flows into
   segments that do not exceed the path MTU.

   A fragmented plain RTMFP packet is reassembled by concatenating the
   packetFragment fields of the fragments for the packet in contiguous
   ascending order, starting from index 0 through and including the
   final fragment.

   When reassembling packets for Session ID 0, a receiver SHOULD
   identify the packets by both the socket address from which the packet
   containing the fragment was received as well as the indicated
   packetID.

   A receiver SHOULD allow up to 60 seconds to completely receive a
   fragmented packet for which progress is being made.  A packet is
   progressing if at least one new fragment for it was received in the
   last second.

   A receiver MUST discard a Packet Fragment chunk having an empty
   packetFragment field.

   The mode of each packet containing Packet Fragments for the same
   fragmented packet MUST match the mode of the fragmented packet.  A
   receiver MUST discard any new Packet Fragment chunk received in a
   packet with a mode different from the mode of the packet containing
   the first received fragment.  A receiver MUST discard any reassembled
   packet with a mode different than the packets containing its
   fragments.

   In order to avoid jamming the network, the sender MUST rate limit
   packet transmission.  In the absence of specific path capacity
   information (for instance, during session startup), a sender SHOULD
   NOT send more than 4380 bytes nor more than four packets per distinct
   endpoint every 200ms.

   To avoid resource exhaustion, a receiver SHOULD limit the number of
   concurrent packet reassembly buffers and the size of each buffer.

3.5.  Sessions

   A session is the protocol relationship between a pair of
   communicating endpoints, comprising the shared and endpoint-specific
   information context necessary to carry out the communication.  The
   session context at each end includes at least:

   o  TS_RX: the last timestamp received from the far end;

   o  TS_RX_TIME: the time at which TS_RX was first observed to be
      different than its previous value;

   o  TS_ECHO_TX: the last timestamp echo sent to the far end;

   o  MRTO: the measured retransmission timeout;

   o  ERTO: the effective retransmission timeout;

   o  Cryptographic keys for encrypting and decrypting packets, and for
      verifying the validity of packets, according to the Cryptography
      Profile;

   o  Cryptographic near and far nonces, according to the Cryptography
      Profile, the near nonce being the far end's far nonce, and vice
      versa;

   o  The certificate of the far end;

   o  The receive session identifier, used by the far end when sending
      packets to this end;

   o  The send session identifier to use when sending packets to the far
      end;

   o  DESTADDR: the socket address to which to send packets to the far
      end;

   o  The set of all sending flow contexts (Section 3.6.2);

   o  The set of all receiving flow contexts (Section 3.6.3);

   o  The transmission budget, which controls the rate at which data is
      sent into the network (for example, a congestion window);

   o  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 of this end of the session, which is either Initiator or
      Responder.

    Note: this 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
       |                     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 |--------------------+
       |   +-+           +--------+                    |
       |              CLOSE|    |rcv Close Ack         |
       |                   |    |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 7: Session state diagram

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, it 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 8: Normal handshake

   In the following sections the handshake is detailed from the
   perspectives of the Initiator and Responder.

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.  The Tag SHOULD be cryptographically pseudorandom
   and SHOULD NOT be less than 8 bytes in length.  The Initiator
   constructs an IHello chunk (Section 2.3.2) with the Endpoint
   Discriminator and the Tag.

   While the Initiator is in the 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

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

   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,

       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 to reach a Forwarder (Section 3.5.1.5) but another to reach
   the Responder.

   Consider the following example: Initiator has two network interfaces,
   a first preferred interface with address Ix = 192.0.2.100:50000, and
   a second with address Iy = 198.51.100.101:50001.  Responder has one
   interface with address Ry = 198.51.100.200:51000, on the same network
   as Initiator's second interface.  Initiator uses its first interface
   to reach a Forwarder.  Forwarder observes Initiator's address of Ix
   and sends a Forwarded IHello (Section 2.3.3) to Responder.  Responder
   treats this as if it was an IHello from Ix, calculates a
   corresponding cookie, and sends an RHello to Ix.  Initiator receives
   this RHello from Ry and selects that address as the destination for
   the session.  It then sends an IIKeying, copying the cookie from the
   RHello.  However, since the source of the RHello is Ry, on a network
   to which the Initiator is directly connected, Initiator uses its
   second interface Iy to send the IIKeying.  Responder, on receiving
   the IIKeying, will compare the cookie to the expected value based on
   the source address of the packet, and since the IIKeying source
   doesn't match the IHello source used to generate the cookie,
   Responder will reject the IIKeying.

   If Responder determines that it generated the cookie in the IIKeying
   but the cookie doesn't match the sender's address (for example, if
   the cookie is in two parts, with a first part generated independently
   of the Initiator's address, and a second part dependent on the
   address), Responder SHOULD generate a new cookie based on the address
   from which the IIKeying was received, and send an RHello Cookie
   Change chunk (Section 2.3.6) to the source of the IIKeying, using the
   session ID from the IIKeying and the Default Session Key.

   If 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: Initiator adopts the new
   cookie, constructs and signs a new IIKeying chunk, and sends the new
   IIKeying to the Responder.  Initiator SHOULD NOT change the cookie
   for a session more than once.

    Initiator                    Forwarder                     Responder
    | IHello                         |                                 |
    |(Src=Ix)                        |                                 |
    |------------------------------->|                                 |
    |                                | FIHello                         |
    |                                |(RA=Ix)                          |
    |                                |-------------------------------->|
    |                                                                  |
    |                                                           RHello |
    |                                                       (Cookie:Ix)|
    |<-----------------------------------------------------------------|
    |                                                                  |
    | IIKeying                                                         |
    |(Cookie:Ix,Src=Iy)                                                |
    |----------------------------------------------------------------->|
    |                                                                  |
    |                                             RHello Cookie Change |
    |                                             (Cookie:Ix,Cookie:Iy)|
    |<-----------------------------------------------------------------|
    |                                                                  |
    | IIKeying                                                         |
    |(Cookie:Iy)                                                       |
    |----------------------------------------------------------------->|
    |                                                                  |
    |                                                         RIKeying |
    |<-----------------------------------------------------------------|
    |                                                                  |
    |<======================== S E S S I O N =========================>|

                  Figure 9: Handshake with Cookie Change

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 which is a destination
   for an opening session.  Only one session is allowed between a pair
   of endpoints.

   Glare is resolved by comparing the certificate in the received
   IIKeying with the near end's certificate.  The Cryptography Profile
   defines a certificate comparison function to determine the prevailing
   endpoint when there is glare.

   If the near end prevails, discard and ignore the received IIKeying.
   The far end will abort its opening session on receipt of IIKeying
   from the near end.

   Otherwise, the far end prevails:

   1.  If the certificate in the IIKeying overrides the certificate
       associated with the near opening session according to the
       Cryptography Profile, then: abort and destroy the near opening
       session.  Then,

   2.  Continue with normal Responder IIKeying processing
       (Section 3.5.1.1.2).

3.5.1.4.  Redirector

       +-----------+           +------------+          +-----------+
       | Initiator |---------->| Redirector |          | Responder |
       |           |<----------|            |          |           |
       |           |           +------------+          |           |
       |           |<=================================>|           |
       +-----------+                                   +-----------+

                           Figure 10: 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 a Responder Redirect chunk (Section 2.3.5) back to the
   Initiator 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 11: Handshake using a Redirector

   Redirectors SHOULD NOT initiate new sessions to endpoints which might
   use the Redirector's address as a candidate for another endpoint,
   since the far end might interpret the Redirector's IIKeying as glare
   for the far end's initiation to the other endpoint.

3.5.1.5.  Forwarder

        +-----------+     +-----------+     +---+     +-----------+
        | Initiator |---->| Forwarder |<===>| N |<===>| Responder |
        |           |     +-----------+     | A |     |           |
        |           |<=====================>| T |<===>|           |
        +-----------+                       +---+     +-----------+

                           Figure 12: 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.

   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 13: Forwarder handshake where Responder sends an RHello

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

      Figure 14: 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 15: Introduction service for Initiator and Responder behind
                                   NATs

   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.

   Responder is registered with the introduction service via an S_OPEN
   session to it.  The service observes and records Responder's public
   NAT address as the DESTADDR of the S_OPEN session.  The service MAY
   record other addresses for Responder, for example addresses Responder
   self-reports as being directly attached.

   Initiator begins with an address of the introduction service as an
   initial candidate.  The Redirector portion of the service sends a
   Responder Redirect to Initiator containing at least Responder's
   public NAT address as previously recorded.  The Forwarder portion of
   the service sends a Forwarded IHello to Responder containing
   Initiator's public NAT address as observed as the source of the
   IHello.

   Responder sends an RHello to Initiator's public NAT address in
   response to the FIHello.  This will allow inbound packets to
   Responder through its NAT from Initiator's public NAT address.

   Initiator sends an IHello to Responder's public NAT address in
   response to the Responder Redirect.  This will allow inbound packets
   to Initiator through its NAT from Responder's public NAT address.

   With transit paths created in both NATs, normal session startup can
   proceed.

    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 16: Handshake with Redirector and Forwarder

   At the point in the diagram marked (*), Responder's RHello from the
   FIHello might arrive at Initiator's NAT before or after Initiator's
   IHello is sent outbound to 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 Initiator and Responder
   to each other and the introduction service.

3.5.2.  Congestion Control

   An RTMFP MUST implement congestion control

3.5.1.7.  Load Distribution and avoidance algorithms
   that are "TCP compatible", in accordance with Internet best current
   practice [RFC2914].  The algorithms SHOULD NOT be 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 17: Parallel Open to Multiple Endpoints

   Section 3.2 allows more aggressive than those described in TCP Congestion Control [RFC5681], and MUST
   NOT one endpoint to be selected by one
   Endpoint Discriminator.  This will typically be more aggressive than the "slow start algorithm" described in
   RFC 5681 Section 3.1.

   An endpoint maintains case for a transmission budget in the session
   information context set of
   servers, any of each S_OPEN session (Section 3.5), controlling
   the rate at which the could accommodate a connecting client.

   Section 3.5.1.1.1 allows an Initiator to use multiple candidate
   endpoint sends data into the network.

   For window-based congestion control addresses when starting a session, and avoidance algorithms, the
   transmission budget is specifies that the congestion window, which is
   the amount sender of
   user data that is allowed the first acceptable RHello chunk to be outstanding, or in flight, in the
   network.  Transmission is allowed when S_OUTSTANDING_BYTES
   (Section 3.5) received is less than
   selected to complete the congestion window (Section 3.6.2.3). session, with later responses ignored.  An endpoint avoids sending large bursts of data or packets into
   Initiator can start with the
   network (Section 3.5.2.3).

   A sending multiple candidate endpoint increases and decreases its transmission budget in
   response to acknowledgements addresses,
   or it may learn them during startup from one or more Redirectors
   (Section 3.6.2.4) and loss according 3.5.1.4).

   Parallel open to multiple endpoints for the congestion control and avoidance algorithms.  Loss is detected same Endpoint
   Discriminator combined with selection by
   negative acknowledgement (Section 3.6.2.5) earliest RHello can be used
   for load distribution and timeout
   (Section 3.6.2.6).

   Timeout fault tolerance.  The cost at each endpoint
   that is determined by the Effective Retransmission Timeout ERTO
   (Section 3.5.2.2).  ERTO not selected 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 limited to measure receipt of data, or lack thereof.

   A receiving endpoint and processing an
   IHello, and generating and sending an RHello.

   In one circumstance, multiple servers of similar processing and
   networking capacity may be receiving time critical (or real-time)
   data from located in near proximity to each other,
   such as in a first sender while receiving data from other senders.
   The receiving endpoint center.  In this circumstance, a less heavily
   loaded server can signal its other senders (Section 2.2.4)
   to cause them respond to decrease the aggressiveness of their congestion
   control an IHello more quickly than more heavily
   loaded servers, and avoidance algorithms, in order will tend to yield 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 capacity
   distance) to the time critical data (Section 3.5.2.1).

3.5.2.1.  Time Critical Reverse Notification

   A sender client can increase its transmission budget at a rate compatible
   with (but not exceeding) respond more quickly than more distant
   servers, and will tend to be selected by the "slow start algorithm" specified client.

   Multiple servers, in RFC
   5681 (with which the transmission rate is doubled every round trip
   when beginning proximity or restarting transmission, until loss is detected).

   However, distant from one another, can form
   a sender MUST behave as though the slow start threshold
   SSTHRESH is clamped redundant pool of servers.  A client can perform a parallel open 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 multiple servers.  In normal operation, the far end within multiple servers will
   all respond, and the last 800 milliseconds, unless client will select one of them as described
   above.  If one of the sender
   is itself currently sending time critical data multiple servers fails, other servers in the
   pool can still respond to the far end.

   During each round trip, a sender client, allowing the client to
   successfully complete 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 increase the transmission
   budget by be more aggressive
   than 0.5% or by 384 bytes per round trip (whichever is
   greater) on those described in TCP Congestion Control [RFC5681], and MUST
   NOT be more aggressive than the "slow start algorithm" described in
   RFC 5681 Section 3.1.

   An endpoint maintains a transmission budget in the session where a Time Critical Reverse Notification
   indication has been received from
   information context of each S_OPEN session (Section 3.5), controlling
   the far end within rate at which the last 800
   milliseconds, unless endpoint sends data into the sender network.

   For window-based congestion control and avoidance algorithms, the
   transmission budget is itself currently sending time
   critical data to the far end.

3.5.2.2.  Retransmission Timeout

   RTMFP uses congestion window, which is the Effective Retransmission Timeout ERTO to detect when a amount of
   user data fragment has been lost that is allowed to be outstanding, or in flight, in the
   network.  The ERTO  Transmission is
   typically calculated in a manner similar to that specified in
   Requirements allowed when S_OUTSTANDING_BYTES
   (Section 3.5) is less than the congestion window (Section 3.6.2.3).
   See Appendix A for Internet Hosts - Communication Layers [RFC1122], an experimental window-based congestion control
   algorithm for real-time and
   is a function bulk data.

   An endpoint avoids sending large bursts of round trip time measurements data or packets into the
   network (Section 3.5.2.3).

   A sending endpoint increases and persistent timeout
   behavior.

   The ERTO SHOULD be at least 250 milliseconds decreases its transmission budget in
   response to acknowledgements (Section 3.6.2.4) and SHOULD allow for the
   receiver loss according to delay sending an
   the congestion control and avoidance algorithms.  Loss is detected by
   negative acknowledgement for up to 200
   milliseconds (Section 3.6.3.4.4).  The ERTO MUST NOT be less than 3.6.2.5) and timeout
   (Section 3.6.2.6).

   Timeout is determined by the
   round trip time.

   To facilitate round trip time measurement, an endpoint MUST implement Effective Retransmission Timeout ERTO
   (Section 3.5.2.2).  ERTO is measured using the Timestamp and
   Timestamp Echo facility:

   o  On a session entering the S_OPEN state, initialize TS_RX_TIME packet header fields (Section 2.2.4).

   A receiving endpoint acknowledges all received data (Section 3.6.3.4)
   to
      negative infinity, and TS_RX and TS_ECHO_TX enable the sender to have no value.

   o  On measure receipt of data, or lack thereof.

   A receiving endpoint may be receiving time critical (or real-time)
   data from a packet in an S_OPEN session with the
      timestampPresent first sender while receiving data from other senders.
   The receiving endpoint can signal its other senders (Section 2.2.4) flag set, if the timestamp field
      in the packet is different than TS_RX: set TS_RX
   to cause them to decrease the value aggressiveness of
      the timestamp field in the packet, their congestion
   control and set TS_RX_TIME to the
      current time.

   o  When sending a packet to the far end avoidance algorithms, 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 order to have no value and do not include a timestamp
          echo; otherwise

      2.  Calculate TS_RX_ELAPSED_TICKS yield network capacity
   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 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 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 exceeding) the Effective Retransmission Timeout ERTO.  Real-time
   applications and P2P mesh applications often require knowing "slow start algorithm" specified in RFC
   5681 (with which the transmission rate is doubled every round trip time and RTT variance.  This section additionally
   describes
   when beginning or restarting transmission, until loss is detected).
   However, a method for measuring sender MUST behave as though the round trip time and RTT
   variance, and calculating a smoothed round trip time.

   Let slow start threshold
   SSTHRESH is clamped to 0 (disabling the slow start algorithm's
   exponential increase behavior) on a session information context contain additional variables:

   o  TS_TX: where a Time Critical
   Reverse Notification (Section 2.2.4) indication has been received
   from the far end within the last timestamp sent 800 milliseconds, unless the sender
   is itself currently sending time critical data to the far end, initialized to have
      no value;

   o  TS_ECHO_RX: end.

   During each round trip, a sender SHOULD NOT increase the last timestamp echo 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,
      initialized to have no value;

   o  SRTT: end within the smoothed round-trip time, initialized to have no value;

   o  RTTVAR: last 800
   milliseconds, unless the round-trip sender is itself currently sending time variance, initialized to 0;

   Initialize MRTO
   critical data to 250 milliseconds.

   Initialize the far end.

3.5.2.2.  Retransmission Timeout

   RTMFP uses the Effective Retransmission Timeout ERTO to 3 seconds.

   On sending detect when a packet to
   user data fragment has been lost in the far end 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 an S_OPEN session, if round trip time measurements and persistent timeout
   behavior.

   The ERTO SHOULD be at least 250 milliseconds and SHOULD allow for the
   current send timestamp is not equal
   receiver to TS_TX, then: set TS_TX delay sending an acknowledgement for up to 200
   milliseconds (Section 3.6.3.4.4).  The ERTO MUST NOT be less than the
   current send timestamp, set
   round trip time.

   To facilitate round trip time measurement, an endpoint MUST implement
   the timestampPresent flag in Timestamp Echo facility:

   o  On a session entering the packet
   header, S_OPEN state, initialize TS_RX_TIME to
      negative infinity, and set the timestamp field TS_RX and TS_ECHO_TX to TS_TX. have no value.

   o  On receipt of a packet from the far end of in an S_OPEN session, if session with the
   timestampEchoPresent
      timestampPresent (Section 2.2.4) flag is set set, if the timestamp field
      in the packet header AND is different than TS_RX: set TS_RX to the
   timestampEcho value of
      the timestamp field is not equal in the packet, and set TS_RX_TIME to TS_ECHO_RX, then:

   1.  Set TS_ECHO_RX the
      current time.

   o  When sending a packet to timestampEcho;

   2. the far end in an S_OPEN session:

      1.  Calculate RTT_TICKS TS_RX_ELAPSED = (current send timestamp current time - timestampEcho)
       MODULO 65536;

   3. TS_RX_TIME.  If RTT_TICKS
          TS_RX_ELAPSED is greater more than 32767, the measurement is invalid,
       so discard this measurement; 128 seconds, then set TS_RX and
          TS_ECHO_TX to have no value and do not include a timestamp
          echo; otherwise

   4.

      2.  Calculate RTT = RTT_TICKS * TS_RX_ELAPSED_TICKS to be the number of whole 4 milliseconds;

   5.  If SRTT has a value,
          millisecond periods in TS_RX_ELAPSED; then calculate new values of RTTVAR and
       SRTT:

       1.  RTT_DELTA = | SRTT - RTT |;

       2.  RTTVAR = ((3 * RTTVAR) + RTT_DELTA) / 4;

      3.  SRTT  Calculate TS_ECHO = ((7 * SRTT) (TS_RX + RTT) / 8;

   6.  If SRTT has no value, TS_RX_ELAPSED_TICKS) MODULO
          65536; then

      4.  If TS_ECHO is not equal to TS_ECHO_TX, then: set SRTT = RTT and RTTVAR = RTT / 2;

   7.  Set MRTO = SRTT + 4 * RTTVAR + 200 milliseconds;

   8.  Set ERTO TS_ECHO_TX to
          TS_ECHO, set the greater of MRTO or 250 milliseconds.

   A retransmission timeout occurs when the most recently transmitted
   user data fragment has remained outstanding in timestampEchoPresent flag, and set the network for ETRO.
   When
          timestampEcho field to TS_ECHO_TX.

   The remainder of this timeout occurs, increase ERTO on an exponential backoff
   with section describes an ultimate backoff cap of 10 seconds:

   1.  Calculate ERTO_BACKOFF = ERTO * 1.4142;

   2.  Calculate ERTO_CAPPED to be OPTIONAL method for
   calculating the lesser of ERTO_BACKOFF Effective Retransmission Timeout ERTO.  Real-time
   applications and 10
       seconds;

   3.  Set ERTO to P2P mesh applications often require knowing the greater of ERTO_CAPPED
   round trip time and MRTO.

3.5.2.3.  Burst Avoidance

   An application's sending patterns may cause the transmission budget
   to grow to RTT variance.  This section additionally
   describes a large value but, at times, method for there to be a
   comparatively small amount of data outstanding in the network.  In
   this circumstance, especially with a window-based congestion
   avoidance algorithm, if the application then has a large amount of
   new data to send (for example, a new bulk data transfer), it could
   send data into the network all at once to fill measuring the window.  This kind
   of transmission burst can jam interfaces, links, round trip time and buffers, RTT
   variance, and is
   undesirable.

   Accordingly, in any session, an endpoint SHOULD NOT send more than
   six packets containing user data between receiving acknowledgements
   or retransmission timeouts.

   The following describes an OPTIONAL method to avoid bursting large
   numbers of packets into the network. calculating a smoothed round trip time.

   Let the session information context contain an additional variable
   DATA_PACKET_COUNT, variables:

   o  TS_TX: the last timestamp sent to the far end, initialized to 0.

   Transmission of a user data fragment on this session is not allowed
   if DATA_PACKET_COUNT is greater than or equal have
      no value;

   o  TS_ECHO_RX: the last timestamp echo received from the far end,
      initialized to 6, regardless of any
   other allowance of have no value;

   o  SRTT: the congestion control algorithm.

   On transmission of a packet containing at least one User Data chunk
   (Section 2.3.11), set DATA_PACKET_COUNT = DATA_PACKET_COUNT + 1.

   On receipt of an acknowledgement chunk (Section 2.3.13,
   Section 2.3.14), set DATA_PACKET_COUNT smoothed round-trip time, initialized to 0.

   On a retransmission timeout, set DATA_PACKET_COUNT have no value;

   o  RTTVAR: the round-trip time variance, initialized 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 0;

   Initialize MRTO to change during
   an S_OPEN session.  This can happen, for example, when switching from
   a wireless 250 milliseconds.

   Initialize ERTO to 3 seconds.

   On sending a wired network, or when moving from one wireless base
   station packet to another, or when a NAT restarts.

   If the near far end receives a valid packet for of 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 session, if the far end
   current send timestamp is
   definitively at not equal to TS_TX, then: set TS_TX to the new address before changing DESTADDR.  A
   suggested verification method is described in Section 3.5.4.2.

3.5.4.  Ping

   If an endpoint receives a Ping chunk (Section 2.3.9) in a session
   current send timestamp, set the timestampPresent flag in the S_OPEN state, it SHOULD construct packet
   header, and send a Ping Reply chunk
   (Section 2.3.10) in response if possible, copying set the message
   unaltered.  A Ping Reply response SHOULD be sent as quickly as
   possible following timestamp field to TS_TX.

   On 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 ONLY be sent as a response to a Ping.

   Receipt of a Ping Reply implies live bidirectional connectivity.

   This specification doesn't mandate any other semantics for a Ping
   Reply.

3.5.4.1.  Keepalive

   An endpoint can use Ping to test for live bidirectional connectivity,
   to test that packet from the far end of a session an S_OPEN session, if the
   timestampEchoPresent flag is still S_OPEN, to keep NAT
   translations alive, and to keep firewall holes open.

   An endpoint can use Ping to hasten detection by set in the far end of a near
   end address change.

   An endpoint may declare a session to be defunct and dead after a
   persistent failure by packet header AND the far end
   timestampEcho field is not equal to return Ping Replies in response TS_ECHO_RX, then:

   1.  Set TS_ECHO_RX to Pings. timestampEcho;

   2.  Calculate RTT_TICKS = (current send timestamp - timestampEcho)
       MODULO 65536;

   3.  If used for these purposes, a Keepalive Ping SHOULD have an empty
   message.

   A Keepalive Ping SHOULD NOT be sent more often RTT_TICKS is greater than once per ERTO. 32767, the measurement is invalid,
       so discard this measurement; otherwise

   4.  Calculate RTT = RTT_TICKS * 4 milliseconds;

   5.  If SRTT has a corresponding Ping Reply is not received within ERTO value, then calculate new values of sending
   the Ping, ERTO SHOULD be increased according to Congestion Control
   (Section 3.5.2).

3.5.4.2.  Address Mobility

   This section describes an OPTIONAL but suggested method for
   processing and verifying a far end address change.

   Let the session context contain additional variables MOB_TX_TS,
   MOB_RX_TS, and MOB_SECRET.  MOB_TX_TS RTTVAR 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
       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 known only RTTVAR = RTT / 2;

   7.  Set MRTO = SRTT + 4 * RTTVAR + 200 milliseconds;

   8.  Set ERTO 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 S_OPEN, AND the source
   address greater of MRTO or 250 milliseconds.

   A retransmission timeout occurs when the packet does not match DESTADDR, AND MOB_TX_TS is at
   least one second most recently transmitted
   user data fragment has remained outstanding in the past, then: network for ETRO.
   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 the lesser of ERTO_BACKOFF and 10
       seconds;

   3.  Set MOB_TX_TS ERTO to the current time;

   2.  Construct a Ping message comprising: a marking greater of ERTO_CAPPED and MRTO.

3.5.2.3.  Burst Avoidance

   An application's sending patterns may cause the transmission budget
   to grow 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' large value but, at times, for
       "Mobility"), a timestamp set there to MOB_TX_TS, and be a cryptographic
       hash over the preceding as well as the address from which
   comparatively small amount of data outstanding in the
       packet was received and MOB_SECRET; and

   3.  Send network.  In
   this Ping to the address from which the packet was received,
       instead of DESTADDR.

   On receipt of circumstance, especially with a Ping Reply in an S_OPEN session, window-based congestion
   avoidance algorithm, if the Ping Reply's
   message satisfies all of these conditions:

   o  it application then has this end's expected marking a large amount of
   new data to indicate it is send (for example, a mobility
      check, and

   o new bulk data transfer), it could
   send data into the timestamp in network all at once to fill the message window.  This kind
   of transmission burst can jam interfaces, links, and buffers, and is not
   undesirable.

   Accordingly, in any session, an endpoint SHOULD NOT send more than 120 seconds in the
      past, and

   o
   six packets containing user data between receiving acknowledgements
   or retransmission timeouts.

   The following describes an OPTIONAL method to avoid bursting large
   numbers of packets into the timestamp in network.

   Let the message 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 MOB_RX_TS, and

   o  the cryptographic hash matches the expected value according or equal to the
      contents 6, regardless of the message plus the source address any
   other allowance of the congestion control algorithm.

   On transmission of a packet containing this Ping Reply and MOB_SECRET,

   then: at least one User Data chunk
   (Section 2.3.11), set DATA_PACKET_COUNT = DATA_PACKET_COUNT + 1.  Set MOB_RX_TS

   On receipt of an acknowledgement chunk (Section 2.3.13,
   Section 2.3.14), set DATA_PACKET_COUNT to the timestamp in the message; and

   2.  Set DESTADDR 0.

   On a retransmission timeout, set DATA_PACKET_COUNT 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 0.

3.5.3.  Address Mobility

   Sessions are demultiplexed with a method
   for measuring the path MTU between communicating endpoints.

   An RTMFP SHOULD perform path MTU discovery.

   The method of RFC 4821 32 bit session ID, rather than by
   endpoint address.  This allows an endpoint's address to change during
   an S_OPEN session.  This can be adapted happen, for use in RTMFP by sending example, when switching from
   a
   probe packet comprising wireless to a wired network, or when moving from one of the Padding chunk types (type 0x00 wireless base
   station to another, or
   0xff) and when a Ping.  The Ping chunk SHOULD come after NAT restarts.

   If the Padding
   chunk, to guard against near end receives a false positive response in case the probe valid packet is truncated.

3.5.5.  Close

   An endpoint may close a 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 any time.  Typically the new address before changing DESTADDR.  A
   suggested verification method is described in Section 3.5.4.2.

3.5.4.  Ping

   If an endpoint
   will close receives a session when there have been no open flows Ping chunk (Section 2.3.9) 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) it 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 construct 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 Ping Reply chunk
   (Section 2.3.18), then move to 2.3.10) in response if possible, copying the S_CLOSED
   state.

   On message
   unaltered.  A Ping Reply response SHOULD be sent as quickly as
   possible following receipt of a Session Close Request chunk for Ping.  The semantics of a session in Ping's
   message is reserved for the
   S_OPEN, S_NEARCLOSE, or S_FARCLOSE_LINGER states: send sender; a Session
   Close Acknowledgement chunk; then, if receiver SHOULD NOT interpret
   the session is in Ping's message.

   Endpoints can use the S_OPEN
   state: move to mechanism of the S_FARCLOSE_LINGER state.

   A session that has been in Ping chunk and the S_FARCLOSE_LINGER state expected
   Ping Reply for at least
   19 seconds (allowing time to answer 3 retransmissions any purpose.  This specification doesn't mandate any
   specific constraints on the format or semantics of a Session
   Close Request) SHOULD move to the S_CLOSED state.

   On receipt of a Session Close Acknowledgement chunk for Ping message.  A
   Ping Reply MUST ONLY be sent as a session in
   the S_OPEN, S_NEARCLOSE, or S_FARCLOSE_LINGER states: move response to the
   S_CLOSED state.

3.6.  Flows

   A flow is a unidirectional communication channel in Ping.

   Receipt of a session Ping Reply implies live bidirectional connectivity.
   This specification doesn't mandate any other semantics for
   transporting a correlated series of user messages from a sender Ping
   Reply.

3.5.4.1.  Keepalive

   An endpoint can use Ping to a
   receiver.  Each test for live bidirectional connectivity,
   to test that the far end of a session may have zero or more sending flows is still S_OPEN, to keep NAT
   translations alive, and to keep firewall holes open.

   An endpoint can use Ping to hasten detection by the other end.  Each sending flow at one far end has of a corresponding
   receiving flow at the other end.

3.6.1.  Overview

3.6.1.1.  Identity

   Flows are multiplexed in near
   end address change.

   An endpoint may declare a session by to be defunct and dead after a flow identifier.  Each
   persistent failure by the far end of to return Ping Replies in response
   to Pings.

   If used for these purposes, a session chooses its sending flow identifiers independently of the
   other end.  The choice of similar flow identifiers by both ends does
   not imply Keepalive Ping SHOULD have an association. empty
   message.

   A sender MAY choose any identifier for any
   flow; therefore, a flow receiver MUST Keepalive Ping SHOULD NOT ascribe any semantic
   meaning, role, or name to be sent more often than once per ERTO.
   If a flow based only on its identifier.  There
   are no "well known" or reserved flow identifiers.

   Bidirectional flow association corresponding Ping Reply is indicated with not received within ERTO of sending
   the Return Flow
   Association option Ping, ERTO SHOULD be increased according to Congestion Control
   (Section 2.3.11.1.2).  An endpoint can indicate
   that 3.5.2).

3.5.4.2.  Address Mobility

   This section describes an OPTIONAL but suggested method for
   processing and verifying a new sending flow is 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 return (or response) length
   and known only to a receiving
   flow from the other this 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

   On receipt of the sending flow.

   Flows are named with arbitrary user metadata.  This specification
   doesn't mandate any particular encoding, syntax, or semantics for the
   user metadata except a packet for an S_OPEN session, after processing all
   chunks in the encoded size (Section 2.3.11.1.1); the
   user metadata is entirely reserved for packet: if the application.  The user
   metadata session is fixed for still S_OPEN, AND the lifetime source
   address of the flow.

3.6.1.2.  Messages and Sequencing

   Flows provide message-oriented framing.  Large messages are
   fragmented for transport packet does not match DESTADDR, AND MOB_TX_TS is at
   least one second in the network.  Receivers reassemble
   fragmented messages and only present complete messages past, then:

   1.  Set MOB_TX_TS 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 current time;

   2.  Construct a Ping message comprising: a marking to indicate (to
       this end when they are reordered returned in transit by a Ping Reply) that it is a mobility
       check (for example, the network or as first byte being ASCII 'M' for
       "Mobility"), a result of
   loss timestamp set to MOB_TX_TS, and retransmission.  Flows are a cryptographic
       hash over the basic units of message
   sequencing; each flow is sequenced independently of all other flows;
   inter-flow message arrival preceding as well as the address from which the
       packet was received and delivery sequencing is not guaranteed.

   Independent flow sequencing allows a sender MOB_SECRET; and

   3.  Send this Ping to prioritize the
   transmission or retransmission of address from which the messages packet was received,
       instead of one flow over those DESTADDR.

   On receipt of other flows in a Ping Reply in an S_OPEN session, allocating capacity from if the
   transmission budget according Ping Reply's
   message satisfies all of these conditions:

   o  it has this end's expected marking to priority.  RTMFP indicate it is designed for
   flows to be a mobility
      check, and

   o  the basic unit of prioritization.  In any flow, timestamp in the
   sequence numbers of all fragments of a message MUST be greater is not more than
   the sequence numbers of all fragments of all previously queued
   messages 120 seconds in that flow.  Receipt of fragments within a flow out of
   sequence number order creates discontiguous gaps at the receiver,
   causing it to send an acknowledgement for every packet
      past, and for

   o  the
   size of timestamp in 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, greater than MOB_RX_TS, and retransmit any lost fragments of all
   messages not abandoned, until all the fragments of all messages not
   abandoned are acknowledged by

   o  the receiver.  A sender indicates a
   Forward Sequence Number (FSN) to instruct cryptographic hash matches the receiver that sequence
   numbers less than or equal expected value according to the FSN will not be transmitted or
   retransmitted.  This allows the receiver to move forward over gaps
   and continue sequenced delivery
      contents of completely received messages to the user.  Any incomplete messages missing fragments with sequence
   numbers less than or equal to message plus the FSN were abandoned by source address of the sender packet
      containing this Ping Reply and will never be completed.  A gap indication MUST be communicated MOB_SECRET,

   then:

   1.  Set MOB_RX_TS to the receiving user.

3.6.1.3.  Lifetime

   A sender begins a flow by sending user message fragments to timestamp in the other
   end, message; and including the user metadata and, if any, the return flow
   association.  The sender continues

   2.  Set DESTADDR to include the user metadata and
   return flow association until source address of 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, packet containing this
       Ping Reply.

3.5.4.3.  Path MTU Discovery

   Packetization Layer Path MTU Discovery [RFC4821] describes a method
   for measuring the flow identifier alone is sufficient.

   Flow receivers path MTU between communicating endpoints.

   An RTMFP SHOULD acknowledge all sequence numbers received perform path MTU discovery.

   The method of RFC 4821 can be adapted for
   any flow, whether use in RTMFP by sending a
   probe packet comprising one of the flow is accepted Padding chunk types (type 0x00 or rejected.  Flow receivers
   MUST NOT acknowledge sequence numbers higher than
   0xff) and a Ping.  The Ping chunk SHOULD come after the FSN that were
   not received.  Acknowledgements drive Padding
   chunk, to guard against a false positive response in case the congestion control and
   avoidance algorithms and therefore must be accurate. probe
   packet is truncated.

3.5.5.  Close

   An endpoint can reject may close a receiving flow session at any time in the flow's
   lifetime.  To reject the flow, the receiving time.  Typically an endpoint sends
   will close a Flow
   Exception chunk (Section 2.3.16) immediately preceding every
   acknowledgement chunk session when there have been no open flows in either
   direction for the rejected receiving flow.

   An a time.  In another circumstance, an endpoint may eventually conclude be
   ceasing operation and will 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, its sessions even if they
   have been cumulatively
   acknowledged by open flows.

   To close an S_OPEN session in a reliable and orderly fashion, an
   endpoint moves the receiver.  The receiving flow is complete when
   every sequence number from session to the FSN S_NEARCLOSE state.

   On a session transitioning from S_OPEN to S_NEARCLOSE and every 5
   seconds thereafter while still in the final sequence number S_NEARCLOSE state, send a
   Session Close Request chunk (Section 2.3.17).

   A session that has been received.  The sending flow and corresponding receiving flow in the S_NEARCLOSE state for at least 90
   seconds (allowing time to retransmit the respective ends hold Session Close Request
   multiple times) SHOULD move to the flow identifier of a completed flow in
   reserve for S_CLOSED state.

   On a time session transitioning from S_OPEN to allow delayed the S_NEARCLOSE,
   S_FARCLOSE_LINGER or duplicated fragments S_CLOSED state: immediately abort and
   acknowledgements 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 drain from the network without erroneously
   initiating a new receiving flow or erroneously acknowledging S_CLOSED
   state.

   On receipt of a new
   sending flow.

   If Session Close Request chunk for a flow sender receives session in the
   S_OPEN, S_NEARCLOSE, or S_FARCLOSE_LINGER states: send a Flow Exception indication from Session
   Close Acknowledgement chunk; then, if the other
   end, session is in the flow sender SHOULD close S_OPEN
   state: move to the flow and abandon all of S_FARCLOSE_LINGER state.

   A session that has been in the
   undelivered queued messages.  The flow sender S_FARCLOSE_LINGER state for at least
   19 seconds (allowing time to answer 3 retransmissions of a Session
   Close Request) SHOULD indicate an
   exception move to the user.

3.6.2.  Sender

   Each sending flow comprises S_CLOSED state.

   On receipt of a Session Close Acknowledgement chunk for a session in
   the flow-specific information context
   necessary S_OPEN, S_NEARCLOSE, or S_FARCLOSE_LINGER states: move to transfer that flow's 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 context includes at least:

   o  F_FLOW_ID: this flow's identifier;

   o  STARTUP_OPTIONS: one end has a corresponding
   receiving flow at the set 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 options to send to 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 until
      this 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 acknowledged, including the User's Per-Flow Metadata
      and, if set, indicated with the Return Flow Association;

   o  SEND_QUEUE: the unacknowledged message fragments queued in this
      flow, initially empty; each message fragment entry comprising:

      *  SEQUENCE_NUMBER: the sequence number of this fragment;

      *  DATA: this fragment's user data;

      *  FRA: the fragment control value for this message fragment,
         having one of the values enumerated for
   Association option (Section 2.3.11.1.2).  An endpoint can indicate
   that purpose a new sending flow is in User
         Data (Section 2.3.11);

      *  ABANDONED: a boolean flag indicating whether this fragment has
         been abandoned;

      *  SENT_ABANDONED: a boolean flag indicating whether this fragment
         was abandoned when sent;

      *  EVER_SENT: a boolean flag indicating whether this fragment has
         been sent at least once, initially false;

      *  NAK_COUNT: return (or response) to a count of 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 negative acknowledgements
         detected for this fragment, initially 0;

      *  IN_FLIGHT: a boolean flag indicating whether this fragment sending flows.  The return flow
   association, if any, is
         currently in flight in the network, initially false;

      *  TRANSMIT_SIZE: fixed for the size, in bytes, lifetime of the encoded User Data
         chunk (including the chunk header) sending flow.

   Flows are named with arbitrary user metadata.  This specification
   doesn't mandate any particular encoding, syntax, or semantics for this fragment when it
         was transmitted into the network.

   o  F_OUTSTANDING_BYTES:
   user metadata except for the sum of encoded size (Section 2.3.11.1.1); the TRANSMIT_SIZE of each entry in
      SEND_QUEUE where entry.IN_FLIGHT
   user metadata is true;

   o  RX_BUFFER_SIZE: entirely reserved for the most recent available buffer advertisement
      from application.  The user
   metadata is fixed for the other end (Section 2.3.13, Section 2.3.14), initially
      65536 bytes;

   o  NEXT_SN: lifetime of the next sequence number to assign to a message fragment,
      initially 1;

   o  F_FINAL_SN: flow.

3.6.1.2.  Messages and Sequencing

   Flows provide message-oriented framing.  Large messages are
   fragmented for transport in the sequence number assigned network.  Receivers reassemble
   fragmented messages and only present complete messages to the final message
      fragment of the flow, initially having no value;

   o  EXCEPTION: user.

   A sender queues messages on a boolean flag indicating whether an exception has been
      reported by the receiver, initially false;

   o  The state, at any time being sending flow one of after another.  A
   receiver can recover the following values: original queuing order of the open
      state F_OPEN; messages, even
   when they are reordered in transit by the closing states F_CLOSING and F_COMPLETE_LINGER; network or as a result of
   loss and retransmission.  Flows are the closed state F_CLOSED.

    Note: this diagram basic units of message
   sequencing; each flow is only a summary sequenced independently of state transitions and their
     causing events, all other flows;
   inter-flow message arrival and delivery sequencing 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 17: Sending guaranteed.

   Independent flow state diagram

3.6.2.1.  Startup

   The application opens sequencing allows a new sending flow sender to prioritize the
   transmission or retransmission of the messages of one flow over those
   of other end flows in an
   S_OPEN session.  The implementation chooses a new flow ID that session, allocating capacity from the
   transmission budget according to priority.  RTMFP is not
   assigned designed for
   flows to be the basic unit of prioritization.  In any other sending flow flow, the
   sequence numbers of all fragments of a message MUST be greater than
   the sequence numbers of all fragments of all previously queued
   messages in that session in the F_OPEN,
   F_CLOSING, or F_COMPLETE_LINGER states.  The flow.  Receipt of fragments within a flow starts in out of
   sequence number order creates discontiguous gaps at the
   F_OPEN state.  The STARTUP_OPTIONS receiver,
   causing it to send an acknowledgement for every packet and for the new flow is set with
   size of the
   User's Per-Flow Metadata (Section 2.3.11.1.1).  If this flow is in
   return (or response) encoded acknowledgements to an RF_OPEN receiving flow from grow.  Therefore, for any
   flow, the other end,
   that flow's ID is encoded in sender SHOULD send lower sequence numbers first.

   A sender can abandon a Return Flow Association
   (Section 2.3.11.1.2) option and added 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 STARTUP_OPTIONS.

   At this point detect a gap in the flow exists in when a message is
   abandoned; therefore, each message SHOULD take at least one sequence
   number from the sender, but 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 receiver.
   The flow begins when user data fragments of all messages not
   abandoned are transmitted to acknowledged by the receiver.  A sender can begin a flow in the absence of immediate user
   data by sending indicates a
   Forward Sequence Number Update (Section 3.6.2.7.1),
   by queuing and transmitting a user data fragment (FSN) to instruct the receiver that is already
   abandoned.

3.6.2.2.  Queuing Data

   The application queues messages in an F_OPEN sending flow for
   transmission sequence
   numbers less than or equal to the far end.  The implementation divides each message
   into one FSN will not be transmitted 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
   retransmitted.  This allows the Path MTU
   (Section 3.5.4.3).

   For each fragment, create a fragment entry and set
   fragmentEntry.SEQUENCE_NUMBER receiver to flow.NEXT_SN, move forward over gaps
   and increment
   flow.NEXT_SN by one.  Set fragmentEntry.FRA according continue sequenced delivery of completely received messages 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 user.  Any incomplete messages missing fragments with sequence
   numbers less than or equal to the last of a multi-fragment message.

   3 :  This fragment is in FSN were abandoned by the middle of a multi-fragment message.

   Append fragmentEntry sender
   and will never be completed.  A gap indication MUST be communicated
   to flow.SEND_QUEUE.

3.6.2.3.  Sending Data the receiving user.

3.6.1.3.  Lifetime

   A sending sender begins a flow is ready by sending user message fragments to transmit if the SEND_QUEUE contains at
   least one entry that is eligible to send other
   end, and including the user metadata 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 any, the following conditions holds:

   o  The entry is not ABANDONED; or
   o return flow
   association.  The entry is sender continues to include the first one in user metadata and
   return flow association until the SEND_QUEUE; or

   o  The entry's SEQUENCE_NUMBER flow is equal to flow.F_FINAL_SN.

   If acknowledged by the session's transmission budget allows, a 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 ready to
   transmit is selected sufficient.

   Flow receivers SHOULD acknowledge all sequence numbers received for transmission according to
   any flow, whether the
   implementation's prioritization scheme.  The manner of flow
   prioritization is not mandated by this specification.

   Trim abandoned messages from accepted or rejected.  Flow receivers
   MUST NOT acknowledge sequence numbers higher than the front of FSN that were
   not received.  Acknowledgements drive the queue congestion control and find
   avoidance algorithms and therefore must be accurate.

   An endpoint can reject a receiving flow at any time in the
   Forward Sequence Number FSN:

   1.  While flow's
   lifetime.  To reject the SEND_QUEUE contains at least two entries, AND flow, the first
       entry is not IN_FLIGHT, AND receiving endpoint sends a Flow
   Exception chunk (Section 2.3.16) immediately preceding every
   acknowledgement chunk for the first entry is ABANDONED: remove rejected receiving flow.

   An endpoint may eventually conclude and discard the first entry from SEND_QUEUE;

   2.  If close a sending flow.  The
   last sequence number of the first entry in flow is marked with the SEND_QUEUE Final flag.  The
   sending flow is not abandoned: set FSN to
       entry.SEQUENCE_NUMBER - 1; otherwise

   3.  If complete when all sequence numbers of the first entry in flow,
   including the SEND_QUEUE is IN_FLIGHT AND
       entry.SENT_ABANDONED final sequence number, have been cumulatively
   acknowledged by the receiver.  The receiving flow is false: set complete when
   every sequence number from the FSN to entry.SEQUENCE_NUMBER -
       1; otherwise

   4.  The first entry in the SEND_QUEUE is abandoned and is either not
       IN_FLIGHT or was already abandoned when sent: set FSN to
       entry.SEQUENCE_NUMBER.

   The FSN MUST NOT be greater than any final sequence number currently in
   flight. has
   been received.  The FSN MUST NOT be equal to any sequence number currently sending flow and corresponding receiving flow at
   the respective ends hold the flow identifier of a completed flow in flight that was not abandoned when sent.

   Assemble user data chunks
   reserve for this flow into a packet time to send allow delayed or duplicated fragments and
   acknowledgements to drain from the
   receiver.  While enough space remains in 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 packet and other
   end, the flow is
   ready to transmit:

   1.   Starting at sender SHOULD close the head flow and abandon all of the SEND_QUEUE, find
   undelivered queued messages.  The flow sender SHOULD indicate an
   exception to the first eligible
        fragment entry;

   2.   Encode entry into a User Data chunk (Section 2.3.11) or, if
        possible (Section 3.6.2.3.2), a Next User Data chunk
        (Section 2.3.12);

   3.   If present, set chunk.flowID user.

3.6.2.  Sender

   Each sending flow comprises the flow-specific information context
   necessary to flow.F_FLOW_ID;

   4.   If present, set chunk.sequenceNumber transfer that flow's messages to entry.SEQUENCE_NUMBER;

   5.   If present, the other end.  Each
   sending flow context includes at least:

   o  F_FLOW_ID: this flow's identifier;

   o  STARTUP_OPTIONS: the set chunk.fsnOffset to entry.SEQUENCE_NUMBER - FSN;
   6.   Set chunk.fragmentControl of options to entry.FRA;

   7.   Set chunk.abandon send 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 receiver until
      this flow 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 acknowledged, including the
        packet to exceed User's Per-Flow Metadata
      and, if set, the path MTU: do not assemble this chunk into Return Flow Association;

   o  SEND_QUEUE: the packet, enough space no longer remains unacknowledged message fragments queued in this
      flow, initially empty; each message fragment entry comprising:

      *  SEQUENCE_NUMBER: 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 sequence number of the assembled chunk,
        including the chunk header;

   17.  Assemble this chunk into the packet; and

   18.  If fragment;

      *  DATA: 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 fragment's user data;

      *  FRA: the FIRST User
   Data chunk fragment control value for this flow into a packet, add message fragment,
         having one of the encoded
   STARTUP_OPTIONS to values enumerated for that chunk's option list.

3.6.2.3.2.  Send Next Data

   The Next purpose in User
         Data chunk (Section 2.3.12) is a compact encoding for 2.3.11);

      *  ABANDONED: a
   user message fragment when multiple contiguous fragments are
   assembled into one packet.

   If, after assembling a user message boolean flag indicating whether this fragment of has
         been abandoned;

      *  SENT_ABANDONED: a flow into boolean flag indicating whether this fragment
         was abandoned when sent;

      *  EVER_SENT: a packet
   (Section 3.6.2.3), the next eligible boolean flag indicating whether this fragment to be selected for
   assembly belongs to the same flow AND its sequence number is one
   greater than that has
         been sent at least once, initially false;

      *  NAK_COUNT: a count of the fragment just assembled, an implementation
   SHOULD encode a Next User Data chunk instead number of negative acknowledgements
         detected for this fragment, initially 0;

      *  IN_FLIGHT: a User Data chunk.

   The FIRST boolean flag indicating whether this fragment is
         currently in flight in the network, initially false;

      *  TRANSMIT_SIZE: the size, in bytes, of a flow assembled into a packet MUST be the 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 (including the chunk (Section 2.3.14) encodes header) for this fragment when it
         was transmitted into the
   acknowledgement of receipt of one or more sequence numbers network.

   o  F_OUTSTANDING_BYTES: the sum of a flow,
   as well as the receiver's current receive window advertisement.

   On receipt TRANSMIT_SIZE 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;

   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
      SEND_QUEUE where entry.IN_FLIGHT is true, then: remove entry from flow.SEND_QUEUE; and

   5.  Notify true;

   o  RX_BUFFER_SIZE: 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 most recent available buffer advertisement
      from the session information context contain additional variables: other end (Section 2.3.13, Section 2.3.14), initially
      65536 bytes;

   o  NEXT_TSN:  NEXT_SN: the next TSN sequence number to assign to record with a fragment's queue entry
      when it is transmitted, message fragment,
      initially 1;

   o  MAX_TSN_ACK:  F_FINAL_SN: the highest acknowledged TSN, initially 0.

   Let each fragment queue entry contain an additional variable TSN,
   initially 0, sequence number assigned to track its transmission order.

   On transmission of a the final 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 the flow, initially having no value;

   o  EXCEPTION: a packet containing boolean flag indicating whether an exception has been
      reported by the receiver, initially false;

   o  The state, at least any time being 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 of the following values: the open
      state F_OPEN; the closing states F_CLOSING and
   entry.TSN is less than session.MAX_TSN_ACK: increment entry.NAK_COUNT F_COMPLETE_LINGER;
      and notify the congestion control closed state F_CLOSED.

    Note: this diagram is only a summary of state transitions and avoidance algorithms that their
     causing events, and is not a
   negative acknowledgement was detected in this packet.

   For each 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 18: Sending flow state diagram

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 session, for each entry in that flow's
   SEND_QUEUE, if entry.IN_FLIGHT is true and entry.NAK_COUNT is at
   least 3, not
   assigned to any other sending flow in that fragment was lost session in the network and 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 no longer in
   flight.  Set entry.IN_FLIGHT
   return (or response) to false.  Notify the congestion control
   and avoidance algorithms of an RF_OPEN receiving flow from the loss.

3.6.2.6.  Timeout

   A fragment other end,
   that flow's ID is considered lost and no longer encoded in flight a Return Flow Association
   (Section 2.3.11.1.2) option and added to STARTUP_OPTIONS.

   At this point the flow exists 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 that sender, but not the implementation's
   congestion control and avoidance algorithms will eventually stop
   sending new receiver.
   The flow begins when user data 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 transmitted to fire in ERTO.

   On receiving the
   receiver.  A sender can begin a packet containing at least one acknowledgement, reset
   TIMEOUT_ALARM (if already set) to fire in ERTO.

   When TIMEOUT_ALARM fires:

   1.  Set ANY_LOSS = false;

   2.  For each sending flow in the session, and for each entry in that
       flow's SEND_QUEUE:

       1.  If entry.IN_FLIGHT is true: set ANY_LOSS = true; and

       2.  Set entry.IN_FLIGHT to false.

   3.  If ANY_LOSS is true: perform ERTO backoff absence of immediate user
   data by sending a Forward Sequence Number Update (Section 3.5.2.2); and

   4.  Notify the congestion control 3.6.2.7.1),
   by queuing and avoidance algorithms of the
       timeout and, if ANY_LOSS is true, transmitting a user data fragment that there was loss.

3.6.2.7.  Abandoning is already
   abandoned.

3.6.2.2.  Queuing Data

   The application can abandon queued queues messages at any time and in an F_OPEN sending flow for any
   reason.  Example reasons include (but are not limited to):
   transmission to the far end.  The implementation divides each message
   into 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 transmission in User Data chunks
   (Section 2.3.11).  Each fragment MUST be small enough so that, if
   assembled into a specified retransmission limit; Packet (Section 2.2.4) with a prior
   message on which maximum-size common
   header, User Data chunk header, and, if not empty, this message depends (such as a key frame in a
   prediction chain) was abandoned and flow's
   STARTUP_OPTIONS, the Packet will not delivered.

   To abandon a message exceed the Path MTU
   (Section 3.5.4.3).

   For each fragment, create a fragment entry and set its SEND_QUEUE entry's ABANDON
   flag
   fragmentEntry.SEQUENCE_NUMBER to true.  When abandoning 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 message fragment, abandon all
   fragments complete message.

   1 :  This fragment is the first of a multi-fragment message.

   2 :  This fragment is the message to which it belongs.

   An abandoned last of a multi-fragment message.

   3 :  This fragment MUST NOT be un-abandoned.

3.6.2.7.1.  Forward Sequence Number Update

   Abandoned data may leave gaps is in the sequence number space middle of a flow.
   Gaps may cause the receiver to hold completely received messages for
   ordered delivery multi-fragment message.

   Append fragmentEntry to allow for retransmission of the missing
   fragments.  User flow.SEND_QUEUE.

3.6.2.3.  Sending Data chunks (Section 2.3.11) encode a Forward
   Sequence Number (FSN)

   A sending flow is ready to instruct transmit if the receiver SEND_QUEUE contains at
   least one entry that sequence numbers
   less is eligible to send and if either RX_BUFFER_SIZE
   is greater than F_OUTSTANDING_BYTES or equal EXCEPTION is set to the FSN will true.

   A SEND_QUEUE entry is eligible to send if it is not be transmitted or
   retransmitted.

   When IN_FLIGHT AND at
   least one of the receiver has gaps in following conditions holds:

   o  The entry is not ABANDONED; or

   o  The entry is the received sequence number space and
   no non-abandoned message fragments remain first one in the SEND_QUEUE, SEND_QUEUE; or

   o  The entry's SEQUENCE_NUMBER is equal to flow.F_FINAL_SN.

   If the
   sender SHOULD transmit 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 Update (FSN Update)
   comprising a User Data chunk marked abandoned, whose sequence number FSN:

   1.  While the SEND_QUEUE contains at least two entries, AND the first
       entry is not IN_FLIGHT, AND the FSN first entry is ABANDONED: remove
       and whose fsnOffset discard the first entry from SEND_QUEUE;

   2.  If the first entry in the SEND_QUEUE is 0.  An not abandoned: set FSN Update allows to
       entry.SEQUENCE_NUMBER - 1; otherwise

   3.  If the
   receiver first entry in the SEND_QUEUE is IN_FLIGHT AND
       entry.SENT_ABANDONED is false: set FSN to skip gaps that will not be repaired entry.SEQUENCE_NUMBER -
       1; otherwise

   4.  The first entry in the SEND_QUEUE is abandoned and deliver received
   messages is either not
       IN_FLIGHT or was already abandoned when sent: set FSN to the user.  An
       entry.SEQUENCE_NUMBER.

   The FSN Update may MUST NOT be thought of as a
   transmission or retransmission of abandoned greater than any sequence numbers without
   actually sending the data.

   The method described number currently in Sending Data (Section 3.6.2.3) generates
   flight.  The FSN
   Updates when appropriate.

3.6.2.8.  Examples

    Sender MUST NOT be equal to any sequence number currently
   in flight that was not abandoned when sent.

   Assemble user data chunks for this flow into a packet to send to the
   receiver.  While enough space remains in the packet and the flow is
   ready to transmit:

   1.   Starting at the head of the SEND_QUEUE, find the first eligible
        fragment entry;

   2.   Encode entry into a User Data chunk (Section 2.3.11) or, if
        possible (Section 3.6.2.3.2), a Next User Data chunk
        (Section 2.3.12);

   3.   If present, set chunk.flowID to flow.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;

   17.  Assemble this chunk into the packet; and

   18.  If this flow or entry is considered Time Critical (real-time),
        set the timeCritical flag in the packet header (Section 2.2.4).

   Complete any other appropriate packet processing, and transmit the
   packet to the far end.

3.6.2.3.1.  Startup Options

   If STARTUP_OPTIONS is not empty, then when assembling the FIRST User
   Data chunk for this flow into a packet, add the encoded
   STARTUP_OPTIONS to that chunk's option list.

3.6.2.3.2.  Send Next Data

   The Next User Data chunk (Section 2.3.12) is a compact encoding for a
   user message fragment when multiple contiguous fragments are
   assembled into one packet.

   If, after assembling a user message fragment of a flow into a packet
   (Section 3.6.2.3), the next eligible fragment to be selected for
   assembly belongs to the same flow AND its sequence number is one
   greater than that of the fragment just assembled, an implementation
   SHOULD encode a Next User Data chunk instead of a User Data chunk.

   The FIRST fragment of a flow assembled into a packet MUST be encoded
   as a User Data chunk.

3.6.2.4.  Processing Acknowledgements

   A Data Acknowledgement Bitmap chunk (Section 2.3.13) or a Data
   Acknowledgement Ranges chunk (Section 2.3.14) encodes the
   acknowledgement of receipt of one or more sequence numbers of a flow,
   as well as the receiver's current receive window advertisement.

   On receipt of an acknowledgement chunk for a sending flow:

   1.  Set PRE_ACK_OUTSTANDING_BYTES to flow.F_OUTSTANDING_BYTES;

   2.  Set flow.STARTUP_OPTIONS to empty;

   3.  Set flow.RX_BUFFER_SIZE to chunk.bufferBytesAvailable;

   4.  For each sequence number encoded in the acknowledgement: if there
       is an entry in flow.SEND_QUEUE with that sequence number and its
       IN_FLIGHT is true, then: remove entry from flow.SEND_QUEUE; and

   5.  Notify the congestion control and avoidance algorithms that
       PRE_ACK_OUTSTANDING_BYTES - flow.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
   entry.TSN is less than session.MAX_TSN_ACK: increment entry.NAK_COUNT
   and notify the congestion control and avoidance algorithms that a
   negative acknowledgement was detected in this packet.

   For each sending flow in that session, for each entry in that flow's
   SEND_QUEUE, if entry.IN_FLIGHT is true and entry.NAK_COUNT is at
   least 3, that fragment was lost in the network and is no longer in
   flight.  Set entry.IN_FLIGHT to false.  Notify the congestion control
   and avoidance algorithms of the loss.

3.6.2.6.  Timeout

   A fragment is considered lost and no longer in flight in the network
   if it has remained outstanding for at least ERTO.

   The following describes an OPTIONAL method to manage transmission
   timeouts.  This method REQUIRES that either Burst Avoidance
   (Section 3.5.2.3) is implemented, or that the implementation's
   congestion control and avoidance algorithms will eventually stop
   sending new fragments into the network if acknowledgements are
   persistently not received.

   Let the session information context contain an alarm TIMEOUT_ALARM,
   initially unset.

   On sending a packet containing at least one User Data chunk, set or
   reset TIMEOUT_ALARM to fire in ERTO.

   On receiving a packet containing at least one acknowledgement, reset
   TIMEOUT_ALARM (if already set) to fire in ERTO.

   When TIMEOUT_ALARM fires:

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

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): one or
   more fragments of a message have remained in the SEND_QUEUE for
   longer than a specified message lifetime; a fragment has been
   retransmitted more than a specified retransmission limit; a prior
   message on which this message depends (such as a key frame in a
   prediction chain) was abandoned and not delivered.

   To abandon a message fragment, set its SEND_QUEUE entry's ABANDON
   flag to true.  When abandoning a message fragment, abandon all
   fragments of the message to which it belongs.

   An abandoned fragment MUST NOT be un-abandoned.

3.6.2.7.1.  Forward Sequence Number Update

   Abandoned data may leave gaps in the sequence number space of a flow.
   Gaps may cause the receiver to hold completely received messages for
   ordered delivery to allow for retransmission of the missing
   fragments.  User Data chunks (Section 2.3.11) encode a Forward
   Sequence Number (FSN) to instruct the receiver that sequence numbers
   less than or equal to the FSN will not be transmitted or
   retransmitted.

   When the receiver has gaps in the received sequence number space and
   no non-abandoned message fragments remain in the SEND_QUEUE, the
   sender SHOULD transmit a Forward Sequence Number Update (FSN Update)
   comprising a User Data chunk marked abandoned, whose sequence number
   is the FSN and whose fsnOffset is 0.  An FSN Update allows the
   receiver to skip gaps that will not be repaired and deliver received
   messages to the user.  An FSN Update may be thought of as a
   transmission or retransmission of abandoned sequence numbers without
   actually sending the data.

   The method described in Sending Data (Section 3.6.2.3) generates FSN
   Updates when appropriate.

3.6.2.8.  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 18: 19: Normal flow with no loss

    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, in transit, and a
   pause at 64. 33 is retransmitted, 31 and 60 are abandoned.  Note line
   25 is a Forward Sequence Number Update (Section 3.6.2.7.1).

                         Figure 20: Flow with loss

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 (Section 2.3.13, Section 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
   pause probe within one second.

   The initial period between Buffer Probes SHOULD be at 64. 33 least one
   second or ERTO, whichever is retransmitted, 31 and 60 are abandoned.  Note line
   25 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 Forward Sequence Number Update Flow Exception Report (Section 3.6.2.7.1).

                         Figure 19: 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 loss

3.6.2.9.  Flow Control

   The the
       encoded exception code;

   2.  Set the EXCEPTION flag to true; and

   3.  For each entry in SEND_QUEUE: set entry.ABANDONED = true.

3.6.2.11.  Close

   A sending flow receiver advertises is closed by the amount user or as a result of new data it's willing an exception.
   To close an F_OPEN flow:

   1.  Move to
   accept from the flow sender with F_CLOSING state;

   2.  If the SEND_QUEUE is not empty, AND the tail entry of the bufferBytesAvailable derived
   field
       SEND_QUEUE has a sequence number of an acknowledgement (Section 2.3.13, Section 2.3.14).

   The flow sender MUST NOT send new data into NEXT_SN - 1, AND the network if
   flow.F_OUTSTANDING_BYTES tail
       entry.EVER_SENT is greater than or equal false: set F_FINAL_SN to the most
   recently received buffer advertisement, unless flow.EXCEPTION is true
   (Section 3.6.2.3).

3.6.2.9.1.  Buffer Probe
       entry.SEQUENCE_NUMBER; else

   3.  The flow sender SEND_QUEUE is suspended if empty, OR the most recently received buffer
   advertisement tail entry does not have a
       sequence number of NEXT_SN - 1, OR the tail entry.EVER_SENT is zero
       true: enqueue a new SEND_QUEUE entry with entry.SEQUENCE_NUMBER =
       flow.NEXT_SN, entry.FRA = 0, and the entry.ABANDONED = true, and set
       flow.F_FINAL_SN to entry.SEQUENCE_NUMBER.

   An F_CLOSING sending 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 complete when its SEND_QUEUE transitions
   to empty, indicating that might
   reopen all sequence numbers including 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 FINAL_SN
   have been acknowledged by the receive window advertisement transitions from non-zero other end.

   When an F_CLOSING sending flow becomes complete, move to
   zero, the
   F_COMPLETE_LINGER state.

   A sending flow sender MAY send a Buffer Probe immediately and SHOULD
   send a probe within one second.

   The initial period between Buffer Probes SHOULD be MUST remain in the F_COMPLETE_LINGER state for at
   least one
   second or ERTO, whichever is greater.  The period between probes
   SHOULD increase over time, but 130 seconds.  After at least 130 seconds, move to the period between probes SHOULD NOT
   be more than one minute or ERTO, whichever is greater. F_CLOSED
   state.  The flow sender SHOULD stop sending Buffer Probes if it is no longer
   suspended.

3.6.2.10.  Exception

   The flow receiver is now closed, its resources can reject the flow at any time be
   reclaimed, and its F_FLOW_ID MAY be used for any reason.
   The flow receiver sends a Flow Exception Report (Section 2.3.16) when
   it has rejected a new sending flow.

   On

3.6.3.  Receiver

   Each receiving a Flow Exception Report for a flow comprises the flow-specific information context
   necessary to receive that flow's messages from the sending flow:

   1.  If end and
   deliver completed messages to the user.  Each receiving flow is F_OPEN, close context
   includes at least:

   o  RF_FLOW_ID: this flow's identifier;

   o  SEQUENCE_SET: the flow (Section 3.6.2.11) and
       notify set of all sequence numbers seen in this
      receiving flow, whether received or abandoned, initially empty;

   o  RF_FINAL_SN: the final sequence number of the flow, initially
      having no value;

   o  RECV_BUFFER: the message fragments waiting to be delivered to the
      user, sorted by sequence number in ascending order, initially
      empty; each message fragment entry comprising:

      *  SEQUENCE_NUMBER: the sequence number of this fragment;

      *  DATA: this fragment's user data; and
      *  FRA: the fragment control value for this message fragment,
         having one of the values enumerated for that purpose in User
         Data (Section 2.3.11).

   o  BUFFERED_SIZE: the far end reported an exception with sum of the
       encoded exception code;

   2.  Set 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 EXCEPTION flag to true; and

   3.  For each entry receive buffer,
      in SEND_QUEUE: set entry.ABANDONED = true.

3.6.2.11.  Close

   A sending flow is closed by bytes;

   o  PREV_RWND: the user or as a result of most recent receive window advertisement sent in an exception.
   To close
      acknowledgement, in 1024-byte blocks, initially having no value;

   o  SHOULD_ACK: whether or not an F_OPEN flow:

   1.  Move to the F_CLOSING state;

   2.  If acknowledgement should be sent for
      this flow, initially false;

   o  EXCEPTION_CODE: the SEND_QUEUE is not empty, AND exception code to report to the tail entry of sender when
      the
       SEND_QUEUE flow has a sequence number been rejected, initially 0;

   o  The state, at any time being one 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 following values: the tail entry does not have a
       sequence number of NEXT_SN - 1, OR open
      state RF_OPEN; the tail entry.EVER_SENT closing states RF_REJECTED and
      RF_COMPLETE_LINGER; and the closed state RF_CLOSED.

    Note: this diagram is
       true: enqueue only a new SEND_QUEUE entry with entry.SEQUENCE_NUMBER =
       flow.NEXT_SN, entry.FRA = 0, summary of state transitions and entry.ABANDONED = true, their
     causing events, and set
       flow.F_FINAL_SN to entry.SEQUENCE_NUMBER.

   An F_CLOSING sending flow is not a complete when its SEND_QUEUE transitions
   to empty, indicating that 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 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
                                 |       |  0..RF_FINAL_SN
                                 v       v
                            +------------------+
                            |RF_COMPLETE_LINGER|
                            +------------------+
                                     | 120 seconds
                                     v
                                +---------+
                                |RF_CLOSED|
                                +---------+

                  Figure 21: Receiving 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 diagram

3.6.3.1.  Startup

   A new receiving flow is now closed, its resources can be
   reclaimed, and its F_FLOW_ID MAY be used for starts on receipt of a new sending flow.

3.6.3.  Receiver

   Each User Data chunk
   (Section 2.3.11) encoding a flow ID not belonging to any other
   receiving flow comprises in the flow-specific information context
   necessary to receive that flow's messages from same session in the sending end 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
   deliver completed messages
        ASSOCIATION to the user.  Each each have no value;

   2.   Create a new receiving flow context
   includes at least:

   o  RF_FLOW_ID: this flow's identifier;

   o  SEQUENCE_SET: the set of all sequence numbers seen in this
      receiving flow, whether received or abandoned, initially empty;

   o  RF_FINAL_SN: the final sequence number of the flow, initially
      having no value;

   o  RECV_BUFFER: the message fragments waiting to be delivered session, setting its
        RF_FLOW_ID to the
      user, sorted by sequence number flow ID encoded in ascending order, initially
      empty; each message fragment entry comprising:

      *  SEQUENCE_NUMBER: the sequence number of this fragment;

      *  DATA: this fragment's user data; opening User Data
        chunk, and
      *  FRA: set to the RF_OPEN state;

   3.   If the fragment control value for this message fragment,
         having one of 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 values enumerated for that purpose in opening User Data chunk encodes a Return Flow Association
        option (Section 2.3.11).

   o  BUFFERED_SIZE: 2.3.11.1.2), set ASSOCIATED_FLOWID to
        option.flowID;

   5.   If METADATA has no value, the sum of receiver MUST reject the lengths of each fragment 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
      RECV_BUFFER plus any additional storage overhead for the fragments
      incurred by same session with a flow ID of ASSOCIATED_FLOWID,
        the implementation, in bytes;

   o  BUFFER_CAPACITY: receiver MUST reject the desired maximum size for flow, moving it to the receive buffer,
      in bytes;

   o  PREV_RWND: RF_REJECTED
        state; otherwise set ASSOCIATION to the most recent receive window advertisement sent in an
      acknowledgement, in 1024-byte blocks, initially having no value;

   o  SHOULD_ACK: whether or indicated sending flow;

   7.   If ASSOCIATION indicates a sending flow AND that sending flow's
        state is not an acknowledgement should be sent for F_OPEN, the receiver MUST reject this receiving
        flow, initially false;

   o  EXCEPTION_CODE: the exception code to report moving it to the sender when RF_REJECTED state;

   8.   If the flow has been rejected, initially 0;

   o  The state, at opening User Data chunk encodes any time being one of unrecognized option
        with a type code less than 8192 (Section 2.3.11.1), the following values: receiver
        MUST reject the open
      state RF_OPEN; flow, moving it to the closing states RF_REJECTED and
      RF_COMPLETE_LINGER; and the closed state RF_CLOSED.

    Note: state;

   9.   If this diagram new receiving flow is only still RF_OPEN, then: notify the
        user that a summary of state transitions and their
     causing events, new receiving flow has opened, including the
        METADATA and, if present, the ASSOCIATION, and is not a complete operational specification.

                                      +-+
                                      |X|
                                      +-+
                                       |rcv set
        flow.BUFFER_CAPACITY according to the user;

   10.  Perform the normal data processing (Section 3.6.3.2) for the
        opening 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 20: chunk; and

   11.  Set this session's ACK_NOW to true.

3.6.3.2.  Receiving flow state diagram

3.6.3.1.  Startup Data

   A new receiving flow starts on receipt of a User Data chunk (Section 2.3.11) encoding or a flow ID not belonging to any other 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 states.

   On receipt of such a User Data chunk:

   1.   Set temporary variables METADATA, ASSOCIATED_FLOWID, and
        ASSOCIATION state, perform the steps at Startup
        (Section 3.6.3.1) to each have no value;

   2.   Create start a new receiving flow context in this session, setting its
        RF_FLOW_ID to flow;

   2.   Retrieve the receiving flow ID encoded in the opening User Data
        chunk, and set to context for the RF_OPEN state; flow indicated by
        chunk.flowID;

   3.   If the opening User Data chunk encodes a User's Per-Flow
        Metadata option (Section 2.3.11.1.1), set METADATA   Set flow.SHOULD_ACK to
        option.userMetadata; true;

   4.   If the opening User Data flow is RF_OPEN AND the chunk encodes a Return Flow Association any unrecognized
        option with a type code less than 8192 (Section 2.3.11.1.2), set ASSOCIATED_FLOWID to
        option.flowID;

   5.   If METADATA has no value, 2.3.11.1), the receiver
        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 ASSOCIATED_FLOWID flow.PREV_RWND has a value, then 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 there 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 sending value, then:
        set flow.RF_FINAL_SN to chunk.sequenceNumber, and set
        session.ACK_NOW to true;

   11.  If the flow is in the same session with RF_OPEN state, AND flow.SEQUENCE_SET
        doesn't contain chunk.sequenceNumber, AND chunk.abandon is
        false, then: create a flow ID of ASSOCIATED_FLOWID, 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 receiver MUST reject range of sequence numbers from 0
        through and including the flow, moving it chunk.forwardSequenceNumber derived
        field;

   13.  Add chunk.sequenceNumber to the RF_REJECTED
        state; otherwise flow.SEQUENCE_SET;

   14.  If flow.SEQUENCE_SET now has any gaps, set ASSOCIATION session.ACK_NOW to the indicated sending flow;

   7.
        true;

   15.  If ASSOCIATION indicates a sending flow AND that sending flow's
        state session.ACK_NOW is false and session.DELACK_ALARM is not F_OPEN, the receiver MUST reject set:
        set session.DELACK_ALARM to fire in 200 milliseconds; and

   16.  Attempt delivery of completed messages in this receiving
        flow, moving it flow's
        RECV_BUFFER to the RF_REJECTED state;

   8.   If the opening user (Section 3.6.3.3).

   After processing all chunks in a packet containing at least one 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. chunk, increment session.RX_DATA_PACKETS by one.  If this new
   session.RX_DATA_PACKETS is at least two, set session.ACK_NOW to true.

   A receiving flow that is still RF_OPEN, then: notify not in the
        user 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 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 packet that's already sending user data processing or an
   acknowledgement (Section 3.6.3.2) for 3.6.3.4.6), or when 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
   flag is set (Section 2.3.11) or a Next User 3.6.3.4.5).

3.6.3.3.  Buffering and Delivering Data chunk
   (Section 2.3.12) encodes one fragment of

   A receiving flow's information context contains a RECV_BUFFER for
   reordering, reassembling, and holding the user data message messages of a
   flow, as well as the flow's Forward
   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 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 CSN be the same session highest
   number 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 contiguous range of numbers in SEQUENCE_SET starting
   with 0.  For example, if SEQUENCE_SET contains {0, 1, 2, 3, 5, 6},
   the receiving flow context for contiguous range starting with 0 is 0..3, so the flow indicated by
        chunk.flowID; CSN is 3.   Set flow.SHOULD_ACK to true;

   4.   If

   A message is complete if all of its fragments are present in the flow
   RECV_BUFFER.  The fragments of one message have contiguous sequence
   numbers.  A message can either be a single fragment, whose fragment
   control value is RF_OPEN AND 0-whole, or can be two or more fragments where the chunk encodes any unrecognized
        option
   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 type code less than 8192 (Section 2.3.11.1), the
        flow MUST 1-begin nor
   a 2-end.

   Incomplete message segments can either be rejected: notify in progress or abandoned.
   An incomplete segment is abandoned in the user following cases:

   o  The sequence number of an exception, and
        reject the flow (Section 3.6.3.7), moving it segment's first fragment is less than
      or equal to the RF_REJECTED
        state;

   5.   If the flow CSN AND that fragment's control value is not in
      1-begin; or

   o  The sequence number of the RF_OPEN state: set session.ACK_NOW to
        true;

   6.   If flow.PREV_RWND has a value and that value segment's last fragment 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
      the CSN.

   Abandoned message segments will never be completed, so they SHOULD be
   removed from 0 through the RECV_BUFFER to make room in the advertised receive
   window and including the
        highest sequence number 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 set), set session.ACK_NOW
   user resumes delivery.  A suspended flow can cause the receive window
   advertisement to
        true;

   9.   If flow.SEQUENCE_SET contains chunk.sequenceNumber, then go to zero even when the BUFFER_CAPACITY is non-
   zero; this
        chunk is a duplicate: set session.ACK_NOW to true;

   10.  If flow.SEQUENCE_SET doesn't contain chunk.sequenceNumber, AND
        chunk.final described in detail in Flow Control (Section 3.6.3.5).

   When the receiving flow is true, AND flow.RF_FINAL_SN has no value, then:
        set flow.RF_FINAL_SN 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 chunk.sequenceNumber, the CSN.

   The following describes a method for discarding abandoned message
   segments and set
        session.ACK_NOW to true;

   11.  If delivering complete messages in original queueing order
   when the receiving flow is not suspended.

   While the first fragment entry 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 has a sequence
   number less than or equal to chunk.sequenceNumber, CSN and delivery is still possible:

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

   2.  If entry.FRA is 2-end or 3-middle: this entry belongs to
        chunk.fragmentControl, an
       abandoned segment, so remove and insert discard this new entry into
        flow.RECV_BUFFER;

   12.  Add to flow.SEQUENCE_SET from
       RECV_BUFFER; otherwise,

   3.  Entry.FRA is 1-begin.  Let LAST_ENTRY be the range 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 numbers from 0
        through number order and including
           deliver 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 complete message to
        true;

   15. the user, then remove the
           entries for this complete message from RECV_BUFFER;
           otherwise,

       2.  If session.ACK_NOW LAST_ENTRY.SEQUENCE_NUMBER is false less than CSN: this segment
           is incomplete and session.DELACK_ALARM abandoned, so remove and discard the
           entries for this segment from RECV_BUFFER; otherwise,

       3.  LAST_ENTRY.SEQUENCE_NUMBER is not set:
        set session.DELACK_ALARM equal to fire in 200 milliseconds; CSN and

   16.  Attempt delivery of completed messages in LAST_ENTRY.FRA
           is not 2-end: this flow's
        RECV_BUFFER to the user (Section 3.6.3.3).

   After processing all chunks segment is incomplete but still in a packet containing
           progress.  Ordered delivery is no longer possible until at
           least one User
   Data chunk, increment session.RX_DATA_PACKETS by one. more fragment is received.  Stop.

   If
   session.RX_DATA_PACKETS flow.RF_FINAL_SN has a value and is at least two, set session.ACK_NOW equal to true.

   A receiving flow that is not in the RF_CLOSED state CSN, AND RECV_BUFFER
   is ready empty: all complete messages have been delivered 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 the user, so
   notify the user data or an
   acknowledgement (Section 3.6.3.4.6), or when that the session's ACK_NOW
   flag flow is set (Section 3.6.3.4.5).

3.6.3.3.  Buffering and Delivering complete.

3.6.3.4.  Acknowledging Data

   A receiving flow's information context contains a RECV_BUFFER for
   reordering, reassembling, and holding the flow receiver SHOULD acknowledge all 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 sequence numbers
   seen in SEQUENCE_SET starting
   with 0.  For example, if SEQUENCE_SET contains {0, 1, 2, 3, 5, 6}, that flow.  Acknowledgements drive the contiguous range starting with 0 is 0..3, so sender's congestion
   control and avoidance algorithms, clear data from the CSN is 3.

   A message is complete if all of its fragments are present sender's
   buffers, and in some sender implementations clock new data into the
   RECV_BUFFER.  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 of one message have contiguous sequence
   numbers.  A message can either be acknowledged in a
   single fragment, whose fragment
   control value transmission.  However, it is 0-whole, 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 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 addressed if possible.

   Therefore, a last
   fragment with control value 2-end.

   An incomplete message segment is flow receiver SHOULD send an acknowledgement for a contiguous sequence flow
   as soon as is practical in any of the following circumstances:

   o  On receipt of one or more
   fragments that do not form a complete message; User Data chunk 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 starts a 2-end.

   Incomplete message segments can either be in progress new flow;

   o  On receipt of a User Data or abandoned.
   An incomplete segment Next User Data chunk if the flow is abandoned
      not in the following cases: RF_OPEN state;

   o  The sequence number  On receipt of a User Data chunk where, before processing the segment's first fragment is less than
      or equal to
      chunk, the CSN AND that fragment's control value is SEQUENCE_SET of the indicated flow does not
      1-begin; or

   o  The contain
      every 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 between 0 and the RECV_BUFFER to make room highest sequence number in
      the advertised receive
   window and set (that is, if there was a sequence number gap before
      processing the receiver's memory for messages that can be completed.

   The user can suspend delivery chunk);

   o  On receipt 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 User Data chunk where, after processing the BUFFER_CAPACITY is non-
   zero; this is described in detail in Flow Control (Section 3.6.3.5).

   When chunk,
      the receiving flow is flow's SEQUENCE_SET does not suspended, the original queuing order
   of contain every sequence number
      between 0 and the messages is recovered by delivering, in ascending highest sequence number order, complete messages in the RECV_BUFFER whose set (that is, if
      this chunk causes a sequence
   numbers are less than or equal to 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 CSN.

   The following describes flow indicated fewer than two bufferBlocksAvailable;

   o  On receipt of a method User Data or Next User Data chunk for discarding abandoned message
   segments and delivering complete messages in original queueing order
   when the receiving flow is not suspended.

   While if,
      after processing the first fragment entry in chunk, the RECV_BUFFER has 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 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 was already seen (that is, on receipt 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 duplicate);

   o  On the DATA fields of each fragment
           entry first receipt of this segment in ascending the final sequence number order and
           deliver of the complete message to flow;

   o  On receipt of two packets in the user, then remove 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
           entries flow, if an
      acknowledgement for this complete message from RECV_BUFFER;
           otherwise,

       2.  If LAST_ENTRY.SEQUENCE_NUMBER is less than CSN: this segment any other flow is incomplete and abandoned, so remove and discard being sent (that is,
      consolidate acknowledgements);

   o  After receipt of a User Data chunk for the
           entries flow, if any user data
      for this segment from RECV_BUFFER; otherwise,

       3.  LAST_ENTRY.SEQUENCE_NUMBER a sending flow is equal to CSN being sent in a packet and LAST_ENTRY.FRA
           is not 2-end: this segment if there is incomplete but still space
      available in
           progress.  Ordered delivery is no the same packet (that is, attempt to piggyback an
      acknowledgement with user data if possible);

   o  No longer possible until at
           least one more fragment is received.  Stop.

   If flow.RF_FINAL_SN has than 200 milliseconds after receipt of a value User Data chunk
      for the flow.

3.6.3.4.2.  Size and is equal to CSN, AND RECV_BUFFER
   is empty: all complete messages have been delivered to Truncation

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

   o  If the flow packet is being sent primarily to send an acknowledgement
      AND this 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 first acknowledgement 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 packet, truncate the
      acknowledgement so that multiple data fragments can be acknowledged the packet does not exceed the path MTU;
      otherwise

   o  The acknowledgement is being piggybacked in a
   single transmission.  However, it is also advantageous 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 sender
   to receiving
   flow's SEQUENCE_SET and its receive timely notification about window advertisement.  The two
   chunks are semantically equivalent; implementations SHOULD send
   whichever provides the receiver's disposition most compact encoding of the flow, particularly in unusual or exceptional circumstances, so 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 circumstances can be addressed if possible.

   Therefore, 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 SHOULD send can delay sending an acknowledgement for a flow 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 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
   when the flow session's ACK_NOW flag is
      not in set.  When the RF_OPEN state;

   o  On receipt of ACK_NOW flag is
   set:

   1.  Choose a User Data chunk where, before processing the
      chunk, 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 SEQUENCE_SET of DELACK_ALARM, and
       stop; otherwise

   3.  Start a new packet;
   4.  Assemble an acknowledgement for the indicated flow does not contain
      every sequence number between 0 and the highest sequence number include it in the set (that is,
       packet, truncating it if there was a sequence number gap before
      processing necessary so that the chunk);

   o  On receipt packet doesn't
       exceed the path MTU;

   5.  Set flow.SHOULD_ACK to false;

   6.  Set flow.PREV_RWND to the bufferBlocksAvailable field of a User Data chunk where, after processing the chunk,
       included acknowledgement chunk;

   7.  Attempt to piggyback acknowledgements for any other flows that
       are ready to send an acknowledgement into the flow's SEQUENCE_SET does not contain every sequence number
      between 0 packet, as
       described below; and

   8.  Send the highest sequence number 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 set (that is, packet if
      this chunk causes a sequence number gap);

   o  On receipt of possible.

   To piggyback acknowledgements in a Buffer Probe 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;

   o  On receipt of a User Data chunk if

   2.  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 cannot be included in the flow if,
      after processing packet without
       exceeding the chunk, path MTU: the flow's BUFFER_CAPACITY packet 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 full, stop; otherwise

   3.  Include the first receipt acknowledgement in the packet;

   4.  Set flow.SHOULD_ACK to false;

   5.  Set flow.PREV_RWND to the bufferBlocksAvailable field of the final
       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
   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 number of the flow;

   o  On receipt of two packets numbers 31 and 33 lost in the session containing user data transit, 31 abandoned
   and 33 retransmitted.

                                 Figure 22

3.6.3.5.  Flow Control

   The flow receiver maintains a buffer for
      any flows since an acknowledgement was last sent; the new
      acknowledgements being reassembling and reordering
   messages for delivery to the flows having any User Data chunks
      in user (Section 3.6.3.3).  The
   implementation and the received packets (that is, for every second packet
      containing user data);

   o  After receipt may wish to limit the amount of resources
   (including buffer memory) that 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 allowed to use.

   RTMFP provides a User Data chunk means for each receiving flow to govern the flow, if any user amount
   of data
      for a sending flow is being sent in a packet and if there is space
      available in by the same packet (that is, attempt to piggyback an
      acknowledgement with user data if possible);

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

3.6.3.4.2.  Size and Truncation

   Including an encoded 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 packet might 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
   packet receive buffer to exceed the path MTU. fill.

   In that case:

   o  If the packet is being sent primarily order for progress to send 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
      AND this if it is not suspended, even if the first acknowledgement amount of data in
   the packet, truncate the
      acknowledgement so that buffer exceeds the packet does not exceed buffer capacity, unless the path MTU;
      otherwise

   o  The acknowledgement buffer capacity is being piggybacked in a packet with user
      data or with an acknowledgement for another flow: do not include
      this acknowledgement in
   0.  Otherwise, deadlock can occur, as the packet, and send it later.

3.6.3.4.3.  Constructing

   The Data Acknowledgement Bitmap chunk (Section 2.3.13) receive buffer will stay
   full and Data
   Acknowledgement Ranges chunk (Section 2.3.14) encode won't drain because of a receiving
   flow's SEQUENCE_SET gap or incomplete message, and its the
   gap or incomplete message can't be repaired or completed because the
   sender is suspended.

   The receive window advertisement.  The two
   chunks are semantically equivalent; implementations SHOULD send
   whichever provides the most compact encoding is advertised in units of the SEQUENCE_SET.

   When assembling an acknowledgement 1024-byte blocks.  For
   example, advertisements for a receiving flow:

   1.  If the flow's state is RF_REJECTED, first assemble a Flow
       Exception Report chunk (Section 2.3.16) 1 byte, 1023 bytes, and 1024 bytes each
   require one block.  An advertisement for flow.flowID;

   2.  Choose the acknowledgement chunk type that most compactly encodes
       flow.SEQUENCE_SET;

   3.  Use 1025 bytes requires two
   blocks.

   The following describes the RECOMMENDED method described in Flow Control (Section 3.6.3.5) to
       determine the value for of calculating 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 field of an acknowledgement chunk 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 flow:

   1.  If BUFFERED_SIZE is ready greater than or equal to send an acknowledgement; BUFFER_CAPACITY: set
       ADVERTISE_BYTES to 0;

   2.  If there is no such flow: there BUFFERED_SIZE is no work to do, less than BUFFER_CAPACITY: set ACK_NOW
       ADVERTISE_BYTES to
       false, set RX_DATA_PACKETS BUFFER_CAPACITY - BUFFERED_SIZE;

   3.  Set ADVERTISE_BLOCKS to CEIL(ADVERTISE_BYTES / 1024);

   4.  If ADVERTISE_BLOCKS is 0, clear AND BUFFER_CAPACITY is greater than 0,
       AND delivery to the DELACK_ALARM, user is not suspended: set ADVERTISE_BLOCKS
       to 1; and
       stop; otherwise

   3.  Start

   5.  Set the acknowledgement's bufferBlocksAvailable field to
       ADVERTISE_BLOCKS.

3.6.3.6.  Receiving a new packet;
   4.  Assemble 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 for 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 and include it in the
       packet, truncating it if necessary so that the packet doesn't
       exceed context for the path MTU;

   5. flow indicated by
       chunk.flowID; then

   3.  Set flow.SHOULD_ACK to false;

   6. true; and

   4.  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 session.ACK_NOW to send an acknowledgement into the packet, as
       described below; and

   8.  Send the packet.

3.6.3.4.6.  Opportunistic Acknowledgement

   When sending true.

3.6.3.7.  Rejecting a packet with user data or Flow

   A receiver can reject an acknowledgement, RF_OPEN flow at any other
   receiving flows that are ready to send an acknowledgement should
   include their acknowledgements in the packet if possible. time and for any reason.
   To piggyback acknowledgements in reject 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: in the RF_OPEN state:

   1.  Assemble an acknowledgement for  Move to the flow; RF_REJECTED state;

   2.  Discard all entries in flow.RECV_BUFFER, as they are no longer
       relevant;

   3.  If the acknowledgement cannot be included in user rejected the packet without
       exceeding flow, set flow.EXCEPTION_CODE to the path MTU:
       exception code indicated by the packet is full, stop; user; otherwise

   3.  Include the acknowledgement in flow was
       rejected automatically by the packet; implementation, so the exception
       code is 0;

   4.  Set flow.SHOULD_ACK to false; true; and

   5.  Set flow.PREV_RWND session.ACK_NOW to the bufferBlocksAvailable field of the
       included acknowledgement chunk; and

   6.  If there are no longer any receiving flows 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 session 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
       are ready to send 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 acknowledgement: set session.ACK_NOW RF_OPEN or RF_REJECTED receiving flow becomes complete, move
   to
       false, the RF_COMPLETE_LINGER state, set session.RX_DATA_PACKETS flow.SHOULD_ACK to 0, and clear
       session.DELACK_ALARM.

3.6.3.4.7.  Example
   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 true, and 33 lost set
   session.ACK_NOW to true.

   A receiving flow SHOULD remain in transit, 31 abandoned
   and 33 retransmitted.

                                 Figure 21

3.6.3.5.  Flow Control the RF_COMPLETE_LINGER state for
   120 seconds.  After 120 seconds, move to the RF_CLOSED state.  The
   receiving flow receiver maintains a buffer for reassembling is now closed, and reordering its resources can be reclaimed once
   all complete messages for delivery in flow.RECV_BUFFER have been delivered to the
   user (Section 3.6.3.3).  The
   implementation and same flow ID might be used for a new
   flow by the user may wish to limit sender after this point.

   Discussion: The flow sender detects that the amount flow is complete on
   receiving an acknowledgement of resources
   (including buffer memory) all sequence numbers of the flow.

   This can't happen until after the receiver has detected that a the flow
   is allowed 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 use.

   RTMFP provides 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 means new sending flow
   for each receiving at least 10 seconds after the flow to govern receiver has closed the amount
   receiving flow context.  This ensures correct operation independent
   of data sent by network delay and even when the sender, by way of sender's clock runs up to 8
   percent faster than the bufferBytesAvailable
   derived field of acknowledgement chunks receiver's.

4.  IANA Considerations

   This memo specifies chunk type code values (Section 2.3.13,
   Section 2.3.14). 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 derived field indicates 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 amount of cryptographic
   algorithms, data formats, and semantics as used within this
   framework.  Designing a Cryptography Profile to ensure that the sender is allowed
   communications are protected to have outstanding in the network, until
   instructed otherwise.  This amount is also called degree required by the receive window.

   The flow receiver can suspend
   application-specific threat model is outside the sender by advertising a closed
   (zero length) receive window. scope of this
   specification.

   The user can suspend delivery well-known Default Session Key of messages 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 receiving flow
   (Section 3.6.3.3).  This can cause the receive buffer effort required for casual passive
   observation of startup packets; to fill.

   In order allow for progress different applications
   of RTMFP using different Default Session Keys to be made on completing a fragmented message (intentionally or repairing a gap for sequenced delivery in a flow, the flow
   receiver
   not) share network transport addresses without interference.  The
   Default Session Key, being well-known, MUST advertise at least one buffer block in an
   acknowledgement if it is not suspended, even if NOT be construed to
   contribute to the amount security of data session startup; session startup is
   essentially in the buffer exceeds the buffer capacity, unless the buffer capacity is
   0.  Otherwise, deadlock can occur, as 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 or any substantially similar method
   REQUIRES at least that the receive buffer will stay
   full and won't drain because Packet Encryption function of the
   Cryptography Profile (Section 2.2.3) employs a gap or incomplete message, and cryptographic
   verification mechanism comprising secret information known only to
   the
   gap or incomplete message can't be repaired two endpoints.  Without this constraint, that or completed because the
   sender is suspended.

   The receive window is advertised any
   substantially similar method becomes "session hijacking support".

   Flows and packet fragmentation imply semantics that could cause
   unbounded resource utilization in units receivers, causing a denial of 1024-byte blocks.  For
   example, advertisements for 1 byte, 1023 bytes,
   service.  Implementations SHOULD guard against unbounded or excessive
   resource use, 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 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 acknowledgement chunk for IHello and that possesses 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
   certificate matching the user is not suspended: set ADVERTISE_BLOCKS Endpoint Discriminator (without having to 1; and

   5.  Set
   know the acknowledgement's bufferBlocksAvailable field private key, if any, associated with it) can deny the
   Initiator access to
       ADVERTISE_BLOCKS.

3.6.3.6.  Receiving a Buffer Probe

   A Buffer Probe chunk (Section 2.3.15) the desired Responder by sending an RHello before
   the desired Responder does, since only the first received RHello is sent
   selected by the flow sender
   (Section 3.6.2.9.1) to request Initiator.  The attacker needn't forge the current receive window
   advertisement (in desired
   Responder's source address, since the form of an acknowledgement) from RHello is selected based on the flow
   receiver.

   On receipt of a Buffer Probe chunk:

   1.  If chunk.flowID doesn't belong to a receiving flow in
   tag echo and not the same
       session in packet's source address.  This can simplify the RF_OPEN, RF_REJECTED,
   attack in some network or RF_COMPLETE_LINGER state:
       ignore this Buffer Probe; otherwise,

   2.  Retrieve the receiving flow context host configurations.

6.  Acknowledgements

   Special thanks go to Matthew Kaufman for his contributions to the flow indicated by
       chunk.flowID; then

   3.  Set flow.SHOULD_ACK
   creation and design of RTMFP.

   Thanks to true; 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.

   [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

   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 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 any reason.
   To reject a receiving flow 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 the RF_OPEN state:

   1.  Move to the RF_REJECTED state;

   2.  Discard all entries 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 flow.RECV_BUFFER, as they RTMFP.  The algorithm includes slow-start and
   congestion avoidance phases including modified increase and decrease
   parameters.  These parameters are no longer
       relevant;

   3.  If the user rejected the flow, set flow.EXCEPTION_CODE 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
       exception code indicated by the user; otherwise 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 flow was
       rejected automatically by undesirable
   behaviors are the implementation, so cutting of 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 congestion window in the RF_REJECTED state.

3.6.3.8.  Close

   A receiving flow is complete when every sequence number from 0
   through half during a
   loss event, and including the final sequence number has been received;
   that is, when flow.RF_FINAL_SN has rapidity of the slow start algorithm's
   exponential growth.  Cutting the congestion window in half requires a value
   large channel headroom to support a real-time application, and flow.SEQUENCE_SET
   contains every sequence number can
   cause a large amount of jitter from 0 through flow.RF_FINAL_SN,
   inclusive.

   When an RF_OPEN or RF_REJECTED receiving flow becomes complete, move
   to sender-side buffering.  Doubling
   the RF_COMPLETE_LINGER state, set flow.SHOULD_ACK to true, and set
   session.ACK_NOW to true.

   A receiving flow SHOULD remain in congestion window during the RF_COMPLETE_LINGER state for
   120 seconds.  After 120 seconds, move slow-start phase can lead 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
   congestion window temporarily growing to twice the
   user (Section 3.6.3.3).  The same flow ID might be used for size it should be,
   causing a new
   flow by period of excessive loss in the sender after this point.

   Discussion: The flow sender detects path.

   We found that a number of deployed TCP implementations use the flow is complete on
   receiving an acknowledgement method
   of all sequence numbers equation 3 from RFC 5681 Section 3.1, which, when combined with
   the recommended behavior of acknowledging every other packet, causes
   the flow.

   This can't happen until after congestion window to grow at approximately half the receiver has detected that rate as the flow
   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 complete and acknowledged all approximately
   half of the sequence numbers. typical maximum segment size of 1500 bytes while also
   being easily subdivided.

   The
   receiver's RF_COMPLETE_LINGER period is two minutes (one Maximum
   Segment Lifetime (MSL)), which allows any in-flight packets sender may be sending real-time data to drain
   from the network without being misidentified, and gives 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 sender an
   opportunity
   Internet.  In order to retransmit any sequence numbers if scale the completing
   acknowledgement is lost.  The sender's F_COMPLETE_LINGER period sending rate quickly, the slow start
   algorithm is at
   least two minutes plus 10 seconds, and doesn't begin until desired, but slow start's normal rate of increase can
   cause excessive loss in the
   completing acknowledgement last round trip.  Accordingly, slow
   start's exponential increase rate is received; therefore, adjusted to double every
   approximately 3 round trips instead of every round trip.  The
   multiplicative decrease cuts the same flow
   identifier won't be re-used congestion window by the flow sender for one eighth on
   loss to maintain a new smoother sending flow
   for rate.  The additive increase is
   done at least 10 seconds after half the flow receiver has closed normal rate (incrementing at 384 bytes per round
   trip), both to compensate for the
   receiving flow context.  This ensures correct operation independent
   of network delay less aggressive loss response and even when the sender's clock runs up
   to 8
   percent faster than probe 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 path capacity more gently.

   The far end may report that can it is receiving real-time data from other
   peers, or the sender may be used 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 establish
   a confidential yield capacity to the real-time flows and authenticated session between endpoints.  A
   Cryptography Profile, not specified herein, defines
   to avoid excessive losses while probing the cryptographic
   algorithms, data formats, path capacity.  Slow
   start's exponential increase is disabled and semantics as used within this
   framework.  Designing a Cryptography Profile 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 ensure that
   communications are protected 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 degree required by
   round-trip time instead of doing them all at once.  We divide the
   application-specific threat model is outside
   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 scope additive increase and multiplicative decrease of this
   specification. the
   congestion window in large delay-bandwidth scenarios.  The well-known Default Session Key of 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 Cryptography Profile serves
   multiple purposes, including: to scramble session startup packets 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
   protect interior fields from undesirable modification
   spread the increase out over the round-trip.  The congestion window
   is decreased by middleboxes
   such as NATs; 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 effort required for casual passive
   observation of startup packets; to allow for different applications
   of RTMFP using different Default Session Keys scaled
   increase is adjusted to (intentionally 0.5% 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 384 bytes per round trip, whichever
   is
   essentially in greater.

A.2.  Algorithm

   Let SMSS denote the clear.

   Section 3.5.4.2 describes an OPTIONAL method Sender Maximum Segment Size [RFC5681], for processing a change
   of network address of a communicating peer.  Securely processing
   address mobility using that or any substantially similar method
   REQUIRES at least that
   example 1460 bytes.  Let CWND_INIT denote the Packet Encryption function of Initial Congestion
   Window (IW) according to RFC 5681 Section 3.1, for example 4380
   bytes.  Let CWND_TIMEDOUT denote the
   Cryptography Profile (Section 2.2.3) employs congestion window after a cryptographic
   verification mechanism comprising secret
   timeout indicating lost data, being 1*SMSS (for example 1460 bytes).

   Let the session information known only context contain additional variables:

   o  CWND: the Congestion Window, initialized to CWND_INIT;

   o  SSTHRESH: 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 Slow Start Threshold, initialized to flood a victim address or network with Initiator Hello
   packets, potentially causing positive
      infinity;

   o  ACKED_BYTES_ACCUMULATOR: a denial count of service.

   An attacker that can passively observe an IHello and that possesses a
   certificate matching the Endpoint Discriminator (without having acknowledged bytes,
      initialized to
   know 0;

   o  ACKED_BYTES_THIS_PACKET: a count of acknowledged bytes observed in
      the private key, if any, associated with it) can deny current packet;

   o  PRE_ACK_OUTSTANDING: the
   Initiator access to number of bytes outstanding in the desired Responder by sending an RHello
      network before processing any acknowledgements in the desired Responder does, since only current
      packet;

   o  ANY_LOSS: an indication to whether any loss has been detected in
      the first received RHello is
   selected by current packet;

   o  ANY_NAKS: an indication to whether any negative acknowledgements
      have been detected in the Initiator.  The attacker needn't forge current packet;

   o  ANY_ACKS: an indication to whether any acknowledgement chunks have
      been received in the desired
   Responder's source address, since current packet;

   Let FASTGROW_ALLOWED indicate whether the RHello congestion window is selected based
   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
   tag echo 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 not otherwise being
   TRUE.

   Let TC_SENT indicate whether a Time Critical Forward Notification has
   been sent on this session within the packet's source address.  This can simplify last 800 milliseconds.

   Implement the
   attack 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 some network or host configurations.

6.  Acknowledgements

   Special thanks go Figure 23:

   on TimeoutNotification(WAS_LOSS):
       SSTHRESH <- MAX(SSTHRESH, CWND * 3/4);
       ACKED_BYTES_ACCUMULATOR <- 0;
       if WAS_LOSS is TRUE:
           CWND <- CWND_TIMEDOUT;
       else:
           CWND <- 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 Matthew Kaufman for his contributions TRUE.

   On notification of negative acknowledgement (Section 3.6.2.5): set
   ANY_NAKS to the
   creation and design TRUE.

   On notification of RTMFP.

   Thanks acknowledgement of data (Section 3.6.2.4): set
   ANY_ACKS to Wesley Eddy, Philipp Hancke, Bela Lubkin, TRUE, and Martin
   Stiemerling for their detailed reviews add the count 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.

   [RFC2119]  Bradner, S., "Key words acknowledged bytes to
   ACKED_BYTES_THIS_PACKET.

   After processing all chunks in each received packet for use this session,
   perform the function 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 Figure 24:

   if ANY_LOSS is TRUE:
       if (TC_SENT is TRUE) OR (PRE_ACK_OUTSTANDING > 67200 AND \
       FASTGROW_ALLOWED is TRUE):
           SSTHRESH <- MAX(PRE_ACK_OUTSTANDING * 7/8, CWND_INIT);
       else:
           SSHTRESH <- MAX(PRE_ACK_OUTSTANDING * 1/2, CWND_INIT);
       CWND <- SSTHRESH;
       ACKED_BYTES_ACCUMULATOR <- 0;
   else if (ANY_ACKS is TRUE) AND (ANY_NAKS is FALSE) AND \
   (PRE_ACK_OUTSTANDING >= CWND):
       var INCREASE <- 0;
       var AITHRESH;
       if FASTGROW_ALLOWED is TRUE:
           if CWND < SSTHRESH:
               INCREASE <- ACKED_BYTES_THIS_PACKET;
           else:
               ACKED_BYTES_ACCUMULATOR += ACKED_BYTES_THIS_PACKET;
               AITHRESH <- MIN(MAX(FLOOR(CWND / 16), 64), 4800);
               while ACKED_BYTES_ACCUMULATOR >= AITHRESH:
                   ACKED_BYTES_ACCUMULATOR -= AITHRESH;
                   INCREASE += 48;
       else FASTGROW_ALLOWED is FALSE:
           if CWND < SSTHRESH AND TC_SENT is TRUE:
               INCREASE <- CEIL(ACKED_BYTES_THIS_PACKET / 4);
           else:
               var AITHRESH_CAP;
               if TC_SENT is TRUE:
                   AITHRESH_CAP <- 2400;
               else:
                   AITHRESH_CAP <- 4800;
               ACKED_BYTES_ACCUMULATOR += ACKED_BYTES_THIS_PACKET;
               AITHRESH <- MIN(MAX(FLOOR(CWND / 16), 64), AITHRESH_CAP);
               while ACKED_BYTS_ACCUMULATOR >= AITHRESH:
                   ACKED_BYTES_ACCUMULATOR -= AITHRESH;
                   INCREASE += 24;
       CWND <- MAX(CWND + MIN(INCREASE, SMSS), CWND_INIT);

       Figure 24: Pseudocode for NAT (STUN)", RFC 5389,
              October 2008. congestion window adjustment after
                            processing a packet

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/