<?xml version="1.0"?>

<!--
  Copyright Notice
  ================
  (c) Copyright Cisco Systems, Credit Suisse, Deutsche Borse Systems, Envoy Technologies, Inc.,
  Goldman Sachs, IONA Technologies PLC, iMatix Corporation sprl.,JPMorgan Chase Bank Inc. N.A,
  Novell, Rabbit Technologies Ltd., Red Hat, Inc., TWIST Process Innovations ltd, and 29West Inc.
  2006, 2007. All rights reserved.

  License
  =======

  Cisco Systems, Credit Suisse, Deutsche Borse Systems, Envoy Technologies, Inc.,Goldman Sachs,
  IONA Technologies PLC, iMatix Corporation sprl.,JPMorgan Chase Bank Inc. N.A, Novell, Rabbit
  Technologies Ltd., Red Hat, Inc., TWIST Process Innovations ltd, and 29West Inc. (collectively,
  the "Authors") each hereby grants to you a worldwide, perpetual, royalty-free, nontransferable,
  nonexclusive license to (i) copy, display, distribute and implement the Advanced Messaging Queue
  Protocol ("AMQP") Specification and (ii) the Licensed Claims that are held by the Authors, all for
  the purpose of implementing the Advanced Messaging Queue Protocol Specification. Your license and
  any rights under this Agreement will terminate immediately without notice from any Author if you
  bring any claim, suit, demand, or action related to the Advanced Messaging Queue Protocol
  Specification against any Author. Upon termination, you shall destroy all copies of the Advanced
  Messaging Queue Protocol Specification in your possession or control.

  As used hereunder, "Licensed Claims" means those claims of a patent or patent application,
  throughout the world, excluding design patents and design registrations, owned or controlled, or
  that can be sublicensed without fee and in compliance with the requirements of this Agreement, by
  an Author or its affiliates now or at any future time and which would necessarily be infringed by
  implementation of the Advanced Messaging Queue Protocol Specification. A claim is necessarily
  infringed hereunder only when it is not possible to avoid infringing it because there is no
  plausible non-infringing alternative for implementing the required portions of the Advanced
  Messaging Queue Protocol Specification. Notwithstanding the foregoing, Licensed Claims shall not
  include any claims other than as set forth above even if contained in the same patent as Licensed
  Claims; or that read solely on any implementations of any portion of the Advanced Messaging Queue
  Protocol Specification that are not required by the Advanced Messaging Queue Protocol
  Specification, or that, if licensed, would require a payment of royalties by the licensor to
  unaffiliated third parties. Moreover, Licensed Claims shall not include (i) any enabling
  technologies that may be necessary to make or use any Licensed Product but are not themselves
  expressly set forth in the Advanced Messaging Queue Protocol Specification (e.g., semiconductor
  manufacturing technology, compiler technology, object oriented technology, networking technology,
  operating system technology, and the like); or (ii) the implementation of other published
  standards developed elsewhere and merely referred to in the body of the Advanced Messaging Queue
  Protocol Specification, or (iii) any Licensed Product and any combinations thereof the purpose or
  function of which is not required for compliance with the Advanced Messaging Queue Protocol
  Specification. For purposes of this definition, the Advanced Messaging Queue Protocol
  Specification shall be deemed to include both architectural and interconnection requirements
  essential for interoperability and may also include supporting source code artifacts where such
  architectural, interconnection requirements and source code artifacts are expressly identified as
  being required or documentation to achieve compliance with the Advanced Messaging Queue Protocol
  Specification.

  As used hereunder, "Licensed Products" means only those specific portions of products (hardware,
  software or combinations thereof) that implement and are compliant with all relevant portions of
  the Advanced Messaging Queue Protocol Specification.

  The following disclaimers, which you hereby also acknowledge as to any use you may make of the
  Advanced Messaging Queue Protocol Specification:

  THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION IS PROVIDED "AS IS," AND THE AUTHORS MAKE NO
  REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, OR TITLE; THAT THE CONTENTS
  OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
  IMPLEMENTATION OF THE ADVANCED MESSAGING QUEUE PROTOCOL SPECIFICATION WILL NOT INFRINGE ANY THIRD
  PARTY PATENTS, COPYRIGHTS, TRADEMARKS OR OTHER RIGHTS.

  THE AUTHORS WILL NOT BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL
  DAMAGES ARISING OUT OF OR RELATING TO ANY USE, IMPLEMENTATION OR DISTRIBUTION OF THE ADVANCED
  MESSAGING QUEUE PROTOCOL SPECIFICATION.

  The name and trademarks of the Authors may NOT be used in any manner, including advertising or
  publicity pertaining to the Advanced Messaging Queue Protocol Specification or its contents
  without specific, written prior permission. Title to copyright in the Advanced Messaging Queue
  Protocol Specification will at all times remain with the Authors.

  No other rights are granted by implication, estoppel or otherwise.

  Upon termination of your license or rights under this Agreement, you shall destroy all copies of
  the Advanced Messaging Queue Protocol Specification in your possession or control.

  Trademarks
  ==========
  "JPMorgan", "JPMorgan Chase", "Chase", the JPMorgan Chase logo and the Octagon Symbol are
  trademarks of JPMorgan Chase & Co.

  IMATIX and the iMatix logo are trademarks of iMatix Corporation sprl.

  IONA, IONA Technologies, and the IONA logos are trademarks of IONA Technologies PLC and/or its
  subsidiaries.

  LINUX is a trademark of Linus Torvalds. RED HAT and JBOSS are registered trademarks of Red Hat,
  Inc. in the US and other countries.

  Java, all Java-based trademarks and OpenOffice.org are trademarks of Sun Microsystems, Inc. in the
  United States, other countries, or both.

  Other company, product, or service names may be trademarks or service marks of others.

  Links to full AMQP specification:
  =================================
  http://www.envoytech.org/spec/amq/
  http://www.iona.com/opensource/amqp/
  http://www.redhat.com/solutions/specifications/amqp/
  http://www.twiststandards.org/tiki-index.php?page=AMQ
  http://www.imatix.com/amqp
-->

<!--
  XML Notes
  =========

  We use entities to indicate repetition; attributes to indicate properties.

  We use the "name" attribute as an identifier, usually within the context of the surrounding
  entities.

  We use hyphens (minus char '-') to seperate words in names.

  We do not enforce any particular validation mechanism but we support all mechanisms.  The protocol
  definition conforms to a formal grammar that is published seperately in several technologies.

-->

<!DOCTYPE amqp SYSTEM "amqp.dtd">

<amqp xmlns="http://www.amqp.org/schema/amqp.xsd"
    major="0" minor="10" port="5672">

  <!--
    ====================== == type definitions == ======================
  -->

  <!--
    0x00 - 0x0f: Fixed width, 1 octet
  -->

  <type name="bin8" code="0x00" fixed-width="1" label="octet of unspecified encoding">
    <doc>
      The bin8 type consists of exactly one octet of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET
      +----------+
      |   bin8   |
      +----------+
    </doc>

    <doc type="bnf">
               bin8 = OCTET
    </doc>
  </type>

  <type name="int8" code="0x01" fixed-width="1" label="8-bit signed integral value (-128 - 127)">
    <doc>
      The int8 type is a signed integral value encoded using an 8-bit two's complement
      representation.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET
      +----------+
      |   int8   |
      +----------+
    </doc>

    <doc type="bnf">
               int8 = OCTET
    </doc>
  </type>

  <type name="uint8" code="0x02" fixed-width="1" label="8-bit unsigned integral value (0 - 255)">
    <doc>
      The uint8 type is an 8-bit unsigned integral value.
    </doc>

    <doc type="picture" title="Wire Format">
        1 OCTET
      +---------+
      |  uint8  |
      +---------+
    </doc>

    <doc type="bnf">
              uint8 = OCTET
    </doc>
  </type>

  <type name="char" code="0x04" fixed-width="1" label="an iso-8859-15 character">
    <doc>
      The char type encodes a single character from the iso-8859-15 character set.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET
      +----------+
      |   char   |
      +----------+
    </doc>

    <doc type="bnf">
               char = OCTET
    </doc>
  </type>

  <type name="boolean" code="0x08" fixed-width="1"
        label="boolean value (zero represents false, nonzero represents true)">
    <doc>
      The boolean type is a single octet that encodes a true or false value. If the octet is zero,
      then the boolean is false. Any other value represents true.
    </doc>

    <doc type="picture" title="Wire Format">
        1 OCTET
      +---------+
      | boolean |
      +---------+
    </doc>

    <doc type="bnf">
            boolean = OCTET
    </doc>
  </type>

  <!--
    0x10 - 0x1f: Fixed width, 2 octets
  -->

  <type name="bin16" code="0x10" fixed-width="2" label="two octets of unspecified binary encoding">
    <doc>
      The bin16 type consists of two consecutive octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET
      +-----------+-----------+
      | octet-one | octet-two |
      +-----------+-----------+
    </doc>

    <doc type="bnf">
              bin16 = 2 OCTET
    </doc>
  </type>

  <type name="int16" code="0x11" fixed-width="2" label="16-bit signed integral value">
    <doc>
      The int16 type is a signed integral value encoded using a 16-bit two's complement
      representation in network byte order.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET    1 OCTET
      +-----------+----------+
      | high-byte | low-byte |
      +-----------+----------+
    </doc>

    <doc type="bnf">
              int16 = high-byte low-byte
          high-byte = OCTET
           low-byte = OCTET
    </doc>
  </type>

  <type name="uint16" code="0x12" fixed-width="2" label="16-bit unsigned integer">
    <doc>
      The uint16 type is a 16-bit unsigned integral value encoded in network byte order.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET    1 OCTET
      +-----------+----------+
      | high-byte | low-byte |
      +-----------+----------+
    </doc>

    <doc type="bnf">
             uint16 = high-byte low-byte
          high-byte = OCTET
           low-byte = OCTET
    </doc>
  </type>

  <!--
    0x20 - 0x2f: Fixed width, 4 octets
  -->

  <type name="bin32" code="0x20" fixed-width="4" label="four octets of unspecified binary encoding">
    <doc>
      The bin32 type consists of 4 consecutive octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET      1 OCTET      1 OCTET
      +-----------+-----------+-------------+------------+
      | octet-one | octet-two | octet-three | octet-four |
      +-----------+-----------+-------------+------------+
    </doc>

    <doc type="bnf">
              bin32 = 4 OCTET
    </doc>
  </type>

  <type name="int32" code="0x21" fixed-width="4" label="32-bit signed integral value">
    <doc>
      The int32 type is a signed integral value encoded using a 32-bit two's complement
      representation in network byte order.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET     1 OCTET    1 OCTET
      +-----------+------------+----------+----------+
      | byte-four | byte-three | byte-two | byte-one |
      +-----------+------------+----------+----------+
          MSB                                 LSB
    </doc>

    <doc type="bnf">
              int32 = byte-four byte-three byte-two byte-one
          byte-four = OCTET ; most significant byte (MSB)
         byte-three = OCTET
           byte-two = OCTET
           byte-one = OCTET ; least significant byte (LSB)
    </doc>
  </type>

  <type name="uint32" code="0x22" fixed-width="4" label="32-bit unsigned integral value">
    <doc>
      The uint32 type is a 32-bit unsigned integral value encoded in network byte order.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET     1 OCTET    1 OCTET
      +-----------+------------+----------+----------+
      | byte-four | byte-three | byte-two | byte-one |
      +-----------+------------+----------+----------+
          MSB                                 LSB
    </doc>

    <doc type="bnf">
             uint32 = byte-four byte-three byte-two byte-one
          byte-four = OCTET ; most significant byte (MSB)
         byte-three = OCTET
           byte-two = OCTET
           byte-one = OCTET ; least significant byte (LSB)
    </doc>
  </type>

  <type name="float" code="0x23" fixed-width="4"
        label="single precision IEEE 754 32-bit floating point">
    <doc>
      The float type encodes a single precision 32-bit floating point number. The format and
      operations are defined by the IEEE 754 standard for 32-bit floating point numbers.
    </doc>

    <doc type="picture" title="Wire Format">
              4 OCTETs
      +-----------------------+
      |         float         |
      +-----------------------+
        IEEE 754 32-bit float
    </doc>

    <doc type="bnf">
              float = 4 OCTET ; IEEE 754 32-bit floating point number
    </doc>
  </type>

  <type name="char-utf32" code="0x27" fixed-width="4"
        label="single unicode character in UTF-32 encoding">
    <doc>
      The char-utf32 type consists of a single unicode character in the UTF-32 encoding.
    </doc>

    <doc type="picture" title="Wire Format">
            4 OCTETs
      +------------------+
      |    char-utf32    |
      +------------------+
        UTF-32 character
    </doc>

    <doc type="bnf">
         char-utf32 = 4 OCTET ; single UTF-32 character
    </doc>
  </type>

  <type name="sequence-no" fixed-width="4" label="serial number defined in RFC-1982">
    <doc>
      The sequence-no type encodes, in network byte order, a serial number as defined in RFC-1982.
      The arithmetic, operators, and ranges for numbers of this type are defined by RFC-1982.
    </doc>

    <doc type="picture" title="Wire Format">
               4 OCTETs
      +------------------------+
      |      sequence-no       |
      +------------------------+
        RFC-1982 serial number
    </doc>

    <doc type="bnf">
        sequence-no = 4 OCTET ; RFC-1982 serial number
    </doc>
  </type>

  <!--
    0x30 - 0x3f: Fixed width types - 8 octets
  -->

  <type name="bin64" code="0x30" fixed-width="8"
        label="eight octets of unspecified binary encoding">
    <doc>
      The bin64 type consists of eight consecutive octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET            1 OCTET       1 OCTET
      +-----------+-----------+-----+-------------+-------------+
      | octet-one | octet-two | ... | octet-seven | octet-eight |
      +-----------+-----------+-----+-------------+-------------+
    </doc>

    <doc type="bnf">
              bin64 = 8 OCTET
    </doc>
  </type>

  <type name="int64" code="0x31" fixed-width="8" label="64-bit signed integral value">
    <doc>
      The int64 type is a signed integral value encoded using a 64-bit two's complement
      representation in network byte order.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET      1 OCTET           1 OCTET    1 OCTET
      +------------+------------+-----+----------+----------+
      | byte-eight | byte-seven | ... | byte-two | byte-one |
      +------------+------------+-----+----------+----------+
          MSB                                        LSB
    </doc>

    <doc type="bnf">
              int64 = byte-eight byte-seven byte-six byte-five
                      byte-four byte-three byte-two byte-one
         byte-eight = 1 OCTET ; most significant byte (MSB)
         byte-seven = 1 OCTET
           byte-six = 1 OCTET
          byte-five = 1 OCTET
          byte-four = 1 OCTET
         byte-three = 1 OCTET
           byte-two = 1 OCTET
           byte-one = 1 OCTET ; least significant byte (LSB)
    </doc>
  </type>

  <type name="uint64" code="0x32" fixed-width="8" label="64-bit unsigned integral value">
    <doc>
      The uint64 type is a 64-bit unsigned integral value encoded in network byte order.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET      1 OCTET           1 OCTET    1 OCTET
      +------------+------------+-----+----------+----------+
      | byte-eight | byte-seven | ... | byte-two | byte-one |
      +------------+------------+-----+----------+----------+
          MSB                                        LSB
    </doc>

    <doc type="bnf">
             uint64 = byte-eight byte-seven byte-six byte-five
                      byte-four byte-three byte-two byte-one
         byte-eight = 1 OCTET ; most significant byte (MSB)
         byte-seven = 1 OCTET
           byte-six = 1 OCTET
          byte-five = 1 OCTET
          byte-four = 1 OCTET
         byte-three = 1 OCTET
           byte-two = 1 OCTET
           byte-one = 1 OCTET ; least significant byte (LSB)
    </doc>
  </type>

  <type name="double" code="0x33" fixed-width="8" label="double precision IEEE 754 floating point">
    <doc>
      The double type encodes a double precision 64-bit floating point number. The format and
      operations are defined by the IEEE 754 standard for 64-bit double precision floating point
      numbers.
    </doc>

    <doc type="picture" title="Wire Format">
              8 OCTETs
      +-----------------------+
      |        double         |
      +-----------------------+
        IEEE 754 64-bit float
    </doc>

    <doc type="bnf">
             double = 8 OCTET ; double precision IEEE 754 floating point number
    </doc>
  </type>

  <type name="datetime" code="0x38" fixed-width="8" label="datetime in 64 bit POSIX time_t format">
    <doc>
      The datetime type encodes a date and time using the 64 bit POSIX time_t format.
    </doc>

    <doc type="picture" title="Wire Format">
             8 OCTETs
      +---------------------+
      |      datetime       |
      +---------------------+
        posix time_t format
    </doc>

    <doc type="bnf">
           datetime = 8 OCTET ; 64 bit posix time_t format
    </doc>
  </type>

  <!--
    0x40 - 0x4f: Fixed width types - 16 octets
  -->

  <type name="bin128" code="0x40" fixed-width="16"
        label="sixteen octets of unspecified binary encoding">
    <doc>
      The bin128 type consists of 16 consecutive octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET             1 OCTET         1 OCTET
      +-----------+-----------+-----+---------------+---------------+
      | octet-one | octet-two | ... | octet-fifteen | octet-sixteen |
      +-----------+-----------+-----+---------------+---------------+
    </doc>

    <doc type="bnf">
             bin128 = 16 OCTET
    </doc>
  </type>

  <type name="uuid" code="0x48" fixed-width="16" label="UUID (RFC-4122 section 4.1.2) - 16 octets">
    <doc>
      The uuid type encodes a universally unique id as defined by RFC-4122. The format and
      operations for this type can be found in section 4.1.2 of RFC-4122.
    </doc>

    <doc type="picture" title="Wire Format">
          16 OCTETs
      +---------------+
      |     uuid      |
      +---------------+
        RFC-4122 UUID
    </doc>

    <doc type="bnf">
               uuid = 16 OCTET ; RFC-4122 section 4.1.2
    </doc>
  </type>

  <!--
    0x50 - 0x5f: Fixed width types - 32 octets
  -->

  <type name="bin256" code="0x50" fixed-width="32"
        label="thirty two octets of unspecified binary encoding">
    <doc>
      The bin256 type consists of thirty two consecutive octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET              1 OCTET            1 OCTET
      +-----------+-----------+-----+------------------+------------------+
      | octet-one | octet-two | ... | octet-thirty-one | octet-thirty-two |
      +-----------+-----------+-----+------------------+------------------+
    </doc>

    <doc type="bnf">
             bin256 = 32 OCTET
    </doc>
  </type>

  <!--
    0x60 - 0x6f: Fixed width types - 64 octets
  -->

  <type name="bin512" code="0x60" fixed-width="64"
        label="sixty four octets of unspecified binary encoding">
    <doc>
      The bin512 type consists of sixty four consecutive octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET               1 OCTET            1 OCTET
      +-----------+-----------+-----+-------------------+------------------+
      | octet-one | octet-two | ... | octet-sixty-three | octet-sixty-four |
      +-----------+-----------+-----+-------------------+------------------+
    </doc>

    <doc type="bnf">
             bin512 = 64 OCTET
    </doc>
  </type>

  <!--
    0x70 - 0x7f: Fixed width types - 128 octets
  -->

  <type name="bin1024" code="0x70" fixed-width="128"
        label="one hundred and twenty eight octets of unspecified binary encoding">
    <doc>
      The bin1024 type consists of one hundred and twenty eight octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET                 1 OCTET                  1 OCTET
      +-----------+-----------+-----+------------------------+------------------------+
      | octet-one | octet-two | ... | octet-one-twenty-seven | octet-one-twenty-eight |
      +-----------+-----------+-----+------------------------+------------------------+
    </doc>

    <doc type="bnf">
            bin1024 = 128 OCTET
    </doc>
  </type>

  <!--
    0x80 - 0x8f: Variable length - one byte length field (up to 255 octets)
  -->

  <type name="vbin8" code="0x80" variable-width="1" label="up to 255 octets of opaque binary data">
    <doc>
      The vbin8 type encodes up to 255 octets of opaque binary data. The number of octets is first
      encoded as an 8-bit unsigned integral value. This is followed by the actual data.
    </doc>

    <doc type="picture" title="Wire Format">
        1 OCTET   size OCTETs
      +---------+-------------+
      |  size   |   octets    |
      +---------+-------------+
         uint8
    </doc>

    <doc type="bnf">
              vbin8 = size octets
               size = uint8
             octets = 0*255 OCTET ; size OCTETs
    </doc>
  </type>

  <type name="str8-latin" code="0x84" variable-width="1" label="up to 255 iso-8859-15 characters">
    <doc>
      The str8-latin type encodes up to 255 octets of iso-8859-15 characters. The number of octets
      is first encoded as an 8-bit unsigned integral value. This is followed by the actual
      characters.
    </doc>

    <doc type="picture" title="Wire Format">
        1 OCTET        size OCTETs
      +---------+------------------------+
      |  size   |       characters       |
      +---------+------------------------+
        uint16    iso-8859-15 characters
    </doc>

    <doc type="bnf">
         str8-latin = size characters
               size = uint8
         characters = 0*255 OCTET ; size OCTETs
    </doc>
  </type>

  <type name="str8" code="0x85" variable-width="1" label="up to 255 octets worth of UTF-8 unicode">
    <doc>
      The str8 type encodes up to 255 octets worth of UTF-8 unicode. The number of octets of unicode
      is first encoded as an 8-bit unsigned integral value. This is followed by the actual UTF-8
      unicode. Note that the encoded size refers to the number of octets of unicode, not necessarily
      the number of characters since the UTF-8 unicode may include multi-byte character sequences.
    </doc>

    <doc type="picture" title="Wire Format">
        1 OCTET   size OCTETs
      +---------+--------------+
      |  size   | utf8-unicode |
      +---------+--------------+
         uint8
    </doc>

    <doc type="bnf">
               str8 = size utf8-unicode
               size = uint8
       utf8-unicode = 0*255 OCTET ; size OCTETs
    </doc>
  </type>

  <type name="str8-utf16" code="0x86" variable-width="1"
        label="up to 255 octets worth of UTF-16 unicode">
    <doc>
      The str8-utf16 type encodes up to 255 octets worth of UTF-16 unicode. The number of octets of
      unicode is first encoded as an 8-bit unsigned integral value. This is followed by the actual
      UTF-16 unicode. Note that the encoded size refers to the number of octets of unicode, not the
      number of characters since the UTF-16 unicode will include at least two octets per unicode
      character.
    </doc>

    <doc type="picture" title="Wire Format">
        1 OCTET    size OCTETs
      +---------+---------------+
      |  size   | utf16-unicode |
      +---------+---------------+
         uint8
    </doc>

    <doc type="bnf">
         str8-utf16 = size utf16-unicode
               size = uint8
      utf16-unicode = 0*255 OCTET ; size OCTETs
    </doc>
  </type>

  <!--
    0x90 - 0x9f: Variable length types - two byte length field (up to 65535 octets)
  -->

  <type name="vbin16" code="0x90" variable-width="2"
        label="up to 65535 octets of opaque binary data">
    <doc>
      The vbin16 type encodes up to 65535 octets of opaque binary data. The number of octets is
      first encoded as a 16-bit unsigned integral value in network byte order. This is followed by
      the actual data.
    </doc>

    <doc type="picture" title="Wire Format">
        2 OCTETs   size OCTETs
      +----------+-------------+
      |   size   |   octets    |
      +----------+-------------+
         uint16
    </doc>

    <doc type="bnf">
             vbin16 = size octets
               size = uint16
             octets = 0*65535 OCTET ; size OCTETs
    </doc>
  </type>

  <type name="str16-latin" code="0x94" variable-width="2"
        label="up to 65535 iso-8859-15 characters">
    <doc>
      The str16-latin type encodes up to 65535 octets of is-8859-15 characters. The number of octets
      is first encoded as a 16-bit unsigned integral value in network byte order. This is followed
      by the actual characters.
    </doc>

    <doc type="picture" title="Wire Format">
        2 OCTETs        size OCTETs
      +----------+------------------------+
      |   size   |       characters       |
      +----------+------------------------+
         uint16    iso-8859-15 characters
    </doc>

    <doc type="bnf">
        str16-latin = size characters
               size = uint16
         characters = 0*65535 OCTET ; size OCTETs
    </doc>
  </type>

  <type name="str16" code="0x95" variable-width="2"
        label="up to 65535 octets worth of UTF-8 unicode">
    <doc>
      The str16 type encodes up to 65535 octets worth of UTF-8 unicode. The number of octets is
      first encoded as a 16-bit unsigned integral value in network byte order. This is followed by
      the actual UTF-8 unicode. Note that the encoded size refers to the number of octets of
      unicode, not necessarily the number of unicode characters since the UTF-8 unicode may include
      multi-byte character sequences.
    </doc>

    <doc type="picture" title="Wire Format">
        2 OCTETs   size OCTETs
      +----------+--------------+
      |   size   | utf8-unicode |
      +----------+--------------+
         uint16
    </doc>

    <doc type="bnf">
              str16 = size utf8-unicode
               size = uint16
       utf8-unicode = 0*65535 OCTET ; size OCTETs
    </doc>
  </type>

  <type name="str16-utf16" code="0x96" variable-width="2"
        label="up to 65535 octets worth of UTF-16 unicode">
    <doc>
      The str16-utf16 type encodes up to 65535 octets worth of UTF-16 unicode. The number of octets
      is first encoded as a 16-bit unsigned integral value in network byte order. This is followed
      by the actual UTF-16 unicode. Note that the encoded size refers to the number of octets of
      unicode, not the number of unicode characters since the UTF-16 unicode will include at least
      two octets per unicode character.
    </doc>

    <doc type="picture" title="Wire Format">
        2 OCTETs    size OCTETs
      +----------+---------------+
      |   size   | utf16-unicode |
      +----------+---------------+
         uint16
    </doc>

    <doc type="bnf">
        str16-utf16 = size utf16-unicode
               size = uint16
      utf16-unicode = 0*65535 OCTET ; size OCTETs
    </doc>
  </type>

  <type name="byte-ranges" variable-width="2" label="byte ranges within a 64-bit payload">
    <doc>
      The byte-ranges type encodes up to 65535 octets worth of non-overlapping, non-touching,
      ascending byte ranges within a 64-bit sequence of bytes. Each range is represented as an
      inclusive lower and upper bound that identifies all the byte offsets included within a given
      range.
    </doc>

    <doc>
      The number of octets of data is first encoded as a 16-bit unsigned integral value in network
      byte order. This is then followed by the encoded representation of the ranges included in the
      set. These MUST be encoded in ascending order, and any two ranges included in a given set MUST
      NOT include overlapping or touching byte offsets.
    </doc>

    <doc>
      Each range is encoded as a pair of 64-bit unsigned integral values in network byte order
      respectively representing the lower and upper bounds for that range. Note that because each
      range is exactly 16 octets, the size in octets of the encoded ranges will always be 16 times
      the number of ranges in the set.
    </doc>

    <doc type="picture" title="Wire Format">
                 +----= size OCTETs =----+
                 |                       |
        2 OCTETs |       16 OCTETs       |
      +----------+-----+-----------+-----+
      |   size   | .../|   range   |\... |
      +----------+---/ +-----------+ \---+
         uint16     / /             \ \
                   / /               \ \
                  / 8 OCTETs   8 OCTETs \
                 +-----------+-----------+
                 |   lower   |   upper   |
                 +-----------+-----------+
                     uint64     uint64
    </doc>

    <doc type="bnf">
        byte-ranges = size *range
               size = uint16
              range = lower upper
              lower = uint64
              upper = uint64
    </doc>
  </type>

  <type name="sequence-set" variable-width="2" label="ranged set representation">
    <doc>
      The sequence-set type is a set of pairs of RFC-1982 numbers representing a discontinuous range
      within an RFC-1982 sequence. Each pair represents a closed interval within the list.
    </doc>

    <doc>
      Sequence-sets can be represented as lists of pairs of positive 32-bit numbers, each pair
      representing a closed interval that does not overlap or touch with any other interval in the
      list. For example, a set containing words 0, 1, 2, 5, 6, and 15 can be represented:
    </doc>

    <doc type="picture">
      [(0, 2), (5, 6), (15, 15)]
    </doc>

    <doc>
      1) The list-of-pairs representation is sorted ascending (as defined by RFC 1982
      (http://www.ietf.org/rfc/rfc1982.txt) ) by the first elements of each pair.
    </doc>

    <doc>
      2) The list-of-pairs is flattened into a list-of-words.
    </doc>

    <doc>
      3) Each word in the list is packed into ascending locations in memory with network byte
      ordering.
    </doc>

    <doc>
      4) The size in bytes, represented as a 16-bit network-byte-order unsigned value, is prepended.
    </doc>

    <doc>
      For instance, the example from above would be encoded:
    </doc>

    <doc type="picture">
      [(0, 2), (5, 6), (15, 15)]                           -- already sorted.
      [0, 2, 5, 6, 15, 15]                                 -- flattened.
      000000000000000200000005000000060000000F0000000F     -- bytes in hex
      0018000000000000000200000005000000060000000F0000000F -- bytes in hex,
                                                              length (24) prepended
    </doc>

    <doc type="picture" title="Wire Format">
                 +----= size OCTETs =----+
                 |                       |
        2 OCTETs |       8 OCTETs        |
      +----------+-----+-----------+-----+
      |   size   | .../|   range   |\... |
      +----------+---/ +-----------+ \---+
         uint16     / /             \ \
                   / /               \ \
                  / /                 \ \
                 / /                   \ \
                / 4 OCTETs       4 OCTETs \
               +-------------+-------------+
               |    lower    |    upper    |
               +-------------+-------------+
                 sequence-no   sequence-no
    </doc>

    <doc type="bnf">
       sequence-set = size *range
               size = uint16         ; length of variable portion in bytes

              range = lower upper   ; inclusive
              lower = sequence-no
              upper = sequence-no
    </doc>
  </type>

  <!--
    0xa0 - 0xaf: Variable length types - four byte length field (up to 4294967295 octets)
  -->

  <type name="vbin32" code="0xa0" variable-width="4"
        label="up to 4294967295 octets of opaque binary data">
    <doc>
      The vbin32 type encodes up to 4294967295 octets of opaque binary data. The number of octets is
      first encoded as a 32-bit unsigned integral value in network byte order. This is followed by
      the actual data.
    </doc>

    <doc type="picture" title="Wire Format">
        4 OCTETs   size OCTETs
      +----------+-------------+
      |   size   |   octets    |
      +----------+-------------+
         uint32
    </doc>

    <doc type="bnf">
             vbin32 = size octets
               size = uint32
             octets = 0*4294967295 OCTET ; size OCTETs
    </doc>
  </type>

  <type name="map" code="0xa8" variable-width="4" label="a mapping of keys to typed values">
    <doc>
      A map is a set of distinct keys where each key has an associated (type,value) pair. The triple
      of the key, type, and value, form an entry within a map. Each entry within a given map MUST
      have a distinct key. A map is encoded as a size in octets, a count of the number of entries,
      followed by the encoded entries themselves.
    </doc>

    <doc>
      An encoded map may contain up to (4294967295 - 4) octets worth of encoded entries. The size is
      encoded as a 32-bit unsigned integral value in network byte order equal to the number of
      octets worth of encoded entries plus 4. (The extra 4 octets is added for the entry count.) The
      size is then followed by the number of entries encoded as a 32-bit unsigned integral value in
      network byte order. Finally the entries are encoded sequentially.
    </doc>

    <doc>
      An entry is encoded as the key, followed by the type, and then the value. The key is always a
      string encoded as a str8. The type is a single octet that may contain any valid AMQP type
      code. The value is encoded according to the rules defined by the type code for that entry.
    </doc>

    <doc type="picture" title="Wire Format">
                 +------------= size OCTETs =-----------+
                 |                                      |
        4 OCTETs | 4 OCTETs                             |
      +----------+----------+-----+---------------+-----+
      |   size   |  count   | .../|     entry     |\... |
      +----------+----------+---/ +---------------+ \---+
         uint32     uint32     / /                 \ \
                              / /                   \ \
                             / /                     \ \
                            / /                       \ \
                           / /                         \ \
                          / k OCTETs   1 OCTET   n OCTETs \
                         +-----------+---------+-----------+
                         |    key    |  type   |   value   |
                         +-----------+---------+-----------+
                             str8                 *type*
    </doc>

    <doc type="bnf">
                map = size count *entry

               size = uint32             ; size of count and entries in octets
              count = uint32             ; number of entries in the map

              entry = key type value
                key = str8
               type = OCTET              ; type code of the value
              value = *OCTET             ; the encoded value
    </doc>
  </type>

  <type name="list" code="0xa9" variable-width="4" label="a series of consecutive type-value pairs">
    <doc>
      A list is an ordered sequence of (type, value) pairs. The (type, value) pair forms an item
      within the list.  The list may contain items of many distinct types. A list is encoded as a
      size in octets, followed by a count of the number of items, followed by the items themselves
      encoded in their defined order.
    </doc>

    <doc>
      An encoded list may contain up to (4294967295 - 4) octets worth of encoded items. The size is
      encoded as a 32-bit unsigned integral value in network byte order equal to the number of
      octets worth of encoded items plus 4. (The extra 4 octets is added for the item count.) The
      size is then followed by the number of items encoded as a 32-bit unsigned integral value in
      network byte order. Finally the items are encoded sequentially in their defined order.
    </doc>

    <doc>
      An item is encoded as the type followed by the value. The type is a single octet that may
      contain any valid AMQP type code. The value is encoded according to the rules defined by the
      type code for that item.
    </doc>

    <doc type="picture" title="Wire Format">
                 +---------= size OCTETs =---------+
                 |                                 |
        4 OCTETs | 4 OCTETs                        |
      +----------+----------+-----+----------+-----+
      |   size   |  count   | .../|   item   |\... |
      +----------+----------+---/ +----------+ \---+
         uint32     uint32     / /            \ \
                              / /              \ \
                             / 1 OCTET   n OCTETs \
                            +----------+-----------+
                            |   type   |   value   |
                            +----------+-----------+
                                          *type*
    </doc>

    <doc type="bnf">
               list = size count *item

               size = uint32            ; size of count and items in octets
              count = uint32            ; number of items in the list

               item = type value
               type = OCTET             ; type code of the value
              value = *OCTET            ; the encoded value
    </doc>
  </type>

  <type name="array" code="0xaa" variable-width="4"
        label="a defined length collection of values of a single type">
    <doc>
      An array is an ordered sequence of values of the same type. The array is encoded in as a size
      in octets, followed by a type code, then a count of the number values in the array, and
      finally the values encoded in their defined order.
    </doc>

    <doc>
      An encoded array may contain up to (4294967295 - 5) octets worth of encoded values. The size
      is encoded as a 32-bit unsigned integral value in network byte order equal to the number of
      octets worth of encoded values plus 5. (The extra 5 octets consist of 4 octets for the count
      of the number of values, and one octet to hold the type code for the items in the array.) The
      size is then followed by a single octet that may contain any valid AMQP type code. The type
      code is then followed by the number of values encoded as a 32-bit unsigned integral value in
      network byte order. Finally the values are encoded sequentially in their defined order
      according to the rules defined by the type code for the array.
    </doc>

    <doc type="picture" title="Wire Format">
        4 OCTETs   1 OCTET   4 OCTETs      (size - 5) OCTETs
      +----------+---------+----------+-------------------------+
      |   size   |  type   |  count   |         values          |
      +----------+---------+----------+-------------------------+
         uint32               uint32    *count* encoded *types*
    </doc>

    <doc type="bnf">
              array = size type count values

               size = uint32            ; size of type, count, and values in octets
               type = OCTET             ; the type of the encoded values
              count = uint32            ; number of items in the array

             values = 0*4294967290 OCTET ; (size - 5) OCTETs
    </doc>
  </type>

  <type name="struct32" code="0xab" variable-width="4" label="a coded struct with a 32-bit size">
    <doc>
      The struct32 type describes any coded struct with a 32-bit (4 octet) size. The type is
      restricted to be only coded structs with a 32-bit size, consequently the first six octets of
      any encoded value for this type MUST always contain the size, class-code, and struct-code in
      that order.
    </doc>

    <doc>
      The size is encoded as a 32-bit unsigned integral value in network byte order that is equal to
      the size of the encoded field-data, packing-flags, class-code, and struct-code. The class-code
      is a single octet that may be set to any valid class code. The struct-code is a single octet
      that may be set to any valid struct code within the given class-code.
    </doc>

    <doc>
      The first six octets are then followed by the packing flags and encoded field data. The
      presence and quantity of packing-flags, as well as the specific fields are determined by the
      struct definition identified with the encoded class-code and struct-code.
    </doc>

    <doc type="picture" title="Wire Format">
        4 OCTETs    1 OCTET       1 OCTET     pack-width OCTETs    n OCTETs
      +----------+------------+-------------+-------------------+------------+
      |   size   | class-code | struct-code |   packing-flags   | field-data |
      +----------+------------+-------------+-------------------+------------+
         uint32

                          n = (size - 2 - pack-width)
    </doc>

    <doc type="bnf">
           struct32 = size class-code struct-code packing-flags field-data

               size = uint32

         class-code = OCTET     ; zero for top-level structs
        struct-code = OCTET     ; together with class-code identifies the struct
                                ; definition which determines the pack-width and
                                ; fields

      packing-flags = 0*4 OCTET ; pack-width OCTETs

         field-data = *OCTET    ; (size - 2 - pack-width) OCTETs
    </doc>
  </type>

  <!--
    0xb0 - 0xbf: Reserved
  -->

  <!--
    0xc0 - 0xcf:Fixed width types - 5 octets
  -->

  <type name="bin40" code="0xc0" fixed-width="5" label="five octets of unspecified binary encoding">
    <doc>
      The bin40 type consists of five consecutive octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET      1 OCTET      1 OCTET      1 OCTET
      +-----------+-----------+-------------+------------+------------+
      | octet-one | octet-two | octet-three | octet-four | octet-five |
      +-----------+-----------+-------------+------------+------------+
    </doc>

    <doc type="bnf">
              bin40 = 5 OCTET
    </doc>
  </type>

  <type name="dec32" code="0xc8" fixed-width="5"
        label="32-bit decimal value (e.g. for use in financial values)">
    <doc>
      The dec32 type is decimal value with a variable number of digits following the decimal point.
      It is encoded as an 8-bit unsigned integral value representing the number of decimal places.
      This is followed by the signed integral value encoded using a 32-bit two's complement
      representation in network byte order.
    </doc>

    <doc>
      The former value is referred to as the exponent of the divisor. The latter value is the
      mantissa. The decimal value is given by: mantissa / 10^exponent.
    </doc>

    <doc type="picture" title="Wire Format">
        1 OCTET    4 OCTETs
      +----------+----------+
      | exponent | mantissa |
      +----------+----------+
         uint8      int32
    </doc>

    <doc type="bnf">
              dec32 = exponent mantissa
           exponent = uint8
           mantissa = int32
    </doc>
  </type>

  <!--
    0xd0 - 0xdf: Fixed width types - 9 octets
  -->

  <type name="bin72" code="0xd0" fixed-width="9"
        label="nine octets of unspecified binary encoding">
    <doc>
      The bin72 type consists of nine consecutive octets of opaque binary data.
    </doc>

    <doc type="picture" title="Wire Format">
         1 OCTET     1 OCTET            1 OCTET      1 OCTET
      +-----------+-----------+-----+-------------+------------+
      | octet-one | octet-two | ... | octet-eight | octet-nine |
      +-----------+-----------+-----+-------------+------------+
    </doc>

    <doc type="bnf">
              bin64 = 9 OCTET
    </doc>
  </type>

  <type name="dec64" code="0xd8" fixed-width="9"
        label="64-bit decimal value (e.g. for use in financial values)">
    <doc>
      The dec64 type is decimal value with a variable number of digits following the decimal point.
      It is encoded as an 8-bit unsigned integral value representing the number of decimal places.
      This is followed by the signed integral value encoded using a 64-bit two's complement
      representation in network byte order.
    </doc>

    <doc>
      The former value is referred to as the exponent of the divisor. The latter value is the
      mantissa. The decimal value is given by: mantissa / 10^exponent.
    </doc>

    <doc type="picture" title="Wire Format">
        1 OCTET    8 OCTETs
      +----------+----------+
      | exponent | mantissa |
      +----------+----------+
         uint8      int64
    </doc>

    <doc type="bnf">
              dec64 = exponent mantissa
           exponent = uint8
           mantissa = int64
    </doc>
  </type>

  <!--
    0xe0 - 0xef: Reserved
  -->

  <!--
    0xf0 - 0xff: Zero-length types
  -->

  <type name="void" code="0xf0" fixed-width="0" label="the void type">
    <doc>
      The void type is used within tagged data structures such as maps and lists to indicate an
      empty value. The void type has no value and is encoded as an empty sequence of octets.
    </doc>
  </type>

  <type name="bit" code="0xf1" fixed-width="0" label="presence indicator">
    <doc>
      The bit type is used to indicate that a packing flag within a packed struct is being used to
      represent a boolean value based on the presence of an empty value. The bit type has no value
      and is encoded as an empty sequence of octets.
    </doc>
  </type>

  <!--
    ======================================================
    ==       CONSTANTS
    ======================================================
  -->

  <!-- Protocol constants -->

  <constant name="MIN-MAX-FRAME-SIZE" value="4096" label="The minimum size (in bytes) which can be
    agreed upon as the maximum frame size.">
    <doc>
      During the initial connection negotiation, the two peers must agree upon a maximum frame size.
      This constant defines the minimum value to which the maximum frame size can be set.  By
      defining this value, the peers can guarantee that they can send frames of up to this size
      until they have agreed a definitive maximum frame size for that connection.
    </doc>
  </constant>

  <!--
    ======================================================
    ==       DOMAIN TYPES
    ======================================================
  -->

  <!-- Segment types -->

  <domain name="segment-type" type="uint8" label="valid values for the frame type indicator.">
    <doc>
      Segments are defined in <xref ref="specification.transport.assemblies_segments_and_frames"/>.
      The segment domain defines the valid values that may be used for the segment indicator within
      the frame header.
    </doc>

    <enum>
      <choice name="control" value="0">
        <doc>
          The frame type indicator for Control segments (see <xref
          ref="specification.formal_notation.controls"/>).
        </doc>
      </choice>
      <choice name="command" value="1">
        <doc>
          The frame type indicator for Command segments (see <xref
            ref="specification.formal_notation.commands"/>).
        </doc>
      </choice>
      <choice name="header" value="2" >
        <doc>
          The frame type indicator for Header segments (see <xref
            ref="specification.formal_notation.segments.header"/>).
        </doc>
      </choice>
      <choice name="body" value="3" >
        <doc>
          The frame type indicator for Body segments (see <xref
            ref="specification.formal_notation.segments.body"/>).
        </doc>
      </choice>
    </enum>
  </domain>

  <!-- Tracks -->

  <domain name="track" type="uint8" label="Valid values for transport level tracks">
    <doc> Tracks are defined in <xref ref="specification.transport.channels_and_tracks"/>.  The
      track domain defines the valid values that may used for the track indicator within the frame
      header</doc>
    <enum>
      <choice name="control" value="0">
        <doc>
          The track used for all controls.  All controls defined in this specification MUST be sent
          on track 0.
        </doc>
      </choice>
      <choice name="command" value="1">
        <doc>
          The track used for all commands.  All commands defined in this specification MUST be sent
          on track 1.
        </doc>
      </choice>
    </enum>
  </domain>


  <domain name="str16-array" type="array" label="An array of values of type str16.">
    <doc>
      An array of values of type str16.
    </doc>
  </domain>



  <!-- == Class: connection ==================================================================== -->

  <class name="connection" code="0x1" label="work with connections">
    <doc>
      The connection class provides controls for a client to establish a network connection to a
      server, and for both peers to operate the connection thereafter.
    </doc>

    <doc type="grammar">
      connection        = open-connection
                          *use-connection
                          close-connection
      open-connection   = C:protocol-header
                          S:START C:START-OK
                          *challenge
                          S:TUNE C:TUNE-OK
                          C:OPEN S:OPEN-OK | S:REDIRECT
      challenge         = S:SECURE C:SECURE-OK
      use-connection    = *channel
      close-connection  = C:CLOSE S:CLOSE-OK
                        / S:CLOSE C:CLOSE-OK
    </doc>

    <role name="server" implement="MUST" />
    <role name="client" implement="MUST" />

    <domain name="close-code" type="uint16" label="code used in the connection.close control to
      indicate reason for closure">
      <enum>
        <choice name="normal" value="200">
          <doc>
            The connection closed normally.
          </doc>
        </choice>

        <choice name="connection-forced" value="320">
          <doc>
            An operator intervened to close the connection for some reason. The client may retry at
            some later date.
          </doc>
        </choice>

        <choice name="invalid-path" value="402">
          <doc>
            The client tried to work with an unknown virtual host.
          </doc>
        </choice>

        <choice name="framing-error" value="501">
          <doc>
            A valid frame header cannot be formed from the incoming byte stream.
          </doc>
        </choice>
      </enum>
    </domain>

    <domain name="amqp-host-url" type="str16" label="URL for identifying an AMQP Server">
      <doc>
        The amqp-url domain defines a format for identifying an AMQP Server.  It is used to provide
        alternate hosts in the case where a client has to reconnect because of failure, or because
        the server requests the client to do so upon initial connection.
      </doc>
      <doc type="bnf"><![CDATA[
        amqp_url          = "amqp:" prot_addr_list
        prot_addr_list    = [prot_addr ","]* prot_addr
        prot_addr         = tcp_prot_addr | tls_prot_addr

        tcp_prot_addr     = tcp_id tcp_addr
        tcp_id            = "tcp:" | ""
        tcp_addr          = [host [":" port] ]
        host              = <as per http://www.ietf.org/rfc/rfc3986.txt>
        port              = number]]>
      </doc>
    </domain>

    <domain name="amqp-host-array" type="array" label="An array of values of type amqp-host-url">
      <doc>
        Used to provide a list of alternate hosts.
      </doc>
    </domain>

    <!-- - Control: connection.start - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="start" code="0x1" label="start connection negotiation">
      <doc>
        This control starts the connection negotiation process by telling the client the supported
        security mechanisms and locales from which the client can choose.
      </doc>

      <rule name="protocol-name">
        <doc>
          If the server cannot support the protocol specified in the protocol header, it MUST close
          the socket connection without sending any response control.
        </doc>
        <doc type="scenario">
          The client sends a protocol header containing an invalid protocol name. The server must
          respond by closing the connection.
        </doc>
      </rule>

      <rule name="client-support">
        <doc>
          If the client cannot handle the protocol version suggested by the server it MUST close the
          socket connection.
        </doc>
        <doc type="scenario">
          The server sends a protocol version that is lower than any valid implementation, e.g. 0.1.
          The client must respond by closing the connection.
        </doc>
      </rule>

      <implement role="client" handle="MUST" />

      <response name="start-ok" />

      <field name="server-properties" type="map" label="server properties">
        <rule name="required-fields">
          <doc>
            The properties SHOULD contain at least these fields: "host", specifying the server host
            name or address, "product", giving the name of the server product, "version", giving the
            name of the server version, "platform", giving the name of the operating system,
            "copyright", if appropriate, and "information", giving other general information.
          </doc>
          <doc type="scenario">
            Client connects to server and inspects the server properties. It checks for the presence
            of the required fields.
          </doc>
        </rule>
      </field>

      <field name="mechanisms" type="str16-array" label="available security mechanisms"
             required="true">
        <doc>
          A list of the security mechanisms that the server supports.
        </doc>
      </field>

      <field name="locales" type="str16-array" label="available message locales" required="true">
        <doc>
          A list of the message locales that the server supports. The locale defines the language in
          which the server will send reply texts.
        </doc>

        <rule name="required-support">
          <doc>
            The server MUST support at least the en_US locale.
          </doc>
          <doc type="scenario">
            Client connects to server and inspects the locales field. It checks for the presence of
            the required locale(s).
          </doc>
        </rule>
      </field>
    </control>

    <!-- - Control: connection.start-ok  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="start-ok" code="0x2" label="select security mechanism and locale">
      <doc>
        This control selects a SASL security mechanism.
      </doc>

      <implement role="server" handle="MUST" />

      <field name="client-properties" type="map" label="client properties">
        <rule name="required-fields">
          <!-- This rule is not testable from the client side -->
          <doc>
            The properties SHOULD contain at least these fields: "product", giving the name of the
            client product, "version", giving the name of the client version, "platform", giving the
            name of the operating system, "copyright", if appropriate, and "information", giving
            other general information.
          </doc>
        </rule>
      </field>

      <field name="mechanism" type="str8" label="selected security mechanism" required="true">
        <doc>
          A single security mechanisms selected by the client, which must be one of those specified
          by the server.
        </doc>

        <rule name="security">
          <doc>
            The client SHOULD authenticate using the highest-level security profile it can handle
            from the list provided by the server.
          </doc>
        </rule>

        <rule name="validity">
          <doc>
            If the mechanism field does not contain one of the security mechanisms proposed by the
            server in the Start control, the server MUST close the connection without sending any
            further data.
          </doc>
          <doc type="scenario">
            Client connects to server and sends an invalid security mechanism. The server must
            respond by closing the connection (a socket close, with no connection close
            negotiation).
          </doc>
        </rule>
      </field>

      <field name="response" type="vbin32" label="security response data" required="true">
        <doc>
          A block of opaque data passed to the security mechanism. The contents of this data are
          defined by the SASL security mechanism.
        </doc>
      </field>

      <field name="locale" type="str8" label="selected message locale" required="true">
        <doc>
          A single message locale selected by the client, which must be one of those specified by
          the server.
        </doc>
      </field>
    </control>

    <!-- - Control: connection.secure  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="secure" code="0x3" label="security mechanism challenge">
      <doc>
        The SASL protocol works by exchanging challenges and responses until both peers have
        received sufficient information to authenticate each other. This control challenges the
        client to provide more information.
      </doc>

      <implement role="client" handle="MUST" />

      <response name="secure-ok" />

      <field name="challenge" type="vbin32" label="security challenge data" required="true">
        <doc>
          Challenge information, a block of opaque binary data passed to the security mechanism.
        </doc>
      </field>
    </control>

    <!-- - Control: connection.secure-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="secure-ok" code="0x4" label="security mechanism response">
      <doc>
        This control attempts to authenticate, passing a block of SASL data for the security
        mechanism at the server side.
      </doc>

      <implement role="server" handle="MUST" />

      <field name="response" type="vbin32" label="security response data" required="true">
        <doc>
          A block of opaque data passed to the security mechanism. The contents of this data are
          defined by the SASL security mechanism.
        </doc>
      </field>
    </control>

    <!-- - Control: connection.tune  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="tune" code="0x5" label="propose connection tuning parameters">
      <doc>
        This control proposes a set of connection configuration values to the client. The client can
        accept and/or adjust these.
      </doc>

      <implement role="client" handle="MUST" />

      <response name="tune-ok" />

      <field name="channel-max" type="uint16" label="proposed maximum channels">
        <doc>
          The maximum total number of channels that the server allows per connection. If this is not
          set it means that the server does not impose a fixed limit, but the number of allowed
          channels may be limited by available server resources.
        </doc>
      </field>

      <field name="max-frame-size" type="uint16" label="proposed maximum frame size">
        <doc>
          The largest frame size that the server proposes for the connection. The client can
          negotiate a lower value. If this is not set means that the server does not impose any
          specific limit but may reject very large frames if it cannot allocate resources for them.
        </doc>

        <rule name="minimum">
          <doc>
            Until the max-frame-size has been negotiated, both peers MUST accept frames of up to
            MIN-MAX-FRAME-SIZE octets large, and the minimum negotiated value for max-frame-size is
            also MIN-MAX-FRAME-SIZE.
          </doc>
          <doc type="scenario">
            Client connects to server and sends a large properties field, creating a frame of
            MIN-MAX-FRAME-SIZE octets. The server must accept this frame.
          </doc>
        </rule>
      </field>

      <field name="heartbeat-min" type="uint16" label="the minimum supported heartbeat delay">
        <doc>
          The minimum delay, in seconds, of the connection heartbeat supported by the server. If
          this is not set it means the server does not support sending heartbeats.
        </doc>
      </field>

      <field name="heartbeat-max" type="uint16" label="the maximum supported heartbeat delay">
        <doc>
          The maximum delay, in seconds, of the connection heartbeat supported by the server. If
          this is not set it means the server has no maximum.
        </doc>

        <rule name="permitted-range">
          <doc>
            The heartbeat-max value must be greater than or equal to the value supplied in the
            heartbeat-min field.
          </doc>
        </rule>

        <rule name="no-heartbeat-min">
          <doc>
            If no heartbeat-min is supplied, then the heartbeat-max field MUST remain empty.
          </doc>
        </rule>
      </field>
    </control>

    <!-- - Control: connection.tune-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="tune-ok" code="0x6" label="negotiate connection tuning parameters">
      <doc>
        This control sends the client's connection tuning parameters to the server. Certain fields
        are negotiated, others provide capability information.
      </doc>

      <implement role="server" handle="MUST" />

      <field name="channel-max" type="uint16" label="negotiated maximum channels" required="true">
        <doc>
          The maximum total number of channels that the client will use per connection.
        </doc>

        <rule name="upper-limit">
          <doc>
            If the client specifies a channel max that is higher than the value provided by the
            server, the server MUST close the connection without attempting a negotiated close. The
            server may report the error in some fashion to assist implementers.
          </doc>

        </rule>

        <rule name="available-channels">
          <doc>
            If the client agrees to a channel-max of N channels, then the channels available for
            communication between client and server are precisely the channels numbered 0 to (N-1).
          </doc>
        </rule>
      </field>

      <field name="max-frame-size" type="uint16" label="negotiated maximum frame size">
        <doc>
          The largest frame size that the client and server will use for the connection. If it is
          not set means that the client does not impose any specific limit but may reject very large
          frames if it cannot allocate resources for them. Note that the max-frame-size limit
          applies principally to content frames, where large contents can be broken into frames of
          arbitrary size.
        </doc>

        <rule name="minimum">
          <doc>
            Until the max-frame-size has been negotiated, both peers MUST accept frames of up to
            MIN-MAX-FRAME-SIZE octets large, and the minimum negotiated value for max-frame-size is
            also MIN-MAX-FRAME-SIZE.
          </doc>
        </rule>

        <rule name="upper-limit">
          <doc>
            If the client specifies a max-frame-size that is higher than the value provided by the
            server, the server MUST close the connection without attempting a negotiated close. The
            server may report the error in some fashion to assist implementers.
          </doc>
        </rule>

        <rule name="max-frame-size">
          <doc>
            A peer MUST NOT send frames larger than the agreed-upon size. A peer that receives an
            oversized frame MUST close the connection with the framing-error close-code.
          </doc>
        </rule>
      </field>

      <field name="heartbeat" type="uint16" label="negotiated heartbeat delay">
        <doc>
          The delay, in seconds, of the connection heartbeat chosen by the client. If it is not set
          it means the client does not want a heartbeat.
        </doc>

        <rule name="permitted-range">
          <doc>
            The chosen heartbeat MUST be in the range supplied by the heartbeat-min and
            heartbeat-max fields of connection.tune.
          </doc>
        </rule>

        <rule name="no-heartbeat-min">
          <doc>
            The heartbeat field MUST NOT be set if the heartbeat-min field of connection.tune was
            not set by the server.
          </doc>
        </rule>
      </field>
    </control>

    <!-- - Control: connection.open  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="open" code="0x7" label="open connection to virtual host">
      <doc>
        This control opens a connection to a virtual host, which is a collection of resources, and
        acts to separate multiple application domains within a server. The server may apply
        arbitrary limits per virtual host, such as the number of each type of entity that may be
        used, per connection and/or in total.
      </doc>

      <implement role="server" handle="MUST" />

      <response name="open-ok" />
      <response name="redirect" />

      <field name="virtual-host" type="str8" label="virtual host name"  required="true">
        <doc>
          The name of the virtual host to work with.
        </doc>

        <rule name="separation">
          <doc>
            If the server supports multiple virtual hosts, it MUST enforce a full separation of
            exchanges, queues, and all associated entities per virtual host. An application,
            connected to a specific virtual host, MUST NOT be able to access resources of another
            virtual host.
          </doc>
        </rule>

        <rule name="security">
          <doc>
            The server SHOULD verify that the client has permission to access the specified virtual
            host.
          </doc>
        </rule>
      </field>

      <field name="capabilities" type="str16-array" label="required capabilities">
        <doc>
          The client can specify zero or more capability names. The server can use this to determine
          how to process the client's connection request.
        </doc>
      </field>

      <field name="insist" type="bit" label="insist on connecting to server">
        <doc>
          In a configuration with multiple collaborating servers, the server may respond to a
          connection.open control with a Connection.Redirect. The insist option tells the server
          that the client is insisting on a connection to the specified server.
        </doc>
        <rule name="behavior">
          <doc>
            When the client uses the insist option, the server MUST NOT respond with a
            Connection.Redirect control. If it cannot accept the client's connection request it
            should respond by closing the connection with a suitable reply code.
          </doc>
        </rule>
      </field>
    </control>

    <!-- - Control: connection.open-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="open-ok" code="0x8" label="signal that connection is ready">
      <doc>
        This control signals to the client that the connection is ready for use.
      </doc>

      <implement role="client" handle="MUST" />

      <field name="known-hosts" type="amqp-host-array" label="alternate hosts which may be used in
        the case of failure">
          <doc>
            Specifies an array of equivalent or alternative hosts that the server knows about, which
            will normally include the current server itself. Each entry in the array will be in the
            form of an IP address or DNS name, optionally followed by a colon and a port number.
            Clients can cache this information and use it when reconnecting to a server after a
            failure. This field may be empty.
          </doc>
      </field>
    </control>

    <!-- - Control: connection.redirect  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="redirect" code="0x9" label="redirects client to other server">
      <doc>
        This control redirects the client to another server, based on the requested virtual host
        and/or capabilities.
      </doc>

      <rule name="usage">
        <doc>
          When getting the connection.redirect control, the client SHOULD reconnect to the host
          specified, and if that host is not present, to any of the hosts specified in the
          known-hosts list.
        </doc>
      </rule>

      <implement role="client" handle="MUST" />

      <field name="host" type="amqp-host-url" label="server to connect to" required="true">
        <doc>
          Specifies the server to connect to.
        </doc>
      </field>

      <field name="known-hosts" type="amqp-host-array" label="alternate hosts to try in case of
        failure">
        <doc>
          An array of equivalent or alternative hosts that the server knows about.
        </doc>
      </field>
    </control>

    <!-- - Control: connection.heartbeat - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="heartbeat" code="0xa" label="indicates connection is still alive">
      <doc>
        The heartbeat control may be used to generate artificial network traffic when a connection
        is idle. If a connection is idle for more than twice the negotiated heartbeat delay, the
        peers MAY be considered disconnected.
      </doc>
    </control>

    <!-- - Control: connection.close - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="close" code="0xb" label="request a connection close">
      <doc>
        This control indicates that the sender wants to close the connection. The reason for close
        is indicated with the reply-code and reply-text. The channel this control is sent on MAY be
        used to indicate which channel caused the connection to close.
      </doc>

      <implement role="client" handle="MUST" />
      <implement role="server" handle="MUST" />

      <response name="close-ok" />

      <field name="reply-code" type="close-code" label="the numeric reply code"
        required="true">
        <doc>
          Indicates the reason for connection closure.
        </doc>
      </field>
      <field name="reply-text" type="str8" label="the localized reply text">
        <doc>
          This text can be logged as an aid to resolving issues.
        </doc>
      </field>
    </control>

    <!-- - Control: connection.close-ok  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <control name="close-ok" code="0xc" label="confirm a connection close">
      <doc>
        This control confirms a connection.close control and tells the recipient that it is safe to
        release resources for the connection and close the socket.
      </doc>

      <rule name="reporting">
        <doc>
          A peer that detects a socket closure without having received a Close-Ok handshake control
          SHOULD log the error.
        </doc>
      </rule>

      <implement role="client" handle="MUST" />
      <implement role="server" handle="MUST" />
    </control>

  </class>

  <!-- == Class: session ======================================================================= -->

  <class name="session" code="0x2" label="session controls">
    <doc>
      A session is a named interaction between two peers. Session names are chosen by the upper
      layers and may be used indefinitely. The model layer may associate long-lived or durable state
      with a given session name. The session layer provides transport of commands associated with
      this interaction.
    </doc>

    <doc>
      The controls defined within this class are specified in terms of the "sender" of commands and
      the "receiver" of commands. Since both client and server send and receive commands, the
      overall session dialog is symmetric, however the semantics of the session controls are defined
      in terms of a single sender/receiver pair, and it is assumed that the client and server will
      each contain both a sender and receiver implementation.
    </doc>

    <rule name="attachment">
      <doc>
        The transport MUST be attached in order to use any control other than "attach", "attached",
        "detach", or "detached". A peer receiving any other control on a detached transport MUST
        discard it and send a session.detached with the "not-attached" reason code.
      </doc>
    </rule>

    <role name="server" implement="MUST" />
    <role name="client" implement="MUST" />

    <role name="sender" implement="MUST">
      <doc>
        The sender of commands.
      </doc>
    </role>
    <role name="receiver" implement="MUST">
      <doc>
        The receiver of commands.
      </doc>
    </role>

    <domain name="name" type="vbin16" label="opaque session name">
      <doc>
        The session name uniquely identifies an interaction between two peers. It is scoped to a
        given authentication principal.
      </doc>
    </domain>

    <domain name="detach-code" type="uint8" label="reason for detach">
      <enum>
        <choice name="normal" value="0">
          <doc>
            The session was detached by request.
          </doc>
        </choice>
        <choice name="session-busy" value="1">
          <doc>
            The session is currently attached to another transport.
          </doc>
        </choice>
        <choice name="transport-busy" value="2">
          <doc>
            The transport is currently attached to another session.
          </doc>
        </choice>
        <choice name="not-attached" value="3">
          <doc>
            The transport is not currently attached to any session.
          </doc>
        </choice>
        <choice name="unknown-ids" value="4">
          <doc>
            Command data was received prior to any use of the command-point control.
          </doc>
        </choice>
      </enum>
    </domain>

    <domain name="commands" type="sequence-set" label="identifies a set of commands">
    </domain>

    <struct name="header" size="1" pack="1">
      <doc>
        The session header appears on commands after the class and command id, but prior to command
        arguments.
      </doc>

      <field name="sync" type="bit" label="request notification of completion">
        <doc>
          Request notification of completion for this command.
        </doc>
      </field>
    </struct>

    <struct name="command-fragment" size="0" pack="0" label="byte-ranges within a set of commands">

      <field name="command-id" type="sequence-no" required="true">

      </field>
      <field name="byte-ranges" type="byte-ranges" required="true">

      </field>
    </struct>

    <domain name="command-fragments" type="array" label="an array of values of type
      command-fragment"/>

    <control name="attach" code="0x1" label="attach to the named session">
      <doc>
        Requests that the current transport be attached to the named session. Success or failure
        will be indicated with an attached or detached response. This control is idempotent.
      </doc>

      <rule name="one-transport-per-session">
        <doc>
          A session MUST NOT be attached to more than one transport at a time.
        </doc>
      </rule>

      <rule name="one-session-per-transport">
        <doc>
          A transport MUST NOT be attached to more than one session at a time.
        </doc>
      </rule>

      <rule name="idempotence">
        <doc>
          Attaching a session to its current transport MUST succeed and result in an attached
          response.
        </doc>
      </rule>

      <rule name="scoping">
        <doc>
          Attachment to the same session name from distinct authentication principals MUST succeed.
        </doc>
      </rule>

      <implement role="server" handle="MUST" />
      <implement role="client" handle="MAY" />

      <response name="attached"/>
      <response name="detached"/>

      <field name="name" type="name" label="the session name" required="true">
        <doc>
          Identifies the session to be attached to the current transport.
        </doc>
      </field>

      <field name="force" type="bit" label="force attachment to a busy session">
        <doc>
          If set then a busy session will be forcibly detached from its other transport and
          reattached to the current transport.
        </doc>
      </field>
    </control>

    <control name="attached" code="0x2" label="confirm attachment to the named session">
      <doc>
        Confirms successful attachment of the transport to the named session.
      </doc>

      <implement role="server" handle="MUST" />
      <implement role="client" handle="MUST" />

      <field name="name" type="name" label="the session name" required="true">
        <doc>
          Identifies the session now attached to the current transport.
        </doc>
      </field>
    </control>

    <control name="detach" code="0x3" label="detach from the named session">
      <doc>
        Detaches the current transport from the named session.
      </doc>

      <implement role="server" handle="MUST" />
      <implement role="client" handle="MUST" />

      <response name="detached"/>

      <field name="name" type="name" label="the session name" required="true">
        <doc>
          Identifies the session to detach.
        </doc>
      </field>
    </control>

    <control name="detached" code="0x4" label="confirm detachment from the named session">
      <doc>
        Confirms detachment of the current transport from the named session.
      </doc>

      <implement role="server" handle="MUST" />
      <implement role="client" handle="MUST" />

      <field name="name" type="name" label="the session name" required="true">
        <doc>
          Identifies the detached session.
        </doc>
      </field>
      <field name="code" type="detach-code" label="the reason for detach" required="true">
        <doc>
          Identifies the reason for detaching from the named session.
        </doc>
      </field>
    </control>

    <!--
        Execution state is the set of confirmed, and completed incoming commands, as well as the set
        of outgoing in-doubt commands held for replay.
    -->

    <control name="request-timeout" code="0x5" label="requests the execution timeout be changed">
      <doc>
        This control may be sent by either the sender or receiver of commands. It requests that the
        execution timeout be changed. This is the minimum amount of time that a peer must preserve
        execution state for a detached session.
      </doc>

      <rule name="maximum-granted-timeout">
        <doc>
          The handler of this request MUST set his timeout to the maximum allowed value less than or
          equal to the requested timeout, and MUST convey the chosen timeout in the response.
        </doc>
      </rule>

      <implement role="sender" handle="MUST" />
      <implement role="receiver" handle="MUST" />

      <response name="timeout"/>

      <field name="timeout" type="uint32" label="the requested timeout">
        <doc>
          The requested timeout for execution state in seconds. If not set, this control requests
          that execution state is preserved indefinitely.
        </doc>
      </field>
    </control>

    <control name="timeout" code="0x6" label="the granted timeout">
      <doc>
        This control may be sent by the either the sender or receiver of commands. It is a
        one-to-one reply to the request-timeout control that indicates the granted timeout for
        execution state.
      </doc>

      <implement role="sender" handle="MUST" />
      <implement role="receiver" handle="MUST" />

      <field name="timeout" type="uint32" label="the execution timeout">
        <doc>
          The timeout for execution state. If not set, then execution state is preserved
          indefinitely.
        </doc>
      </field>
    </control>

    <control name="command-point" code="0x7"
             label="the command id and byte offset of subsequent data">
      <doc>
        This control is sent by the sender of commands and handled by the receiver of commands. This
        establishes the sequence numbers associated with all subsequent command data sent from the
        sender to the receiver. The subsequent command data will be numbered starting with the
        values supplied in this control and proceeding sequentially. This must be used at least once
        prior to sending any command data on newly attached transports.
      </doc>

      <rule name="newly-attached-transports">
        <doc>
          If command data is sent on a newly attached transport the session MUST be detached with an
          "unknown-id" reason-code.
        </doc>
      </rule>

      <rule name="zero-offset">
        <doc>
          If the offset is zero, the next data frame MUST have the first-frame and first-segment
          flags set. Violation of this is a framing error.
        </doc>
      </rule>

      <rule name="nonzero-offset">
        <doc>
          If the offset is nonzero, the next data frame MUST NOT have both the first-frame and
          first-segment flag set. Violation of this is a framing error.
        </doc>
      </rule>

      <implement role="receiver" handle="MUST" />

      <field name="command-id" type="sequence-no" label="the command-id of the next command"
        required="true"/>
      <field name="command-offset" type="uint64" label="the byte offset within the command"
        required="true"/>
    </control>

    <control name="expected" code="0x8" label="informs the peer of expected commands">
      <doc>
        This control is sent by the receiver of commands and handled by the sender of commands. It
        informs the sender of what commands and command fragments are expected at the receiver.
        This control is only sent in response to a flush control with the expected flag set.  The
        expected control is never sent spontaneously.
      </doc>

      <rule name="include-next-command">
        <doc>
          The set of expected commands MUST include the next command after the highest seen command.
        </doc>
      </rule>

      <rule name="commands-empty-means-new-session">
        <doc>
          The set of expected commands MUST have zero elements if and only if the sender holds no
          execution state for the session (i.e. it is a new session).
        </doc>
      </rule>

      <rule name="no-overlaps">
        <doc>
          If a command-id appears in the commands field, it MUST NOT appear in the fragments field.
        </doc>
      </rule>

      <rule name="minimal-fragments">
        <doc>
          When choice is permitted, a command MUST appear in the commands field rather than the
          fragments field.
        </doc>
      </rule>

      <implement role="sender" handle="MUST" />

      <field name="commands" type="commands" label="expected commands" required="true"/>
      <field name="fragments" type="command-fragments" label="expected fragments" />
    </control>

    <control name="confirmed" code="0x9" label="notifies of confirmed commands">
      <doc>
        This control is sent by the receiver of commands and handled by the sender of commands. This
        sends the set of commands that will definitely be completed by this peer to the sender. This
        excludes commands known by the receiver to be considered confirmed or complete at the
        sender.
      </doc>
      <doc>
        This control must be sent if the partner requests the set of confirmed commands using the
        session.flush control with the confirmed flag set.
      </doc>
      <doc>
        This control may be sent spontaneously.  One reason for separating confirmation from
        completion is for large persistent messages, where the receipt (and storage to a durable
        store) of part of the message will result in less data needing to be replayed in the case of
        transport failure during transmission.
      </doc>
      <doc>
        A simple implementation of an AMQP client or server may be implemented to take no action on
        receipt of session.confirmed controls, and take action only when receiving
        session.completed controls.
      </doc>
      <doc>
        A simple implementation of an AMQP client or server may be implemented such that it never
        spontaneously sends session.confirmed and that when requested for the set of confirmed
        commands (via the session.flush control) it responds with the same set of commands as it
        would to when the set of completed commands was requested (trivially all completed commands
        are confirmed).
      </doc>

      <rule name="durability">
        <doc>
          If a command has durable implications, it MUST NOT be confirmed until the fact of the
          command has been recorded on durable media.
        </doc>
      </rule>

      <rule name="no-overlaps">
        <doc>
          If a command-id appears in the commands field, it MUST NOT appear in the fragments field.
        </doc>
      </rule>

      <rule name="minimal-fragments">
        <doc>
          When choice is permitted, a command MUST appear in the commands field rather than the
          fragments field.
        </doc>
      </rule>

      <implement role="sender" handle="MUST" />

      <field name="commands" type="commands" label="entirely confirmed commands">
        <rule name="exclude-known-complete">
          <doc>
            Command-ids included in prior known-complete replies MUST be excluded from the set of
            all confirmed commands.
          </doc>
        </rule>
      </field>
      <field name="fragments" type="command-fragments" label="partially confirmed commands"/>
    </control>

    <control name="completed" code="0xa" label="notifies of command completion">
      <doc>
        This control is sent by the receiver of commands, and handled by the sender of commands. It
        informs the sender of all commands completed by the receiver. This excludes commands known
        by the receiver to be considered complete at the sender.
      </doc>

      <rule name="known-completed-reply">
        <doc>
          The sender MUST eventually reply with a known-completed set that covers the completed ids.
        </doc>
      </rule>

      <rule name="delayed-reply">
        <doc>
          The known-complete reply MAY be delayed at the senders discretion if the timely-reply
          field is not set.
        </doc>
      </rule>

      <rule name="merged-reply">
        <doc>
          Multiple replies may be merged by sending a single known-completed that includes the union
          of the merged command-id sets.
        </doc>
      </rule>

      <implement role="sender" handle="MUST" />

      <field name="commands" type="commands" label="completed commands">
        <doc>
          The ids of all completed commands. This excludes commands known by the receiver to be
          considered complete at the sender.
        </doc>

        <rule name="completed-implies-confirmed">
          <doc>
            The sender MUST consider any completed commands to also be confirmed.
          </doc>
        </rule>

        <rule name="exclude-known-complete">
          <doc>
            Command-ids included in prior known-complete replies MUST be excluded from the set of
            all completed commands.
          </doc>
        </rule>
      </field>
      <field name="timely-reply" type="bit">
        <doc>
          If set, the sender is no longer free to delay the known-completed reply.
        </doc>
      </field>
    </control>

    <control name="known-completed" code="0xb" label="Inform peer of which commands are known to be
      completed">
      <doc>
        This control is sent by the sender of commands, and handled by the receiver of commands. It
        is sent in reply to one or more completed controls from the receiver. It informs the
        receiver that commands are known to be completed by the sender.
      </doc>

      <rule name="stateless">
        <doc>
          The sender need not keep state to generate this reply. It is sufficient to reply to any
          completed control with an exact echo of the completed ids.
        </doc>
      </rule>

      <implement role="receiver" handle="MUST" />

      <field name="commands" type="commands" label="commands known to be complete">
        <doc>
          The set of completed commands for one or more session.completed controls.
        </doc>

        <rule name="known-completed-implies-known-confirmed">
          <doc>
            The receiver MUST treat any of the specified commands to be considered by the sender as
            confirmed as well as completed.
          </doc>
        </rule>
      </field>
    </control>

    <control name="flush" code="0xc" label="requests a session.completed">
      <doc>
        This control is sent by the sender of commands and handled by the receiver of commands. It
        requests that the receiver produce the indicated command sets. The receiver should issue the
        indicated sets at the earliest possible opportunity.
      </doc>

      <implement role="receiver" handle="MUST" />

      <field name="expected" type="bit" label="request notification of expected commands"/>
      <field name="confirmed" type="bit" label="request notification of confirmed commands"/>
      <field name="completed" type="bit" label="request notification of completed commands"/>
    </control>

    <control name="gap" code="0xd" label="indicates missing segments in the stream">
      <doc>
        This control is sent by the sender of commands and handled by the receiver of commands. It
        sends command ranges for which there will be no further data forthcoming. The receiver
        should proceed with the next available commands that arrive after the gap.
      </doc>

      <rule name="gap-confirmation-and-completion">
        <doc>
          The command-ids covered by a session.gap MUST be added to the completed and confirmed sets
          by the receiver.
        </doc>
      </rule>

      <rule name="aborted-commands">
        <doc>
          If a session.gap covers a partially received command, the receiving peer MUST treat the
          command as aborted.
        </doc>
      </rule>

      <rule name="completed-or-confirmed-commands">
        <doc>
          If a session.gap covers a completed or confirmed command, the receiving peer MUST continue
          to treat the command as completed or confirmed.
        </doc>
      </rule>

      <implement role="receiver" handle="MUST" />

      <field name="commands" type="commands">
        <doc>
          The set of command-ids that are contained in this gap.
        </doc>
      </field>
    </control>

  </class>

  <!-- == Class: execution ===================================================================== -->

  <class name="execution" code="0x3" label="execution commands">
    <doc>
      The execution class provides commands that carry execution information about other model level
      commands.
    </doc>

    <role name="server" implement="MUST"/>
    <role name="client" implement="MUST"/>

    <domain name="error-code" type="uint16">
      <enum>
        <choice name="unauthorized-access" value="403">
          <doc>
            The client attempted to work with a server entity to which it has no access due to
            security settings.
          </doc>
        </choice>

        <choice name="not-found" value="404">
          <doc>
            The client attempted to work with a server entity that does not exist.
          </doc>
        </choice>

        <choice name="resource-locked" value="405">
          <doc>
            The client attempted to work with a server entity to which it has no access because
            another client is working with it.
          </doc>
        </choice>

        <choice name="precondition-failed" value="406">
          <doc>
            The client requested a command that was not allowed because some precondition failed.
          </doc>
        </choice>

        <choice name="resource-deleted" value="408">
          <doc>
            A server entity the client is working with has been deleted.
          </doc>
        </choice>

        <choice name="illegal-state" value="409">
          <doc>
            The peer sent a command that is not permitted in the current state of the session.
          </doc>
        </choice>

        <choice name="command-invalid" value="503">
          <doc>
            The command segments could not be decoded.
          </doc>
        </choice>

        <choice name="resource-limit-exceeded" value="506">
          <doc>
            The client exceeded its resource allocation.
          </doc>
        </choice>

        <choice name="not-allowed" value="530">
          <doc>
            The peer tried to use a command a manner that is inconsistent with the rules described
            in the specification.
          </doc>
        </choice>

        <choice name="illegal-argument" value="531">
          <doc>
            The command argument is malformed, i.e. it does not fall within the specified domain.
            The illegal-argument exception can be raised on execution of any command which has
            domain valued fields.
          </doc>
        </choice>

        <choice name="not-implemented" value="540">
          <doc>
            The peer tried to use functionality that is not implemented in its partner.
          </doc>
        </choice>

        <choice name="internal-error" value="541">
          <doc>
            The peer could not complete the command because of an internal error. The peer may
            require intervention by an operator in order to resume normal operations.
          </doc>
        </choice>

        <choice name="invalid-argument" value="542">
          <doc>
            An invalid argument was passed to a command, and the operation could not
            proceed.  An invalid argument is not illegal (see illegal-argument), i.e. it matches
            the domain definition; however the particular value is invalid in this context.
          </doc>
        </choice>
      </enum>
    </domain>

    <!-- - Command: execution.sync - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <command name="sync" code="0x1" label="request notification of completion for issued commands">
      <doc>
        This command is complete when all prior commands are completed.
      </doc>

      <implement role="server" handle="MUST"/>
      <implement role="client" handle="MUST"/>
    </command>

    <!-- - Command: execution.result - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <command name="result" code="0x2" label="carries execution results">
      <doc>
        This command carries data resulting from the execution of a command.
      </doc>

      <implement role="server" handle="MUST"/>
      <implement role="client" handle="MUST"/>

      <field name="command-id" type="sequence-no" required="true"/>
      <field name="value" type="struct32"/>
    </command>

    <!-- - Command: execution.exception  - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <command name="exception" code="0x3" label="notifies a peer of an execution error">
      <doc>
        This command informs a peer of an execution exception. The command-id, when given,
        correlates the error to a specific command.
      </doc>

      <implement role="client" handle="MUST"/>
      <implement role="server" handle="MUST"/>

      <field name="error-code" type="error-code" required="true" label="error code indicating the
        type of error"/>
      <field name="command-id" type="sequence-no" label="exceptional command">
        <doc>
          The command-id of the command which caused the exception. If the exception was not caused
          by a specific command, this value is not set.
        </doc>
      </field>
      <field name="class-code" type="uint8" label="the class code of the command whose execution
        gave rise to the error (if appropriate)"/>
      <field name="command-code" type="uint8" label="the class code of the command whose execution
        gave rise to the error (if appropriate)"/>
      <field name="field-index" type="uint8" label="index of the exceptional field">
        <doc>
          The zero based index of the exceptional field within the arguments to the exceptional
          command. If the exception was not caused by a specific field, this value is not set.
        </doc>
      </field>
      <field name="description" type="str16" label="descriptive text on the exception">
        <doc>
          The description provided is implementation defined, but MUST be in the language
          appropriate for the selected locale.  The intention is that this description is suitable
          for logging or alerting output.
        </doc>
      </field>
      <field name="error-info" type="map" label="map to carry additional information about the
        error"/>

    </command>

  </class>

  <!-- == Class: message ======================================================================= -->

  <class name="message" code="0x4" label="message transfer">
    <doc>
      The message class provides commands that support an industry-standard messaging model.
    </doc>

    <doc type="picture" title="Transfer States">
      START:

        The message has yet to be sent to the recipient.

      NOT-ACQUIRED:

        The message has been sent to the recipient, but is not
        acquired by the recipient.

      ACQUIRED:

        The message has been sent to and acquired by the recipient.

      END:

        The transfer is complete.
    </doc>

    <doc type="picture" title="State Transitions"><![CDATA[
     *:TRANSFER (accept-mode=none)         *:TRANSFER (acquire-mode=pre-acquired)
  +---------------------------------START------------------------------------------+
  |                                   |                                            |
  |                                   | *:TRANSFER (acquire-mode=not-acquired)     |
  |                                   |                                            |
  |                  R:RELEASE       \|/                                           |
  |               +-------------NOT-ACQUIRED<--+                                   |
  |               |               |      |     | R:ACQUIRE (if unavailable)        |
  |               |               |      +-----+                                   |
  |               |               |                                                |
  |               |               | R:ACQUIRE (if available)                       |
  |               |               |                                                |
  |               |              \|/                                               |
  |               |            ACQUIRED<-------------------------------------------+
  |               |               |
  |               |               | R:ACCEPT / R:REJECT / R:RELEASE
  |               |               |
  |               |              \|/
  |               +------------->END]]>
  |                              /|\
  |                               |
  +-------------------------------+
    </doc>

    <doc type="grammar">
      message = *:TRANSFER [ R:ACQUIRE ] [ R:ACCEPT / R:REJECT / R:RELEASE ]
              / *:RESUME
              / *:SET-FLOW-MODE
              / *:FLOW
              / *:STOP
              / C:SUBSCRIBE
              / C:CANCEL
              / C:FLUSH
    </doc>

    <rule name="persistent-message">
      <doc>
        The server SHOULD respect the delivery-mode property of messages and SHOULD make a
        best-effort to hold persistent messages on a reliable storage mechanism.
      </doc>
      <doc type="scenario">
        Send a persistent message to queue, stop server, restart server and then verify whether
        message is still present. Assumes that queues are durable. Persistence without durable
        queues makes no sense.
      </doc>
    </rule>

    <rule name="no-persistent-message-discard">
      <doc>
        The server MUST NOT discard a persistent message in case of a queue overflow.
      </doc>
      <doc type="scenario">
        Create a queue overflow situation with persistent messages and verify that messages do not
        get lost (presumably the server will write them to disk).
      </doc>
    </rule>

    <rule name="throttling">
      <doc>
        The server MAY use the message.flow command to slow or stop a message publisher when
        necessary.
      </doc>
    </rule>

    <rule name="non-persistent-message-overflow">
      <doc>
        The server MAY overflow non-persistent messages to persistent storage.
      </doc>
    </rule>

    <rule name="non-persistent-message-discard">
      <doc>
        The server MAY discard or dead-letter non-persistent messages on a priority basis if the
        queue size exceeds some configured limit.
      </doc>
    </rule>

    <rule name="min-priority-levels">
      <doc>
        The server MUST implement at least 2 priority levels for messages, where priorities 0 and
        9 are treated as two distinct levels.
      </doc>
    </rule>

    <rule name="priority-level-implementation">
      <doc>
        The server SHOULD implement distinct priority levels in the following manner:
      </doc>
      <doc>
        If the server implements n distinct priorities then priorities 0 to 5 - ceiling(n/2) should
        be treated equivalently and should be the lowest effective priority.  The priorities 4 +
        floor(n/2) should be treated equivalently and should be the highest effective priority. The
        priorities (5 - ceiling(n/2)) to (4 + floor(n/2)) inclusive must be treated as distinct
        priorities.
      </doc>
      <doc>
        Thus, for example, if 2 distinct priorities are implemented, then levels 0 to 4 are
        equivalent, and levels 5 to 9 are equivalent and levels 4 and 5 are distinct.  If 3 distinct
        priorities are implements the 0 to 3 are equivalent, 5 to 9 are equivalent and 3, 4 and 5
        are distinct.
      </doc>
      <doc>
        This scheme ensures that if two priorities are distinct for a server which implements m
        separate priority levels they are also distinct for a server which implements n different
        priority levels where n > m.
      </doc>
    </rule>

    <rule name="priority-delivery">
      <doc>
        The server MUST deliver messages of the same priority in order irrespective of their
        individual persistence.
      </doc>
      <doc type="scenario">
        Send a set of messages with the same priority but different persistence settings to a queue.
        Subscribe and verify that messages arrive in same order as originally published.
      </doc>
    </rule>

    <role name="server" implement="MUST" />
    <role name="client" implement="MUST" />

    <domain name="destination" type="str8" label="destination for a message">
      <doc>
        Specifies the destination to which the message is to be transferred.
      </doc>
    </domain>

    <domain name="accept-mode" type="uint8" label="indicates a confirmation mode">
      <doc>
        Controls how the sender of messages is notified of successful transfer.
      </doc>

      <enum>
        <choice name="explicit" value="0">
          <doc>
            Successful transfer is signaled by message.accept. An acquired message (whether
            acquisition was implicit as in pre-acquired mode or explicit as in not-acquired mode) is
            not considered transferred until a message.accept that includes the transfer command is
            received.
          </doc>
        </choice>

        <choice name="none" value="1">
          <doc>
            Successful transfer is assumed when accept-mode is "pre-acquired". Messages transferred
            with an accept-mode of "not-acquired" cannot be acquired when accept-mode is "none".
          </doc>
        </choice>
      </enum>
    </domain>

    <domain name="acquire-mode" type="uint8" label="indicates the transfer mode">
      <doc>
        Indicates whether a transferred message can be considered as automatically acquired or
        whether an explicit request is necessary in order to acquire it.
      </doc>

      <enum>
        <choice name="pre-acquired" value="0">
          <doc>
            the message is acquired when the transfer starts
          </doc>
        </choice>

        <choice name="not-acquired" value="1">
          <doc>
            the message is not acquired when it arrives, and must be explicitly acquired by the
            recipient
          </doc>
        </choice>
      </enum>
    </domain>

    <domain name="reject-code" type="uint16" label="reject code for transfer">
      <doc>
        Code specifying the reason for a message reject.
      </doc>
      <enum>
        <choice name="unspecified" value="0">
          <doc>
            Rejected for an unspecified reason.
          </doc>
        </choice>
        <choice name="unroutable" value="1">
          <doc>
            Delivery was attempted but there were no queues which the message could be routed to.
          </doc>
        </choice>
        <choice name="immediate" value="2">
          <doc>
            The rejected message had the immediate flag set to true, but at the time of the transfer
            at least one of the queues to which it was to be routed did not have any subscriber able
            to take the message.
          </doc>
        </choice>
      </enum>
    </domain>

    <domain name="resume-id" type="str16">
      <doc>
        A resume-id serves to identify partially transferred message content. The id is chosen by
        the sender, and must be unique to a given user. A resume-id is not expected to be unique
        across users.
      </doc>
    </domain>

    <domain name="delivery-mode" type="uint8"
            label="indicates whether a message should be treated as transient or durable">
     <doc>

        Used to set the reliability requirements for a message which is transferred to the server.
      </doc>
      <enum>
        <choice name="non-persistent" value="1">
          <doc>
            A non-persistent message may be lost in event of a failure, but the nature of the
            communication is such that an occasional message loss is tolerable. This is the lowest
            overhead mode. Non-persistent messages are delivered at most once only.
          </doc>
        </choice>

        <choice name="persistent" value="2">
          <doc>
            A persistent message is one which must be stored on a persistent medium (usually hard
            drive) at every stage of delivery so that it will not be lost in event of failure (other
            than of the medium itself). This is normally accomplished with some additional overhead.
            A persistent message may be delivered more than once if there is uncertainty about the
            state of its delivery after a failure and recovery.
          </doc>
        </choice>
      </enum>
    </domain>

    <domain name="delivery-priority" type="uint8"
      label="indicates the desired priority to assign to a message transfer">
      <doc>
        Used to assign a priority to a message transfer. Priorities range from 0 (lowest) to 9
        (highest).
      </doc>
      <enum>
        <choice name="lowest" value="0">
          <doc>
            Lowest possible priority message.
          </doc>
        </choice>

        <choice name="lower" value="1">
          <doc>
            Very low priority message
          </doc>
        </choice>

        <choice name="low" value="2">
          <doc>
            Low priority message.
          </doc>
        </choice>

        <choice name="below-average" value="3">
          <doc>
            Below average priority message.
          </doc>
        </choice>

        <choice name="medium" value="4">
          <doc>
            Medium priority message.
          </doc>
        </choice>


        <choice name="above-average" value="5">
          <doc>
            Above average priority message
          </doc>
        </choice>


        <choice name="high" value="6">
          <doc>
            High priority message
          </doc>
        </choice>

        <choice name="higher" value="7">
          <doc>
            Higher priority message
          </doc>
        </choice>

        <choice name="very-high" value="8">
          <doc>
            Very high priority message.
          </doc>
        </choice>

        <choice name="highest" value="9">
          <doc>
            Highest possible priority message.
          </doc>
        </choice>
      </enum>
    </domain>

    <struct name="delivery-properties" size="4" code="0x1" pack="2">
      <field name="discard-unroutable" type="bit" label="controls discard of unroutable messages">
        <doc>
          If set on a message that is not routable the broker can discard it. If not set, an
          unroutable message should be handled by reject when accept-mode is explicit; or by routing
          to the alternate-exchange if defined when accept-mode is none.
        </doc>
      </field>

      <field name="immediate" type="bit" label="Consider message unroutable if it cannot be
        processed immediately">
        <doc>
          If the immediate flag is set to true on a message transferred to a Server, then the
          message should be considered unroutable (and not delivered to any queues) if, for any
          queue that it is to be routed to according to the standard routing behavior, there is not
          a subscription on that queue able to receive the message. The treatment of unroutable
          messages is dependent on the value of the discard-unroutable flag.
        </doc>
        <doc>
          The immediate flag is ignored on transferred to a Client.
        </doc>
      </field>

      <field name="redelivered" type="bit" label="redelivery flag">
        <doc>
          This boolean flag indicates that the message may have been previously delivered to this
          or another client.
        </doc>
        <doc>
          If the redelivered flag is set on transfer to a Server, then any delivery of the message
          from that Server to a Client must also have the redelivered flag set to true.
        </doc>
        <rule name="implementation">
          <doc>
            The server MUST try to signal redelivered messages when it can. When redelivering a
            message that was not successfully accepted, the server SHOULD deliver it to the original
            client if possible.
          </doc>
          <doc type="scenario">
            Create a shared queue and publish a message to the queue. Subscribe using explicit
            accept-mode, but do not accept the message. Close the session, reconnect, and subscribe
            to the queue again. The message MUST arrive with the redelivered flag set.
          </doc>
        </rule>
        <rule name="hinting">
          <doc>
            The client should not rely on the redelivered field to detect duplicate messages where
            publishers may themselves produce duplicates. A fully robust client should be able to
            track duplicate received messages on non-transacted, and locally-transacted sessions.
          </doc>
        </rule>
      </field>

      <field name="priority" type="delivery-priority" label="message priority, 0 to 9"
        required="true">
        <doc> Message priority, which can be between 0 and 9. Messages with higher priorities may be
          delivered before those with lower priorities. </doc>
      </field>

      <field name="delivery-mode" type="delivery-mode" label="message persistence requirement"
        required="true">
        <doc> The delivery mode may be non-persistent or persistent. </doc>
      </field>

      <field name="ttl" type="uint64" label="time to live in ms">
        <doc> Duration in milliseconds for which the message should be considered "live". If this is
          set then a message expiration time will be computed based on the current time plus this
          value. Messages that live longer than their expiration time will be discarded (or dead
          lettered).</doc>
        <rule name="ttl-decrement">
          <doc>
            If a message is transferred between brokers before delivery to a final subscriber the
            ttl should be decremented before peer to peer transfer and both timestamp and expiration
            should be cleared.
          </doc>
        </rule>
      </field>

      <field name="timestamp" type="datetime" label="message timestamp">
        <doc>
          The timestamp is set by the broker on arrival of the message.
        </doc>
      </field>

      <field name="expiration" type="datetime" label="message expiration time">
        <doc>
          The expiration header assigned by the broker. After receiving the message the broker sets
          expiration to the sum of the ttl specified in the publish command and the current time.
          (ttl=expiration - timestamp)
        </doc>
      </field>

      <field name="exchange" type="exchange.name" label="originating exchange">
        <doc>
          Identifies the exchange specified in the destination field of the message.transfer used to
          publish the message. This MUST be set by the broker upon receipt of a message.
        </doc>
      </field>

      <field name="routing-key" type="str8" label="message routing key">
        <doc>
          The value of the key determines to which queue the exchange will send the message. The way
          in which keys are used to make this routing decision depends on the type of exchange to
          which the message is sent. For example, a direct exchange will route a message to a queue
          if that queue is bound to the exchange with a binding-key identical to the routing-key of
          the message.
        </doc>
      </field>

      <field name="resume-id" type="resume-id" label="global id for message transfer">
        <doc>
          When a resume-id is provided the recipient MAY use it to retain message data should the
          session expire while the message transfer is still incomplete.
        </doc>
      </field>

      <field name="resume-ttl" type="uint64" label="ttl in ms for interrupted message data">
        <doc>
          When a resume-ttl is provided the recipient MAY use it has a guideline for how long to
          retain the partially complete data when a resume-id is specified. If no resume-id is
          specified then this value should be ignored.
        </doc>
      </field>
    </struct>

    <struct name="fragment-properties" size="4" code="0x2" pack="2">
      <doc>
        These properties permit the transfer of message fragments. These may be used in conjunction
        with byte level flow control to limit the rate at which large messages are received. Only
        the first fragment carries the delivery-properties and message-properties.

        Syntactically each fragment appears as a complete message to the lower layers of the
        protocol, however the model layer is required to treat all the fragments as a single
        message. For example all fragments must be delivered to the same client. In pre-acquired
        mode, no message fragments can be delivered by the broker until the entire message has been
        received.
      </doc>

      <field name="first" type="bit" default="1">
        <doc>True if this fragment contains the start of the message, false otherwise.</doc>
      </field>

      <field name="last" type="bit" default="1">
        <doc>True if this fragment contains the end of the message, false otherwise.</doc>
      </field>

      <field name="fragment-size" type="uint64">
        <doc>This field may optionally contain the size of the fragment.</doc>
      </field>
    </struct>

    <struct name="reply-to" size="2" pack="2">
      <doc>The reply-to domain provides a simple address structure for replying to to a message to a
      destination within the same virtual-host.</doc>
      <field name="exchange" type="exchange.name" label="the name of the exchange to reply to"/>
      <field name="routing-key" type="str8" label="the routing-key to use when replying"/>
    </struct>

    <struct name="message-properties" size="4" code="0x3" pack="2">
      <field name="content-length" type="uint64" label="length of the body segment in bytes">
        <doc>
          The length of the body segment in bytes.
        </doc>
      </field>

      <field name="message-id" type="uuid" label="application message identifier">
        <doc>
          Message-id is an optional property of UUID type which uniquely identifies a message within
          the message system. The message producer is usually responsible for setting the
          message-id. The server MAY discard a message as a duplicate if the value of the message-id
          matches that of a previously received message. Duplicate messages MUST still be accepted
          if transferred with an accept-mode of "explicit".
        </doc>

        <rule name="unique">
          <doc>
            A message-id MUST be unique within a given server instance. A message-id SHOULD be
            globally unique (i.e. across different systems).
          </doc>
        </rule>

        <rule name="immutable">
          <doc>
            A message ID is immutable. Once set, a message-id MUST NOT be changed or reassigned,
            even if the message is replicated, resent or sent to multiple queues.
          </doc>
        </rule>
      </field>

      <field name="correlation-id" type="vbin16" label="application correlation identifier">
        <doc>
          This is a client-specific id that may be used to mark or identify messages between
          clients. The server ignores this field.
        </doc>
      </field>

      <field name="reply-to" type="reply-to" label="destination to reply to">
        <doc>
          The destination of any message that is sent in reply to this message.
        </doc>
      </field>

      <field name="content-type" type="str8" label="MIME content type">
        <doc>
          The RFC-2046 MIME type for the message content (such as "text/plain"). This is set by the
          originating client.
        </doc>
      </field>

      <field name="content-encoding" type="str8" label="MIME content encoding">
        <doc>
          The encoding for character-based message content. This is set by the originating client.
          Examples include UTF-8 and ISO-8859-15.
        </doc>
      </field>

      <field name="user-id" type="vbin16" label="creating user id">
        <doc>
          The identity of the user responsible for producing the message. The client sets this
          value, and it is authenticated by the broker.
        </doc>

        <rule name="authentication">
          <doc>
            The server MUST produce an unauthorized-access exception if the user-id field is set to
            a principle for which the client is not authenticated.
          </doc>
        </rule>
      </field>

      <field name="app-id" type="vbin16" label="creating application id">
        <doc>
          The identity of the client application responsible for producing the message.
        </doc>
      </field>

      <field name="application-headers" type="map" label="application specific headers table">
        <doc>
          This is a collection of user-defined headers or properties which may be set by the
          producing client and retrieved by the consuming client.
        </doc>
      </field>
    </struct>

    <domain name="flow-mode" type="uint8" label="the flow-mode for allocating flow credit">
      <enum>
        <choice name="credit" value="0">
          <doc>
            Credit based flow control.
          </doc>
        </choice>

        <choice name="window" value="1">
          <doc>
            Window based flow control.
          </doc>
        </choice>
      </enum>
    </domain>

    <domain name="credit-unit" type="uint8" label="specifies the unit of credit balance">
      <enum>
        <choice name="message" value="0">
          <doc>Indicates a value specified in messages.</doc>
        </choice>
        <choice name="byte" value="1">
          <doc>Indicates a value specified in bytes.</doc>
        </choice>
      </enum>
    </domain>

    <!-- - Command: message.transfer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <command name="transfer" code="0x1" label="transfer a message">
      <doc>
        This command transfers a message between two peers. When a client uses this command to
        publish a message to a broker, the destination identifies a specific exchange. The message
        will then be routed to queues as defined by the exchange configuration.

        The client may request a broker to transfer messages to it, from a particular queue, by
        issuing a subscribe command. The subscribe command specifies the destination that the broker
        should use for any resulting transfers.
      </doc>

      <rule name="transactional-publish">
        <doc>
          If a transfer to an exchange occurs within a transaction, then it is not available from
          the queue until the transaction commits. It is not specified whether routing takes place
          when the transfer is received or when the transaction commits.
        </doc>
      </rule>

      <implement role="server" handle="MUST" />
      <implement role="client" handle="MUST" />


      <field name="destination" type="destination" label="message destination">
        <doc>
          Specifies the destination to which the message is to be transferred.
        </doc>

        <rule name="blank-destination">
          <doc>
            The server MUST accept a blank destination to mean the default exchange.
          </doc>
        </rule>

        <exception name="nonexistent-exchange" error-code="not-found">
          <doc>
            If the destination refers to an exchange that does not exist, the peer MUST raise a
            session exception.
          </doc>
        </exception>
      </field>

      <field name="accept-mode" type="accept-mode" required="true">
        <doc>
          Indicates whether message.accept, session.complete, or nothing at all is required to
          indicate successful transfer of the message.
        </doc>
      </field>

      <field name="acquire-mode" type="acquire-mode" required="true">
        <doc>
          Indicates whether or not the transferred message has been acquired.
        </doc>
      </field>

      <segments>
        <header>
          <entry type="delivery-properties"/>
          <entry type="fragment-properties"/>
          <entry type="message-properties"/>
        </header>
        <body/>
      </segments>
    </command>

    <!-- - Command: message.accept - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <command name="accept" code="0x2" label="reject a message">
      <doc>
        Accepts the message. Once a transfer is accepted, the command-id may no longer be referenced
        from other commands.
      </doc>

      <rule name="acquisition">
        <doc>
          The recipient MUST have acquired a message in order to accept it.
        </doc>
      </rule>

      <implement role="server" handle="MUST" />
      <implement role="client" handle="MUST" />

      <field name="transfers" type="session.commands" required="true">
        <doc>
          Identifies the messages previously transferred that should be accepted.
        </doc>
      </field>
    </command>

    <!-- - Command: message.reject - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <command name="reject" code="0x3" label="reject a message">
      <doc>
        Indicates that the message transfers are unprocessable in some way. A server may reject a
        message if it is unroutable. A client may reject a message if it is invalid. A message may
        be rejected for other reasons as well. Once a transfer is rejected, the command-id may no
        longer be referenced from other commands.
      </doc>

      <rule name="alternate-exchange">
        <doc>
          When a client rejects a message, the server MUST deliver that message to the
          alternate-exchange on the queue from which it was delivered. If no alternate-exchange is
          defined for that queue the broker MAY discard the message.
        </doc>
      </rule>

      <rule name="acquisition">
        <doc>
          The recipient MUST have acquired a message in order to reject it. If the message is not
          acquired any reject MUST be ignored.
        </doc>
      </rule>

      <implement role="server" handle="MUST" />
      <implement role="client" handle="MUST" />

      <field name="transfers" type="session.commands" required="true">
        <doc>
          Identifies the messages previously transferred that should be rejected.
        </doc>
      </field>
      <field name="code" type="reject-code" required="true">
        <doc>
          Code describing the reason for rejection.
        </doc>
      </field>
      <field name="text" type="str8" label="informational text for message reject">
        <doc>
          Text describing the reason for rejection.
        </doc>
      </field>
    </command>

    <!-- - Command: message.release  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <command name="release" code="0x4" label="release a message">
      <doc>
        Release previously transferred messages. When acquired messages are released, they become
        available for acquisition by any subscriber. Once a transfer is released, the command-id may
        no longer be referenced from other commands.
      </doc>

      <rule name="ordering">
        <doc>
          Acquired messages that have been released MAY subsequently be delivered out of order.
          Implementations SHOULD ensure that released messages keep their position with respect to
          undelivered messages of the same priority.
        </doc>
      </rule>

      <implement role="server" handle="MUST" />
      <implement role="client" handle="MAY" />

      <field name="transfers" type="session.commands" required="true">
        <doc>
          Indicates the messages to be released.
        </doc>
      </field>
      <field name="set-redelivered" type="bit" label="mark the released messages as redelivered">
        <doc>
          By setting set-redelivered to true, any acquired messages released to a queue with this
          command will be marked as redelivered on their next transfer from that queue. If this flag
          is not set, then an acquired message will retain its original redelivered status on the
          queue. Messages that are not acquired are unaffected by the value of this flag.
        </doc>
      </field>
    </command>

    <!-- - Command: message.acquire  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->

    <command name="acquire" code="0x5" label="acquire messages for consumption">
      <doc>
        Acquires previously transferred messages for consumption. The acquired ids (if any) are
        sent via message.acquired.
      </doc>

      <rule name="one-to-one">
        <