blob: 365928ea4e357bfc85cacbfc900f8fd2199025dc [file] [log] [blame]
<?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.0-10.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>
<implement role="client" handle="MAY" />
<implement role="server" handle="MAY" />
</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">
<doc>
Each acquire MUST produce exactly one message.acquired even if it is empty.
</doc>
</rule>
<implement role="server" handle="MUST" />
<field name="transfers" type="session.commands" required="true">
<doc>
Indicates the messages to be acquired.
</doc>
</field>
<result>
<struct name="acquired" size="4" code="0x4" pack="2" label="indicates acquired messages">
<doc>
Identifies a set of previously transferred messages that have now been acquired.
</doc>
<field name="transfers" type="session.commands" required="true">
<doc>
Indicates the acquired messages.
</doc>
</field>
</struct>
</result>
</command>
<!-- - Command: message.resume - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="resume" code="0x6" label="resume an interrupted message transfer">
<doc>
This command resumes an interrupted transfer. The recipient should return the amount of
partially transferred data associated with the given resume-id, or zero if there is no data
at all. If a non-zero result is returned, the recipient should expect to receive message
fragment(s) containing the remainder of the interrupted message.
</doc>
<implement role="server" handle="MUST" />
<implement role="client" handle="MUST" />
<field name="destination" type="destination">
<doc>
The destination to which the remaining message fragments are transferred.
</doc>
<exception name="destination-not-found" error-code="not-found">
<doc>If the destination does not exist, the recipient MUST close the session.</doc>
</exception>
</field>
<field name="resume-id" type="resume-id" required="true">
<doc>
The name of the transfer being resumed.
</doc>
<rule name="unknown-resume-id">
<doc>If the resume-id is not known, the recipient MUST return an offset of zero.</doc>
</rule>
</field>
<result>
<struct name="message-resume-result" size="4" code="0x5" pack="2">
<field name="offset" type="uint64">
<doc>
Indicates the amount of data already transferred.
</doc>
</field>
</struct>
</result>
</command>
<!-- - Command: message.subscribe - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="subscribe" code="0x7" label="start a queue subscription">
<doc> This command asks the server to start a "subscription", which is a request for messages
from a specific queue. Subscriptions last as long as the session they were created on, or
until the client cancels them. </doc>
<rule name="simultaneous-subscriptions">
<doc> The server SHOULD support at least 16 subscriptions per queue, and ideally, impose no
limit except as defined by available resources. </doc>
<doc type="scenario"> Create a queue and create subscriptions on that queue until the server
closes the connection. Verify that the number of subscriptions created was at least
sixteen and report the total number. </doc>
</rule>
<rule name="default-flow-mode">
<doc> The default flow mode for new subscriptions is window-mode. </doc>
</rule>
<exception name="queue-deletion" error-code="resource-deleted">
<doc>
If the queue for this subscription is deleted, any subscribing sessions MUST be closed.
This exception may occur at any time after the subscription has been completed.
</doc>
</exception>
<exception name="queue-not-found" error-code="not-found">
<doc> If the queue for this subscription does not exist, then the subscribing session MUST
be closed. </doc>
</exception>
<rule name="initial-credit">
<doc>
Immediately after a subscription is created, the initial byte and message credit for that
destination is zero.
</doc>
</rule>
<implement role="server" handle="MUST"/>
<field name="queue" type="queue.name" required="true">
<doc> Specifies the name of the subscribed queue. </doc>
</field>
<field name="destination" type="destination" label="incoming message destination">
<doc> The client specified name for the subscription. This is used as the destination for
all messages transferred from this subscription. The destination is scoped to the session.
</doc>
<exception name="unique-subscriber-destination" error-code="not-allowed">
<doc> The client MUST NOT specify a destination that refers to an existing subscription on
the same session. </doc>
<doc type="scenario"> Attempt to create two subscriptions on the same session with the
same non-empty destination. </doc>
</exception>
</field>
<field name="accept-mode" type="accept-mode" required="true">
<doc> The accept-mode to use for messages transferred from this subscription. </doc>
</field>
<field name="acquire-mode" type="acquire-mode" required="true">
<doc> The acquire-mode to use for messages transferred from this subscription. </doc>
</field>
<field name="exclusive" type="bit" label="request exclusive access">
<doc> Request an exclusive subscription. This prevents other subscribers from subscribing to
the queue. </doc>
<exception name="in-use" error-code="resource-locked">
<doc> The server MUST NOT grant an exclusive subscription to a queue that already has
subscribers. </doc>
<doc type="scenario"> Open two connections to a server, and in one connection create a
shared (non-exclusive) queue and then subscribe to the queue. In the second connection
attempt to subscribe to the same queue using the exclusive option. </doc>
</exception>
</field>
<field name="resume-id" type="resume-id">
<doc> Requests that the broker use the supplied resume-id when transferring messages for
this subscription. </doc>
</field>
<field name="resume-ttl" type="uint64">
<doc> Requested duration in milliseconds for the broker use as resume-ttl when transferring
messages for this subscription. </doc>
</field>
<field name="arguments" type="map" label="arguments for vendor extensions">
<doc> The syntax and semantics of these arguments depends on the providers implementation.
</doc>
</field>
</command>
<!-- - Command: message.cancel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="cancel" code="0x8" label="end a queue subscription">
<doc>
This command cancels a subscription. This does not affect already delivered messages, but it
does mean the server will not send any more messages for that subscription. The client may
receive an arbitrary number of messages in between sending the cancel command and receiving
notification that the cancel command is complete.
</doc>
<rule name="post-cancel-transfer-resolution">
<doc>
Canceling a subscription MUST NOT affect pending transfers. A transfer made prior to
canceling transfers to the destination MUST be able to be accepted, released, acquired, or
rejected after the subscription is canceled.
</doc>
</rule>
<implement role="server" handle="MUST" />
<field name="destination" type="destination" required="true">
<exception name="subscription-not-found" error-code="not-found">
<doc>
If the subscription specified by the destination is not found, the server MUST close the
session.
</doc>
</exception>
</field>
</command>
<!-- - Command: message.set-flow-mode - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="set-flow-mode" code="0x9" label="set the flow control mode">
<doc>
Sets the mode of flow control used for a given destination to either window or credit based
flow control.
With credit based flow control, the sender of messages continually maintains its current
credit balance with the recipient. The credit balance consists of two values, a message
count, and a byte count. Whenever message data is sent, both counts must be decremented.
If either value reaches zero, the flow of message data must stop. Additional credit is
received via the message.flow command.
The sender MUST NOT send partial assemblies. This means that if there is not enough byte
credit available to send a complete message, the sender must either wait or use message
fragmentation (see the fragment-properties header struct) to send the first part of the
message data in a complete assembly.
Window based flow control is identical to credit based flow control, however message
transfer completion implicitly grants a single unit of message credit, and the size of the
message in byte credits for each completed message transfer. Completion of the transfer
command with session.completed is the only way credit is implicitly updated; message.accept,
message.release, message.reject, tx.commit and tx.rollback have no effect on the outstanding
credit balances.
</doc>
<rule name="byte-accounting">
<doc>
The byte count is decremented by the payload size of each transmitted frame with segment
type header or body appearing within a message.transfer command. Note that the payload
size is the frame size less the frame header size.
</doc>
</rule>
<rule name="mode-switching">
<doc>
Mode switching may only occur if both the byte and message credit balance are zero. There
are three ways for a recipient of messages to be sure that the sender's credit balances
are zero:
1) The recipient may send a message.stop command to the sender. When the recipient
receives notification of completion for the message.stop command, it knows that the
sender's credit is zero.
2) The recipient may perform the same steps described in (1) with the message.flush
command substituted for the message.stop command.
3) Immediately after a subscription is created with message.subscribe, the credit for
that destination is zero.
</doc>
</rule>
<rule name="default-flow-mode">
<doc>
Prior to receiving an explicit set-flow-mode command, a peer MUST consider the flow-mode
to be window.
</doc>
</rule>
<implement role="server" handle="MUST" />
<implement role="client" handle="MUST" />
<field name="destination" type="destination"/>
<field name="flow-mode" type="flow-mode" required="true">
<doc>
The new flow control mode.
</doc>
</field>
</command>
<!-- - Command: message.flow - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="flow" code="0xa" label="control message flow">
<doc>
This command controls the flow of message data to a given destination. It is used by the
recipient of messages to dynamically match the incoming rate of message flow to its
processing or forwarding capacity. Upon receipt of this command, the sender must add "value"
number of the specified unit to the available credit balance for the specified destination.
A value of (0xFFFFFFFF) indicates an infinite amount of credit. This disables any limit for
the given unit until the credit balance is zeroed with message.stop or message.flush.
</doc>
<!-- throws no-such-destination -->
<implement role="server" handle="MUST" />
<implement role="client" handle="MUST" />
<field name="destination" type="destination"/>
<field name="unit" type="credit-unit" required="true">
<doc>
The unit of value.
</doc>
</field>
<field name="value" type="uint32">
<doc>
If the value is not set then this indicates an infinite amount of credit.
</doc>
</field>
</command>
<!-- - Command: message.flush - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="flush" code="0xb" label="force the sending of available messages">
<doc>
Forces the sender to exhaust his credit supply. The sender's credit will always be zero when
this command completes. The command completes when immediately available message data has
been transferred, or when the credit supply is exhausted.
</doc>
<implement role="server" handle="MUST" />
<field name="destination" type="destination"/>
</command>
<!-- - Command: message.stop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="stop" code="0xc" label="stop the sending of messages">
<doc>
On receipt of this command, a producer of messages MUST set his credit to zero for the given
destination. When notifying of completion, credit MUST be zero and no further messages will
be sent until such a time as further credit is received.
</doc>
<implement role="server" handle="MUST" />
<implement role="client" handle="MUST" />
<field name="destination" type="destination"/>
</command>
</class>
<!-- == Class: tx ============================================================================ -->
<class name="tx" code="0x5" label="work with standard transactions">
<doc>
Standard transactions provide so-called "1.5 phase commit". We can ensure that work is never
lost, but there is a chance of confirmations being lost, so that messages may be resent.
Applications that use standard transactions must be able to detect and ignore duplicate
messages.
</doc>
<doc type="grammar">
tx = C:SELECT
/ C:COMMIT
/ C:ROLLBACK
</doc>
<!-- XXX: this isn't really a rule, as stated there is no way for
a client library to implement this -->
<rule name="duplicate-tracking">
<doc>
An client using standard transactions SHOULD be able to track all messages received within a
reasonable period, and thus detect and reject duplicates of the same message. It SHOULD NOT
pass these to the application layer.
</doc>
</rule>
<role name="server" implement="SHOULD" />
<!-- - Command: tx.select - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="select" code="0x1" label="select standard transaction mode">
<doc>
This command sets the session to use standard transactions. The client must use this command
exactly once on a session before using the Commit or Rollback commands.
</doc>
<exception name="exactly-once" error-code="illegal-state">
<doc>
A client MUST NOT select standard transactions on a session that is already transactional.
</doc>
</exception>
<exception name="no-dtx" error-code="illegal-state">
<doc>
A client MUST NOT select standard transactions on a session that is already enlisted in a
distributed transaction.
</doc>
</exception>
<exception name="explicit-accepts" error-code="not-allowed">
<doc>
On a session on which tx.select has been issued, a client MUST NOT issue a
message.subscribe command with the accept-mode property set to any value other than
explicit. Similarly a tx.select MUST NOT be issued on a session on which a there is a non
cancelled subscriber with accept-mode of none.
</doc>
</exception>
<implement role="server" handle="MUST" />
</command>
<!-- - Command: tx.commit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="commit" code="0x2" label="commit the current transaction">
<doc>
This command commits all messages published and accepted in the current transaction. A
new transaction starts immediately after a commit.
</doc>
<doc>
In more detail, the commit acts on all messages which have been transferred from the Client
to the Server, and on all acceptances of messages sent from Server to Client. Since the
commit acts on commands sent in the same direction as the commit command itself, there is no
ambiguity on the scope of the commands being committed. Further, the commit will not be
completed until all preceding commands which it affects have been completed.
</doc>
<doc>
Since transactions act on explicit accept commands, the only valid accept-mode for message
subscribers is explicit. For transferring messages from Client to Server (publishing) all
accept-modes are permitted.
</doc>
<exception name="select-required" error-code="illegal-state">
<doc>
A client MUST NOT issue tx.commit on a session that has not been selected for standard
transactions with tx.select.
</doc>
</exception>
<implement role="server" handle="MUST" />
</command>
<!-- - Command: tx.rollback - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="rollback" code="0x3" label="abandon the current transaction">
<doc>
This command abandons the current transaction. In particular the transfers from Client to
Server (publishes) and accepts of transfers from Server to Client which occurred in the
current transaction are discarded. A new transaction starts immediately after a rollback.
</doc>
<doc>
In more detail, when a rollback is issued, any the effects of transfers which occurred from
Client to Server are discarded. The Server will issue completion notification for all such
transfers prior to the completion of the rollback. Similarly the effects of any
message.accept issued from Client to Server prior to the issuance of the tx.rollback will be
discarded; and notification of completion for all such commands will be issued before the
issuance of the completion for the rollback.
</doc>
<doc>
After the completion of the rollback, the client will still hold the messages which it has
not yet accepted (including those for which accepts were previously issued within the
transaction); i.e. the messages remain "acquired". If the Client wishes to release those
messages back to the Server, then appropriate message.release commands must be issued.
</doc>
<exception name="select-required" error-code="illegal-state">
<doc>
A client MUST NOT issue tx.rollback on a session that has not been selected for standard
transactions with tx.select.
</doc>
</exception>
<implement role="server" handle="MUST" />
</command>
</class>
<!-- == Class: dtx =========================================================================== -->
<class name="dtx" code="0x6" label="Demarcates dtx branches">
<doc>
This provides the X-Open XA distributed transaction protocol support. It allows a session
to be selected for use with distributed transactions, the transactional boundaries for work on
that session to be demarcated and allows the transaction manager to coordinate transaction
outcomes.
</doc>
<doc type="grammar">
dtx-demarcation = C:SELECT *demarcation
demarcation = C:START C:END
</doc>
<doc type="grammar">
dtx-coordination = *coordination
coordination = command
/ outcome
/ recovery
command = C:SET-TIMEOUT
/ C:GET-TIMEOUT
outcome = one-phase-commit
/ one-phase-rollback
/ two-phase-commit
/ two-phase-rollback
one-phase-commit = C:COMMIT
one-phase-rollback = C:ROLLBACK
two-phase-commit = C:PREPARE C:COMMIT
two-phase-rollback = C:PREPARE C:ROLLBACK
recovery = C:RECOVER *recovery-outcome
recovery-outcome = one-phase-commit
/ one-phase-rollback
/ C:FORGET
</doc>
<rule name="transactionality">
<doc>
Enabling XA transaction support on a session requires that the server MUST manage
transactions demarcated by start-end blocks. That is to say that on this XA-enabled session,
work undergone within transactional blocks is performed on behalf a transaction branch
whereas work performed outside of transactional blocks is NOT transactional.
</doc>
</rule>
<role name="server" implement="MAY" />
<role name="client" implement="MAY" />
<!-- XA domains -->
<domain name="xa-status" type="uint16" label="XA return codes">
<enum>
<choice name="xa-ok" value="0">
<doc>
Normal execution completion (no error).
</doc>
</choice>
<choice name="xa-rbrollback" value="1">
<doc>
The rollback was caused for an unspecified reason.
</doc>
</choice>
<choice name="xa-rbtimeout" value="2">
<doc>
A transaction branch took too long.
</doc>
</choice>
<choice name="xa-heurhaz" value="3">
<doc>
The transaction branch may have been heuristically completed.
</doc>
</choice>
<choice name="xa-heurcom" value="4">
<doc>
The transaction branch has been heuristically committed.
</doc>
</choice>
<choice name="xa-heurrb" value="5">
<doc>
The transaction branch has been heuristically rolled back.
</doc>
</choice>
<choice name="xa-heurmix" value="6">
<doc>
The transaction branch has been heuristically committed and rolled back.
</doc>
</choice>
<choice name="xa-rdonly" value="7">
<doc>
The transaction branch was read-only and has been committed.
</doc>
</choice>
</enum>
</domain>
<struct name="xa-result" size="4" code="0x1" pack="2">
<field name="status" type="xa-status" required="true"/>
</struct>
<!-- Struct for xid -->
<struct name="xid" size="4" code="0x4" pack="2" label="dtx branch identifier">
<doc>
An xid uniquely identifies a transaction branch.
</doc>
<field name="format" type="uint32" label="implementation specific format code"
required="true"/>
<field name="global-id" type="vbin8" label="global transaction id" required="true"/>
<field name="branch-id" type="vbin8" label="branch qualifier" required="true"/>
</struct>
<!-- - Command: dtx.select - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="select" code="0x1" label="Select dtx mode">
<doc>
This command sets the session to use distributed transactions. The client must use this
command at least once on a session before using XA demarcation operations.
</doc>
<implement role="server" handle="MAY" />
</command>
<!-- - Command: dtx.start - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="start" code="0x2" label="Start a dtx branch">
<doc>
This command is called when messages should be produced and consumed on behalf a transaction
branch identified by xid.
</doc>
<exception name="illegal-state" error-code="illegal-state">
<doc>
If the command is invoked in an improper context (see class grammar) then the server MUST
send a session exception.
</doc>
</exception>
<exception name="already-known" error-code="not-allowed">
<doc>
If neither join nor resume is specified is specified and the transaction branch specified
by xid has previously been seen then the server MUST raise an exception.
</doc>
</exception>
<exception name="join-and-resume" error-code="not-allowed">
<doc>
If join and resume are specified then the server MUST raise an exception.
</doc>
</exception>
<implement role="server" handle="MAY" />
<field name="xid" type="xid" label="Transaction xid" required="true">
<doc>
Specifies the xid of the transaction branch to be started.
</doc>
<exception name="unknown-xid" error-code="not-allowed">
<doc>
If xid is already known by the broker then the server MUST raise an exception.
</doc>
</exception>
</field>
<field name="join" type="bit" label="Join with existing xid flag">
<doc>
Indicate whether this is joining an already associated xid. Indicate that the start
applies to joining a transaction previously seen.
</doc>
<exception name="unsupported" error-code="not-implemented">
<doc>
If the broker does not support join the server MUST raise an exception.
</doc>
</exception>
</field>
<field name="resume" type="bit" label="Resume flag">
<doc>
Indicate that the start applies to resuming a suspended transaction branch specified.
</doc>
</field>
<result type="xa-result">
<doc>
This confirms to the client that the transaction branch is started or specify the error
condition.
The value of this field may be one of the following constants:
xa-ok: Normal execution.
xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
reason.
xa-rbtimeout: The work represented by this transaction branch took too long.
</doc>
</result>
</command>
<!-- - Command: dtx.end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="end" code="0x3" label="End a dtx branch">
<doc>
This command is called when the work done on behalf a transaction branch finishes or needs
to be suspended.
</doc>
<exception name="illegal-state" error-code="illegal-state">
<doc>
If the command is invoked in an improper context (see class grammar) then the server MUST
raise an exception.
</doc>
</exception>
<exception name="suspend-and-fail" error-code="not-allowed">
<doc>
If suspend and fail are specified then the server MUST raise an exception.
</doc>
</exception>
<rule name="success">
<doc>
If neither fail nor suspend are specified then the portion of work has completed
successfully.
</doc>
</rule>
<rule name="session-closed">
<doc>
When a session is closed then the currently associated transaction branches MUST be marked
rollback-only.
</doc>
</rule>
<implement role="server" handle="MAY" />
<field name="xid" type="xid" label="Transaction xid" required="true">
<doc>
Specifies the xid of the transaction branch to be ended.
</doc>
<exception name="not-associated" error-code="illegal-state">
<doc>
The session MUST be currently associated with the given xid (through an earlier start
call with the same xid).
</doc>
</exception>
</field>
<field name="fail" type="bit" label="Failure flag">
<doc>
If set, indicates that this portion of work has failed; otherwise this portion of work has
completed successfully.
</doc>
<rule name="failure">
<doc>
An implementation MAY elect to roll a transaction back if this failure notification is
received. Should an implementation elect to implement this behavior, and this bit is
set, then then the transaction branch SHOULD be marked as rollback-only and the end
result SHOULD have the xa-rbrollback status set.
</doc>
</rule>
</field>
<field name="suspend" type="bit" label="Temporary suspension flag">
<doc>
Indicates that the transaction branch is temporarily suspended in an incomplete state.
</doc>
<rule name="resume">
<doc>
The transaction context is in a suspended state and must be resumed via the start
command with resume specified.
</doc>
</rule>
</field>
<result type="xa-result">
<doc>
This command confirms to the client that the transaction branch is ended or specify the
error condition.
The value of this field may be one of the following constants:
xa-ok: Normal execution.
xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
reason. If an implementation chooses to implement rollback-on-failure behavior, then
this value should be selected if the dtx.end.fail bit was set.
xa-rbtimeout: The work represented by this transaction branch took too long.
</doc>
</result>
</command>
<!-- - Command: dtx.commit - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="commit" code="0x4" label="Commit work on dtx branch">
<doc>
Commit the work done on behalf a transaction branch. This command commits the work
associated with xid. Any produced messages are made available and any consumed messages are
discarded.
</doc>
<exception name="illegal-state" error-code="illegal-state">
<doc>
If the command is invoked in an improper context (see class grammar) then the server MUST
raise an exception.
</doc>
</exception>
<implement role="server" handle="MAY" />
<field name="xid" type="xid" label="Transaction xid" required="true">
<doc>
Specifies the xid of the transaction branch to be committed.
</doc>
<exception name="unknown-xid" error-code="not-found">
<doc>
If xid is unknown (the transaction branch has not been started or has already been
ended) then the server MUST raise an exception.
</doc>
</exception>
<exception name="not-disassociated" error-code="illegal-state">
<doc>
If this command is called when xid is still associated with a session then the server
MUST raise an exception.
</doc>
</exception>
</field>
<field name="one-phase" type="bit" label="One-phase optimization flag">
<doc>
Used to indicate whether one-phase or two-phase commit is used.
</doc>
<exception name="one-phase" error-code="illegal-state">
<doc>
The one-phase bit MUST be set if a commit is sent without a preceding prepare.
</doc>
</exception>
<exception name="two-phase" error-code="illegal-state">
<doc>
The one-phase bit MUST NOT be set if the commit has been preceded by prepare.
</doc>
</exception>
</field>
<result type="xa-result">
<doc>
This confirms to the client that the transaction branch is committed or specify the
error condition.
The value of this field may be one of the following constants:
xa-ok: Normal execution
xa-heurhaz: Due to some failure, the work done on behalf of the specified transaction
branch may have been heuristically completed.
xa-heurcom: Due to a heuristic decision, the work done on behalf of the specified
transaction branch was committed.
xa-heurrb: Due to a heuristic decision, the work done on behalf of the specified
transaction branch was rolled back.
xa-heurmix: Due to a heuristic decision, the work done on behalf of the specified
transaction branch was partially committed and partially rolled back.
xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
reason.
xa-rbtimeout: The work represented by this transaction branch took too long.
</doc>
</result>
</command>
<!-- - Command: dtx.forget - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="forget" code="0x5" label="Discard dtx branch">
<doc>
This command is called to forget about a heuristically completed transaction branch.
</doc>
<exception name="illegal-state" error-code="illegal-state">
<doc>
If the command is invoked in an improper context (see class grammar) then the server MUST
raise an exception.
</doc>
</exception>
<implement role="server" handle="MAY" />
<field name="xid" type="xid" label="Transaction xid" required="true">
<doc>
Specifies the xid of the transaction branch to be forgotten.
</doc>
<exception name="unknown-xid" error-code="not-found">
<doc>
If xid is unknown (the transaction branch has not been started or has already been
ended) then the server MUST raise an exception.
</doc>
</exception>
<exception name="not-disassociated" error-code="illegal-state">
<doc>
If this command is called when xid is still associated with a session then the server
MUST raise an exception.
</doc>
</exception>
</field>
</command>
<!-- - Command: dtx.get-timeout - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="get-timeout" code="0x6" label="Obtain dtx timeout in seconds">
<doc>
This command obtains the current transaction timeout value in seconds. If set-timeout was
not used prior to invoking this command, the return value is the default timeout; otherwise,
the value used in the previous set-timeout call is returned.
</doc>
<implement role="server" handle="MAY" />
<field name="xid" type="xid" label="Transaction xid" required="true">
<doc>
Specifies the xid of the transaction branch for getting the timeout.
</doc>
<exception name="unknown-xid" error-code="not-found">
<doc>
If xid is unknown (the transaction branch has not been started or has already been
ended) then the server MUST raise an exception.
</doc>
</exception>
</field>
<result>
<struct name="get-timeout-result" size="4" code="0x2" pack="2">
<doc> Returns the value of the timeout last specified through set-timeout. </doc>
<field name="timeout" type="uint32" label="The current transaction timeout value"
required="true">
<doc> The current transaction timeout value in seconds. </doc>
</field>
</struct>
</result>
</command>
<!-- - Command: dtx.prepare - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="prepare" code="0x7" label="Prepare a dtx branch">
<doc>
This command prepares for commitment any message produced or consumed on behalf of xid.
</doc>
<exception name="illegal-state" error-code="illegal-state">
<doc>
If the command is invoked in an improper context (see class grammar) then the server MUST
raise an exception.
</doc>
</exception>
<rule name="obligation-1">
<doc>
Once this command successfully returns it is guaranteed that the transaction branch may be
either committed or rolled back regardless of failures.
</doc>
</rule>
<rule name="obligation-2">
<doc>
The knowledge of xid cannot be erased before commit or rollback complete the branch.
</doc>
</rule>
<implement role="server" handle="MAY" />
<field name="xid" type="xid" label="Transaction xid" required="true">
<doc>
Specifies the xid of the transaction branch that can be prepared.
</doc>
<exception name="unknown-xid" error-code="not-found">
<doc>
If xid is unknown (the transaction branch has not been started or has already been
ended) then the server MUST raise an exception.
</doc>
</exception>
<exception name="not-disassociated" error-code="illegal-state">
<doc>
If this command is called when xid is still associated with a session then the server
MUST raise an exception.
</doc>
</exception>
</field>
<result type="xa-result">
<doc>
This command confirms to the client that the transaction branch is prepared or specify the
error condition.
The value of this field may be one of the following constants:
xa-ok: Normal execution.
xa-rdonly: The transaction branch was read-only and has been committed.
xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
reason.
xa-rbtimeout: The work represented by this transaction branch took too long.
</doc>
</result>
</command>
<!-- - Command: dtx.recover - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="recover" code="0x8" label="Get prepared or completed xids">
<doc>
This command is called to obtain a list of transaction branches that are in a prepared or
heuristically completed state.
</doc>
<implement role="server" handle="MAY" />
<result>
<struct name="recover-result" size="4" code="0x3" pack="2">
<doc>
Returns to the client a table with single item that is a sequence of transaction xids
that are in a prepared or heuristically completed state.
</doc>
<field name="in-doubt" type="array" label="array of xids to be recovered" required="true">
<doc> Array containing the xids to be recovered (xids that are in a prepared or
heuristically completed state). </doc>
</field>
</struct>
</result>
</command>
<!-- - Command: dtx.rollback - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="rollback" code="0x9" label="Rollback a dtx branch">
<doc>
This command rolls back the work associated with xid. Any produced messages are discarded
and any consumed messages are re-enqueued.
</doc>
<exception name="illegal-state" error-code="illegal-state">
<doc>
If the command is invoked in an improper context (see class grammar) then the server MUST
raise an exception.
</doc>
</exception>
<implement role="server" handle="MAY" />
<field name="xid" type="xid" label="Transaction xid" required="true">
<doc>
Specifies the xid of the transaction branch that can be rolled back.
</doc>
<exception name="unknown-xid" error-code="not-found">
<doc>
If xid is unknown (the transaction branch has not been started or has already been
ended) then the server MUST raise an exception.
</doc>
</exception>
<exception name="not-disassociated" error-code="illegal-state">
<doc>
If this command is called when xid is still associated with a session then the server
MUST raise an exception.
</doc>
</exception>
</field>
<result type="xa-result">
<doc>
This command confirms to the client that the transaction branch is rolled back or specify
the error condition.
The value of this field may be one of the following constants:
xa-ok: Normal execution
xa-heurhaz: Due to some failure, the work done on behalf of the specified transaction
branch may have been heuristically completed.
xa-heurcom: Due to a heuristic decision, the work done on behalf of the specified
transaction branch was committed.
xa-heurrb: Due to a heuristic decision, the work done on behalf of the specified
transaction branch was rolled back.
xa-heurmix: Due to a heuristic decision, the work done on behalf of the specified
transaction branch was partially committed and partially rolled back.
xa-rbrollback: The broker marked the transaction branch rollback-only for an unspecified
reason.
xa-rbtimeout: The work represented by this transaction branch took too long.
</doc>
</result>
</command>
<!-- - Command: dtx.set-timeout - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="set-timeout" code="0xa" label="Set dtx timeout value">
<doc>
Sets the specified transaction branch timeout value in seconds.
</doc>
<rule name="effective">
<doc>
Once set, this timeout value is effective until this command is reinvoked with a different
value.
</doc>
</rule>
<rule name="reset">
<doc>
A value of zero resets the timeout value to the default value.
</doc>
</rule>
<implement role="server" handle="MAY" />
<field name="xid" type="xid" label="Transaction xid" required="true">
<doc>
Specifies the xid of the transaction branch for setting the timeout.
</doc>
<exception name="unknown-xid" error-code="not-found">
<doc>
If xid is unknown (the transaction branch has not been started or has already been
ended) then the server MUST raise an exception.
</doc>
</exception>
</field>
<field name="timeout" type="uint32" label="Dtx timeout in seconds" required="true">
<doc>
The transaction timeout value in seconds.
</doc>
</field>
</command>
</class>
<!-- == Class: exchange ====================================================================== -->
<class name="exchange" code="0x7" label="work with exchanges">
<doc>
Exchanges match and distribute messages across queues. Exchanges can be configured in the
server or created at runtime.
</doc>
<doc type="grammar">
exchange = C:DECLARE
/ C:DELETE
/ C:QUERY
</doc>
<rule name="required-types">
<doc>
The server MUST implement these standard exchange types: fanout, direct.
</doc>
<doc type="scenario">
Client attempts to declare an exchange with each of these standard types.
</doc>
</rule>
<rule name="recommended-types">
<doc>
The server SHOULD implement these standard exchange types: topic, headers.
</doc>
<doc type="scenario">
Client attempts to declare an exchange with each of these standard types.
</doc>
</rule>
<rule name="required-instances">
<doc>
The server MUST, in each virtual host, pre-declare an exchange instance for each standard
exchange type that it implements, where the name of the exchange instance, if defined, is
"amq." followed by the exchange type name.
The server MUST, in each virtual host, pre-declare at least two direct exchange instances:
one named "amq.direct", the other with no public name that serves as a default exchange for
publish commands (such as message.transfer).
</doc>
<doc type="scenario">
Client creates a temporary queue and attempts to bind to each required exchange instance
("amq.fanout", "amq.direct", "amq.topic", and "amq.headers" if those types are defined).
</doc>
</rule>
<rule name="default-exchange">
<doc>
The server MUST pre-declare a direct exchange with no public name to act as the default
exchange for content publish commands (such as message.transfer) and for default queue
bindings.
</doc>
<doc type="scenario">
Client checks that the default exchange is active by publishing a message with a suitable
routing key but without specifying the exchange name, then ensuring that the message arrives
in the queue correctly.
</doc>
</rule>
<rule name="default-access">
<doc>
The default exchange MUST NOT be accessible to the client except by specifying an empty
exchange name in a content publish command (such as message.transfer). That is, the server
must not let clients explicitly bind, unbind, delete, or make any other reference to this
exchange.
</doc>
</rule>
<rule name="extensions">
<doc>
The server MAY implement other exchange types as wanted.
</doc>
</rule>
<role name="server" implement="MUST" />
<role name="client" implement="MUST" />
<domain name="name" type="str8" label="exchange name">
<doc>
The exchange name is a client-selected string that identifies the exchange for publish
commands. Exchange names may consist of any mixture of digits, letters, and underscores.
Exchange names are scoped by the virtual host.
</doc>
</domain>
<!-- - Command: exchange.declare - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="declare" code="0x1" label="verify exchange exists, create if needed">
<doc>
This command creates an exchange if it does not already exist, and if the exchange exists,
verifies that it is of the correct and expected class.
</doc>
<rule name="minimum">
<doc>
The server SHOULD support a minimum of 16 exchanges per virtual host and ideally, impose
no limit except as defined by available resources.
</doc>
<doc type="scenario">
The client creates as many exchanges as it can until the server reports an error; the
number of exchanges successfully created must be at least sixteen.
</doc>
</rule>
<implement role="server" handle="MUST" />
<field name="exchange" type="name" required="true">
<exception name="reserved-names" error-code="not-allowed">
<doc>
Exchange names starting with "amq." are reserved for pre-declared and standardized
exchanges. The client MUST NOT attempt to create an exchange starting with "amq.".
</doc>
</exception>
<exception name="exchange-name-required" error-code="invalid-argument">
<doc>
The name of the exchange MUST NOT be a blank or empty string.
</doc>
</exception>
</field>
<field name="type" type="str8" label="exchange type" required="true">
<doc>
Each exchange belongs to one of a set of exchange types implemented by the server. The
exchange types define the functionality of the exchange - i.e. how messages are routed
through it. It is not valid or meaningful to attempt to change the type of an existing
exchange.
</doc>
<exception name="typed" error-code="not-allowed">
<doc>
Exchanges cannot be redeclared with different types. The client MUST NOT attempt to
redeclare an existing exchange with a different type than used in the original
exchange.declare command.
</doc>
</exception>
<exception name="exchange-type-not-found" error-code="not-found">
<doc>
If the client attempts to create an exchange which the server does not recognize, an
exception MUST be sent.
</doc>
</exception>
</field>
<field name="alternate-exchange" type="name" label= "exchange name for unroutable messages">
<doc>
In the event that a message cannot be routed, this is the name of the exchange to which
the message will be sent. Messages transferred using message.transfer will be routed to
the alternate-exchange only if they are sent with the "none" accept-mode, and the
discard-unroutable delivery property is set to false, and there is no queue to route to
for the given message according to the bindings on this exchange.
</doc>
<rule name="empty-name">
<doc>
If alternate-exchange is not set (its name is an empty string), unroutable messages
that would be sent to the alternate-exchange MUST be dropped silently.
</doc>
</rule>
<exception name="pre-existing-exchange" error-code="not-allowed">
<doc>
If the alternate-exchange is not empty and if the exchange already exists with a
different alternate-exchange, then the declaration MUST result in an exception.
</doc>
</exception>
<rule name="double-failure">
<doc>
A message which is being routed to a alternate exchange, MUST NOT be re-routed to a
secondary alternate exchange if it fails to route in the primary alternate exchange.
After such a failure, the message MUST be dropped. This prevents looping.
</doc>
</rule>
</field>
<field name="passive" type="bit" label="do not create exchange">
<doc>
If set, the server will not create the exchange. The client can use this to check whether
an exchange exists without modifying the server state.
</doc>
<exception name="not-found" error-code="not-found">
<doc>
If set, and the exchange does not already exist, the server MUST raise an exception.
</doc>
</exception>
</field>
<field name="durable" type="bit" label="request a durable exchange">
<doc>
If set when creating a new exchange, the exchange will be marked as durable. Durable
exchanges remain active when a server restarts. Non-durable exchanges (transient
exchanges) are purged if/when a server restarts.
</doc>
<rule name="support">
<doc>
The server MUST support both durable and transient exchanges.
</doc>
</rule>
<rule name="sticky">
<doc>
The server MUST ignore the durable field if the exchange already exists.
</doc>
</rule>
</field>
<field name="auto-delete" type="bit" label="auto-delete when unused">
<doc>
If set, the exchange is deleted automatically when there remain no bindings between the
exchange and any queue. Such an exchange will not be automatically deleted until at least
one binding has been made to prevent the immediate deletion of the exchange upon creation.
</doc>
<rule name="sticky">
<doc>
The server MUST ignore the auto-delete field if the exchange already exists.
</doc>
</rule>
</field>
<field name="arguments" type="map" label="arguments for declaration">
<doc>
A set of arguments for the declaration. The syntax and semantics of these arguments
depends on the server implementation. This field is ignored if passive is 1.
</doc>
<exception name="unknown-argument" error-code="not-implemented">
<doc>
If the arguments field contains arguments which are not understood by the server,
it MUST raise an exception.
</doc>
</exception>
</field>
</command>
<!-- - Command: exchange.delete - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="delete" code="0x2" label="delete an exchange">
<doc>
This command deletes an exchange. When an exchange is deleted all queue bindings on the
exchange are cancelled.
</doc>
<implement role="server" handle="MUST" />
<field name="exchange" type="name" required="true">
<exception name="exists" error-code="not-found">
<doc>
The client MUST NOT attempt to delete an exchange that does not exist.
</doc>
</exception>
<exception name="exchange-name-required" error-code="invalid-argument">
<doc>
The name of the exchange MUST NOT be a missing or empty string.
</doc>
</exception>
<exception name="used-as-alternate" error-code="not-allowed">
<doc>
An exchange MUST NOT be deleted if it is in use as an alternate-exchange by a queue or
by another exchange.
</doc>
</exception>
</field>
<field name="if-unused" type="bit" label="delete only if unused">
<doc>
If set, the server will only delete the exchange if it has no queue bindings. If the
exchange has queue bindings the server does not delete it but raises an exception
instead.
</doc>
<exception name="exchange-in-use" error-code="precondition-failed">
<doc>
If the exchange has queue bindings, and the if-unused flag is set, the server MUST NOT
delete the exchange, but MUST raise and exception.
</doc>
</exception>
</field>
</command>
<!-- - Command: exchange.query - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="query" code="0x3" label="request information about an exchange">
<doc>
This command is used to request information on a particular exchange.
</doc>
<implement role="server" handle="MUST" />
<field name="name" type="str8" label="the exchange name">
<doc>
The name of the exchange for which information is requested. If not specified explicitly
the default exchange is implied.
</doc>
</field>
<result>
<struct name="exchange-query-result" size="4" code="0x1" pack="2">
<doc>
This is sent in response to a query request and conveys information on a particular
exchange.
</doc>
<field name="type" type="str8" label="indicate the exchange type">
<doc>
The type of the exchange. Will be empty if the exchange is not found.
</doc>
</field>
<field name="durable" type="bit" label="indicate the durability">
<doc>
The durability of the exchange, i.e. if set the exchange is durable. Will not be set
if the exchange is not found.
</doc>
</field>
<field name="not-found" type="bit" label="indicate an unknown exchange">
<doc>
If set, the exchange for which information was requested is not known.
</doc>
</field>
<field name="arguments" type="map" label="other unspecified exchange properties">
<doc>
A set of properties of the exchange whose syntax and semantics depends on the server
implementation. Will be empty if the exchange is not found.
</doc>
</field>
</struct>
</result>
</command>
<!-- - Command: exchange.bind - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="bind" code="0x4" label="bind queue to an exchange">
<doc> This command binds a queue to an exchange. Until a queue is bound it will not receive
any messages. In a classic messaging model, store-and-forward queues are bound to a direct
exchange and subscription queues are bound to a topic exchange. </doc>
<rule name="duplicates">
<doc>
A server MUST ignore duplicate bindings - that is, two or more bind commands with the
same exchange, queue, and binding-key - without treating these as an error. The value of
the arguments used for the binding MUST NOT be altered by subsequent binding requests.
</doc>
<doc type="scenario">
A client binds a named queue to an exchange. The client then repeats the bind (with
identical exchange, queue, and binding-key). The second binding should use a different
value for the arguments field.
</doc>
</rule>
<rule name="durable-exchange">
<doc> Bindings between durable queues and durable exchanges are automatically durable and
the server MUST restore such bindings after a server restart. </doc>
<doc type="scenario"> A server creates a named durable queue and binds it to a durable
exchange. The server is restarted. The client then attempts to use the queue/exchange
combination. </doc>
</rule>
<rule name="binding-count">
<doc> The server SHOULD support at least 4 bindings per queue, and ideally, impose no limit
except as defined by available resources. </doc>
<doc type="scenario"> A client creates a named queue and attempts to bind it to 4 different
exchanges. </doc>
</rule>
<rule name="multiple-bindings">
<doc> Where more than one binding exists between a particular exchange instance and a
particular queue instance any given message published to that exchange should be delivered
to that queue at most once, regardless of how many distinct bindings match. </doc>
<doc type="scenario"> A client creates a named queue and binds it to the same topic exchange
at least three times using intersecting binding-keys (for example, "animals.*",
"animals.dogs.*", "animal.dogs.chihuahua"). Verify that a message matching all the
bindings (using previous example, routing key = "animal.dogs.chihuahua") is delivered once
only. </doc>
</rule>
<implement role="server" handle="MUST"/>
<field name="queue" type="queue.name" required="true">
<doc> Specifies the name of the queue to bind. </doc>
<exception name="empty-queue" error-code="invalid-argument">
<doc> A client MUST NOT be allowed to bind a non-existent and unnamed queue (i.e. empty
queue name) to an exchange. </doc>
<doc type="scenario"> A client attempts to bind with an unnamed (empty) queue name to an
exchange. </doc>
</exception>
<exception name="queue-existence" error-code="not-found">
<doc> A client MUST NOT be allowed to bind a non-existent queue (i.e. not previously
declared) to an exchange. </doc>
<doc type="scenario"> A client attempts to bind an undeclared queue name to an exchange.
</doc>
</exception>
</field>
<field name="exchange" type="name" label="name of the exchange to bind to" required="true">
<exception name="exchange-existence" error-code="not-found">
<doc> A client MUST NOT be allowed to bind a queue to a non-existent exchange. </doc>
<doc type="scenario"> A client attempts to bind a named queue to a undeclared exchange.
</doc>
</exception>
<exception name="exchange-name-required" error-code="invalid-argument">
<doc> The name of the exchange MUST NOT be a blank or empty string. </doc>
</exception>
</field>
<field name="binding-key" type="str8"
label="identifies a binding between a given exchange and queue" required="true">
<doc> The binding-key uniquely identifies a binding between a given (exchange, queue) pair.
Depending on the exchange configuration, the binding key may be matched against the
message routing key in order to make routing decisions. The match algorithm depends on the
exchange type. Some exchange types may ignore the binding key when making routing
decisions. Refer to the specific exchange type documentation. The meaning of an empty
binding key depends on the exchange implementation. </doc>
</field>
<field name="arguments" type="map" label="arguments for binding">
<doc> A set of arguments for the binding. The syntax and semantics of these arguments
depends on the exchange class. </doc>
<exception name="unknown-argument" error-code="not-implemented">
<doc> If the arguments field contains arguments which are not understood by the server, it
MUST raise an exception. </doc>
</exception>
</field>
</command>
<!-- - Command: exchange.unbind - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="unbind" code="0x5" label="unbind a queue from an exchange">
<doc>
This command unbinds a queue from an exchange.
</doc>
<implement role="server" handle="MUST" />
<field name="queue" type="queue.name" required="true">
<doc>
Specifies the name of the queue to unbind.
</doc>
<exception name="non-existent-queue" error-code="not-found">
<doc>
If the queue does not exist the server MUST raise an exception.
</doc>
</exception>
</field>
<field name="exchange" type="name" required="true">
<doc>
The name of the exchange to unbind from.
</doc>
<exception name="non-existent-exchange" error-code="not-found">
<doc>
If the exchange does not exist the server MUST raise an exception.
</doc>
</exception>
<exception name="exchange-name-required" error-code="invalid-argument">
<doc>
The name of the exchange MUST NOT be a blank or empty string.
</doc>
</exception>
</field>
<field name="binding-key" type="str8" label="the key of the binding" required="true">
<doc>
Specifies the binding-key of the binding to unbind.
</doc>
<exception name="non-existent-binding-key" error-code="not-found">
<doc>
If there is no matching binding-key the server MUST raise an exception.
</doc>
</exception>
</field>
</command>
<!-- - Command: exchange.bound - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="bound" code="0x6" label="request information about bindings to an exchange">
<doc>
This command is used to request information on the bindings to a particular exchange.
</doc>
<implement role="server" handle="MUST" />
<field name="exchange" type="str8" label="the exchange name">
<doc>
The name of the exchange for which binding information is being requested. If not
specified explicitly the default exchange is implied.
</doc>
</field>
<field name="queue" type="str8" label="a queue name" required="true">
<doc>
If populated then determine whether the given queue is bound to the exchange.
</doc>
</field>
<field name="binding-key" type="str8" label="a binding-key">
<doc>
If populated defines the binding-key of the binding of interest, if not populated the
request will ignore the binding-key on bindings when searching for a match.
</doc>
</field>
<field name="arguments" type="map" label="a set of binding arguments">
<doc>
If populated defines the arguments of the binding of interest if not populated the request
will ignore the arguments on bindings when searching for a match
</doc>
</field>
<result>
<struct name="exchange-bound-result" size="4" code="0x2" pack="2">
<field name="exchange-not-found" type="bit" label="indicate an unknown exchange">
<doc>
If set, the exchange for which information was requested is not known.
</doc>
</field>
<field name="queue-not-found" type="bit" label="indicate an unknown queue">
<doc>
If set, the queue specified is not known.
</doc>
</field>
<field name="queue-not-matched" type="bit" label="indicate no matching queue">
<doc>
A bit which if set indicates that no binding was found from the specified exchange to
the specified queue.
</doc>
</field>
<field name="key-not-matched" type="bit" label="indicate no matching binding-key">
<doc>
A bit which if set indicates that no binding was found from the specified exchange
with the specified binding-key.
</doc>
</field>
<field name="args-not-matched" type="bit" label="indicate no matching arguments">
<doc>
A bit which if set indicates that no binding was found from the specified exchange
with the specified arguments.
</doc>
</field>
</struct>
</result>
</command>
</class>
<!-- == Class: queue ========================================================================= -->
<class name="queue" code="0x8" label="work with queues">
<doc>
Queues store and forward messages. Queues can be configured in the server or created at
runtime. Queues must be attached to at least one exchange in order to receive messages from
publishers.
</doc>
<doc type="grammar">
queue = C:DECLARE
/ C:BIND
/ C:PURGE
/ C:DELETE
/ C:QUERY
/ C:UNBIND
</doc>
<rule name="any-content">
<doc>
A server MUST allow any content class to be sent to any queue, in any mix, and queue and
deliver these content classes independently. Note that all commands that fetch content off
queues are specific to a given content class.
</doc>
<doc type="scenario">
Client creates an exchange of each standard type and several queues that it binds to each
exchange. It must then successfully send each of the standard content types to each of the
available queues.
</doc>
</rule>
<role name="server" implement="MUST" />
<role name="client" implement="MUST" />
<domain name="name" type="str8" label="queue name">
<doc>
The queue name identifies the queue within the virtual host. Queue names must have a length
of between 1 and 255 characters inclusive, must start with a digit, letter or underscores
('_') character, and must be otherwise encoded in UTF-8.
</doc>
</domain>
<!-- - Command: queue.declare - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="declare" code="0x1" label="declare queue">
<doc>
This command creates or checks a queue. When creating a new queue the client can specify
various properties that control the durability of the queue and its contents, and the level
of sharing for the queue.
</doc>
<rule name="default-binding">
<doc>
The server MUST create a default binding for a newly-created queue to the default
exchange, which is an exchange of type 'direct' and use the queue name as the binding-key.
</doc>
<doc type="scenario">
Client creates a new queue, and then without explicitly binding it to an exchange,
attempts to send a message through the default exchange binding, i.e. publish a message to
the empty exchange, with the queue name as binding-key.
</doc>
</rule>
<rule name="minimum-queues">
<doc>
The server SHOULD support a minimum of 256 queues per virtual host and ideally, impose no
limit except as defined by available resources.
</doc>
<doc type="scenario">
Client attempts to create as many queues as it can until the server reports an error. The
resulting count must at least be 256.
</doc>
</rule>
<implement role="server" handle="MUST" />
<field name="queue" type="name" required="true">
<exception name="reserved-prefix" error-code="not-allowed">
<doc>
Queue names starting with "amq." are reserved for pre-declared and standardized server
queues. A client MUST NOT attempt to declare a queue with a name that starts with "amq."
and the passive option set to zero.
</doc>
<doc type="scenario">
A client attempts to create a queue with a name starting with "amq." and with the
passive option set to zero.
</doc>
</exception>
</field>
<field name="alternate-exchange" type="exchange.name"
label= "exchange name for messages with exceptions">
<doc>
The alternate-exchange field specifies how messages on this queue should be treated when
they are rejected by a subscriber, or when they are orphaned by queue deletion. When
present, rejected or orphaned messages MUST be routed to the alternate-exchange. In all
cases the messages MUST be removed from the queue.
</doc>
<exception name="pre-existing-exchange" error-code="not-allowed">
<doc>
If the alternate-exchange is not empty and if the queue already exists with a different
alternate-exchange, then the declaration MUST result in an exception.
</doc>
</exception>
<exception name="unknown-exchange" error-code="not-found">
<doc>
if the alternate-exchange does not match the name of any existing exchange on the
server, then an exception must be raised.
</doc>
</exception>
</field>
<field name="passive" type="bit" label="do not create queue">
<doc>
If set, the server will not create the queue. This field allows the client to assert the
presence of a queue without modifying the server state.
</doc>
<exception name="passive" error-code="not-found">
<doc>
The client MAY ask the server to assert that a queue exists without creating the queue
if not. If the queue does not exist, the server treats this as a failure.
</doc>
<doc type="scenario">
Client declares an existing queue with the passive option and expects the command to
succeed. Client then attempts to declare a non-existent queue with the passive option,
and the server must close the session with the correct exception.
</doc>
</exception>
</field>
<field name="durable" type="bit" label="request a durable queue">
<doc>
If set when creating a new queue, the queue will be marked as durable. Durable queues
remain active when a server restarts. Non-durable queues (transient queues) are purged
if/when a server restarts. Note that durable queues do not necessarily hold persistent
messages, although it does not make sense to send persistent messages to a transient
queue.
</doc>
<rule name="persistence">
<doc>
The queue definition MUST survive the server losing all transient memory, e.g. a
machine restart.
</doc>
<doc type="scenario">
Client creates a durable queue; server is then restarted. Client then attempts to send
message to the queue. The message should be successfully delivered.
</doc>
</rule>
<rule name="types">
<doc>
The server MUST support both durable and transient queues.
</doc>
<doc type="scenario">
A client creates two named queues, one durable and one transient.
</doc>
</rule>
<rule name="pre-existence">
<doc>
The server MUST ignore the durable field if the queue already exists.
</doc>
<doc type="scenario">
A client creates two named queues, one durable and one transient. The client then
attempts to declare the two queues using the same names again, but reversing the value
of the durable flag in each case. Verify that the queues still exist with the original
durable flag values.
</doc>
</rule>
</field>
<field name="exclusive" type="bit" label="request an exclusive queue">
<doc>
Exclusive queues can only be used from one session at a time. Once a session
declares an exclusive queue, that queue cannot be used by any other session until the
declaring session closes.
</doc>
<rule name="types">
<doc>
The server MUST support both exclusive (private) and non-exclusive (shared) queues.
</doc>
<doc type="scenario">
A client creates two named queues, one exclusive and one non-exclusive.
</doc>
</rule>
<exception name="in-use" error-code="resource-locked">
<doc>
If the server receives a declare, bind, consume or get request for a queue that has been
declared as exclusive by an existing client session, it MUST raise an exception.
</doc>
<doc type="scenario">
A client declares an exclusive named queue. A second client on a different session
attempts to declare a queue of the same name.
</doc>
</exception>
</field>
<field name="auto-delete" type="bit" label="auto-delete queue when unused">
<doc>
If this field is set and the exclusive field is also set, then the queue MUST be deleted
when the session closes.
If this field is set and the exclusive field is not set the queue is deleted when all
the consumers have finished using it. Last consumer can be cancelled either explicitly
or because its session is closed. If there was no consumer ever on the queue, it won't
be deleted.
</doc>
<rule name="pre-existence">
<doc>
The server MUST ignore the auto-delete field if the queue already exists.
</doc>
<doc type="scenario">
A client creates two named queues, one as auto-delete and one explicit-delete. The
client then attempts to declare the two queues using the same names again, but reversing
the value of the auto-delete field in each case. Verify that the queues still exist with
the original auto-delete flag values.
</doc>
</rule>
</field>
<field name="arguments" type="map" label="arguments for declaration">
<doc>
A set of arguments for the declaration. The syntax and semantics of these arguments
depends on the server implementation. This field is ignored if passive is 1.
</doc>
<exception name="unknown-argument" error-code="not-implemented">
<doc>
If the arguments field contains arguments which are not understood by the server,
it MUST raise an exception.
</doc>
</exception>
</field>
</command>
<!-- - Command: queue.delete - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="delete" code="0x2" label="delete a queue">
<doc>
This command deletes a queue. When a queue is deleted any pending messages are sent to the
alternate-exchange if defined, or discarded if it is not.
</doc>
<implement role="server" handle="MUST" />
<field name="queue" type="name" required="true">
<doc>
Specifies the name of the queue to delete.
</doc>
<exception name="empty-name" error-code="invalid-argument">
<doc>
If the queue name in this command is empty, the server MUST raise an exception.
</doc>
</exception>
<exception name="queue-exists" error-code="not-found">
<doc>
The queue must exist. If the client attempts to delete a non-existing queue the server
MUST raise an exception.
</doc>
</exception>
</field>
<field name="if-unused" type="bit" label="delete only if unused">
<doc>
If set, the server will only delete the queue if it has no consumers. If the queue has
consumers the server does does not delete it but raises an exception instead.
</doc>
<exception name="if-unused-flag" error-code="precondition-failed">
<doc>
The server MUST respect the if-unused flag when deleting a queue.
</doc>
</exception>
</field>
<field name="if-empty" type="bit" label="delete only if empty">
<doc>
If set, the server will only delete the queue if it has no messages.
</doc>
<exception name="not-empty" error-code="precondition-failed">
<doc>
If the queue is not empty the server MUST raise an exception.
</doc>
</exception>
</field>
</command>
<!-- - Command: queue.purge - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="purge" code="0x3" label="purge a queue">
<doc>
This command removes all messages from a queue. It does not cancel subscribers. Purged
messages are deleted without any formal "undo" mechanism.
</doc>
<rule name="empty">
<doc>
A call to purge MUST result in an empty queue.
</doc>
</rule>
<rule name="pending-messages">
<doc>
The server MUST NOT purge messages that have already been sent to a client but not yet
accepted.
</doc>
</rule>
<rule name="purge-recovery">
<doc>
The server MAY implement a purge queue or log that allows system administrators to recover
accidentally-purged messages. The server SHOULD NOT keep purged messages in the same
storage spaces as the live messages since the volumes of purged messages may get very
large.
</doc>
</rule>
<implement role="server" handle="MUST" />
<field name="queue" type="name" required="true">
<doc>
Specifies the name of the queue to purge.
</doc>
<exception name="empty-name" error-code="invalid-argument">
<doc>
If the the queue name in this command is empty, the server MUST raise an exception.
</doc>
</exception>
<exception name="queue-exists" error-code="not-found">
<doc>
The queue MUST exist. Attempting to purge a non-existing queue MUST cause an exception.
</doc>
</exception>
</field>
</command>
<!-- - Command: queue.query - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="query" code="0x4" label="request information about a queue">
<doc>
This command requests information about a queue.
</doc>
<implement role="server" handle="MUST" />
<field name="queue" type="name" label="the queried queue" required="true"/>
<result>
<struct name="queue-query-result" size="4" code="0x1" pack="2">
<doc>
This is sent in response to queue.query, and conveys the requested information about a
queue. If no queue with the specified name exists then none of the fields within the
returned result struct will be populated.
</doc>
<field name="queue" type="name" required="true">
<doc>
Reports the name of the queue.
</doc>
</field>
<field name="alternate-exchange" type="exchange.name" />
<field name="durable" type="bit" />
<field name="exclusive" type="bit" />
<field name="auto-delete" type="bit" />
<field name="arguments" type="map" />
<field name="message-count" type="uint32" label="number of messages in queue"
required="true">
<doc> Reports the number of messages in the queue. </doc>
</field>
<field name="subscriber-count" type="uint32" label="number of subscribers"
required="true">
<doc>
Reports the number of subscribers for the queue.
</doc>
</field>
</struct>
</result>
</command>
</class>
<!-- == Class: file ========================================================================== -->
<class name="file" code="0x9" label="work with file content">
<doc>
The file class provides commands that support reliable file transfer. File messages have a
specific set of properties that are required for interoperability with file transfer
applications. File messages and acknowledgements are subject to session transactions. Note
that the file class does not provide message browsing commands; these are not compatible with
the staging model. Applications that need browsable file transfer should use Message content
and the Message class.
</doc>
<doc type="grammar">
file = C:QOS S:QOS-OK
/ C:CONSUME S:CONSUME-OK
/ C:CANCEL
/ C:OPEN S:OPEN-OK C:STAGE content
/ S:OPEN C:OPEN-OK S:STAGE content
/ C:PUBLISH
/ S:DELIVER
/ S:RETURN
/ C:ACK
/ C:REJECT
</doc>
<rule name="reliable-storage">
<doc>
The server MUST make a best-effort to hold file messages on a reliable storage mechanism.
</doc>
</rule>
<rule name="no-discard">
<doc>
The server MUST NOT discard a file message in case of a queue overflow. The server MUST use
the Session.Flow command to slow or stop a file message publisher when necessary.
</doc>
</rule>
<rule name="priority-levels">
<doc>
The server MUST implement at least 2 priority levels for file messages, where priorities 0-4
and 5-9 are treated as two distinct levels. The server MAY implement up to 10 priority
levels.
</doc>
</rule>
<rule name="acknowledgement-support">
<doc>
The server MUST support both automatic and explicit acknowledgements on file content.
</doc>
</rule>
<role name="server" implement="MAY" />
<role name="client" implement="MAY" />
<!-- These are the properties for a File content -->
<struct name="file-properties" size="4" code="0x1" pack="2">
<field name="content-type" type="str8" label="MIME content type" />
<field name="content-encoding" type="str8" label="MIME content encoding" />
<field name="headers" type="map" label="message header field table" />
<field name="priority" type="uint8" label="message priority, 0 to 9" />
<field name="reply-to" type="str8" label="destination to reply to" />
<field name="message-id" type="str8" label="application message identifier" />
<field name="filename" type="str8" label="message filename" />
<field name="timestamp" type="datetime" label="message timestamp" />
<!-- This field is deprecated pending review -->
<field name="cluster-id" type="str8" label="intra-cluster routing identifier" />
</struct>
<domain name="return-code" type="uint16" label="return code from server">
<doc>
The return code. The AMQP return codes are defined by this enum.
</doc>
<enum>
<choice name="content-too-large" value="311">
<doc>
The client attempted to transfer content larger than the server could accept.
</doc>
</choice>
<choice name="no-route" value="312">
<doc>
The exchange cannot route a message, most likely due to an invalid routing key. Only
when the mandatory flag is set.
</doc>
</choice>
<choice name="no-consumers" value="313">
<doc>
The exchange cannot deliver to a consumer when the immediate flag is set. As a result of
pending data on the queue or the absence of any consumers of the queue.
</doc>
</choice>
</enum>
</domain>
<!-- - Command: file.qos - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="qos" code="0x1" label="specify quality of service">
<doc>
This command requests a specific quality of service. The QoS can be specified for the
current session or for all sessions on the connection. The particular properties and
semantics of a qos command always depend on the content class semantics. Though the qos
command could in principle apply to both peers, it is currently meaningful only for the
server.
</doc>
<implement role="server" handle="MUST" />
<response name="qos-ok" />
<field name="prefetch-size" type="uint32" label="pre-fetch window in octets">
<doc>
The client can request that messages be sent in advance so that when the client finishes
processing a message, the following message is already held locally, rather than needing
to be sent within the session. Pre-fetching gives a performance improvement. This field
specifies the pre-fetch window size in octets. May be set to zero, meaning "no specific
limit". Note that other pre-fetch limits may still apply. The prefetch-size is ignored if
the no-ack option is set.
</doc>
</field>
<field name="prefetch-count" type="uint16" label="pre-fetch window in messages">
<doc>
Specifies a pre-fetch window in terms of whole messages. This is compatible with some file
API implementations. This field may be used in combination with the prefetch-size field; a
message will only be sent in advance if both pre-fetch windows (and those at the session
and connection level) allow it. The prefetch-count is ignored if the no-ack option is set.
</doc>
<rule name="prefetch-discretion">
<doc>
The server MAY send less data in advance than allowed by the client's specified
pre-fetch windows but it MUST NOT send more.
</doc>
</rule>
</field>
<field name="global" type="bit" label="apply to entire connection">
<doc>
By default the QoS settings apply to the current session only. If this field is set, they
are applied to the entire connection.
</doc>
</field>
</command>
<!-- - Command: file.qos-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="qos-ok" code="0x2" label="confirm the requested qos">
<doc>
This command tells the client that the requested QoS levels could be handled by the server.
The requested QoS applies to all active consumers until a new QoS is defined.
</doc>
<implement role="client" handle="MUST" />
</command>
<!-- - Command: file.consume - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="consume" code="0x3" label="start a queue consumer">
<doc>
This command asks the server to start a "consumer", which is a transient request for
messages from a specific queue. Consumers last as long as the session they were created on,
or until the client cancels them.
</doc>
<rule name="min-consumers">
<doc>
The server SHOULD support at least 16 consumers per queue, unless the queue was declared
as private, and ideally, impose no limit except as defined by available resources.
</doc>
</rule>
<implement role="server" handle="MUST" />
<response name="consume-ok" />
<field name="queue" type="queue.name">
<doc>
Specifies the name of the queue to consume from.
</doc>
<exception name="queue-exists-if-empty" error-code="not-allowed">
<doc>
If the queue name in this command is empty, the server MUST raise an exception.
</doc>
</exception>
</field>
<field name="consumer-tag" type="str8">
<doc>
Specifies the identifier for the consumer. The consumer tag is local to a connection, so
two clients can use the same consumer tags.
</doc>
<exception name="not-existing-consumer" error-code="not-allowed">
<doc>
The tag MUST NOT refer to an existing consumer. If the client attempts to create two
consumers with the same non-empty tag the server MUST raise an exception.
</doc>
</exception>
<exception name="not-empty-consumer-tag" error-code="not-allowed">
<doc>
The client MUST NOT specify a tag that is empty or blank.
</doc>
<doc type="scenario">
Attempt to create a consumers with an empty tag.
</doc>
</exception>
</field>
<field name="no-local" type="bit">
<doc>If the no-local field is set the server will not send messages to the connection that
published them.</doc>
</field>
<field name="no-ack" type="bit" label="no acknowledgement needed">
<doc>
If this field is set the server does not expect acknowledgements for messages. That is,
when a message is delivered to the client the server automatically and silently
acknowledges it on behalf of the client. This functionality increases performance but at
the cost of reliability. Messages can get lost if a client dies before it can deliver them
to the application.
</doc>
</field>
<field name="exclusive" type="bit" label="request exclusive access">
<doc>
Request exclusive consumer access, meaning only this consumer can access the queue.
</doc>
<exception name="in-use" error-code="resource-locked">
<doc>
If the server cannot grant exclusive access to the queue when asked, - because there are
other consumers active - it MUST raise an exception.
</doc>
</exception>
</field>
<field name="nowait" type="bit" label="do not send a reply command">
<doc>
If set, the server will not respond to the command. The client should not wait for a reply
command. If the server could not complete the command it will raise an exception.
</doc>
</field>
<field name="arguments" type="map" label="arguments for consuming">
<doc>
A set of arguments for the consume. The syntax and semantics of these arguments depends on
the providers implementation.
</doc>
</field>
</command>
<command name="consume-ok" code="0x4" label="confirm a new consumer">
<doc>
This command provides the client with a consumer tag which it MUST use in commands that work
with the consumer.
</doc>
<implement role="client" handle="MUST" />
<field name="consumer-tag" type="str8">
<doc>
Holds the consumer tag specified by the client or provided by the server.
</doc>
</field>
</command>
<!-- - Command: file.cancel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="cancel" code="0x5" label="end a queue consumer">
<doc>
This command cancels a consumer. This does not affect already delivered messages, but it
does mean the server will not send any more messages for that consumer.
</doc>
<implement role="server" handle="MUST" />
<field name="consumer-tag" type="str8">
<doc>
the identifier of the consumer to be cancelled.
</doc>
</field>
</command>
<!-- - Command: file.open - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="open" code="0x6" label="request to start staging">
<doc>
This command requests permission to start staging a message. Staging means sending the
message into a temporary area at the recipient end and then delivering the message by
referring to this temporary area. Staging is how the protocol handles partial file transfers
- if a message is partially staged and the connection breaks, the next time the sender
starts to stage it, it can restart from where it left off.
</doc>
<implement role="server" handle="MUST" />
<implement role="client" handle="MUST" />
<response name="open-ok" />
<field name="identifier" type="str8" label="staging identifier">
<doc>
This is the staging identifier. This is an arbitrary string chosen by the sender. For
staging to work correctly the sender must use the same staging identifier when staging the
same message a second time after recovery from a failure. A good choice for the staging
identifier would be the SHA1 hash of the message properties data (including the original
filename, revised time, etc.).
</doc>
</field>
<field name="content-size" type="uint64" label="message content size">
<doc>
The size of the content in octets. The recipient may use this information to allocate or
check available space in advance, to avoid "disk full" errors during staging of very large
messages.
</doc>
<rule name="content-size">
<doc>
The sender MUST accurately fill the content-size field. Zero-length content is
permitted.
</doc>
</rule>
</field>
</command>
<!-- - Command: file.open-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="open-ok" code="0x7" label="confirm staging ready">
<doc>
This command confirms that the recipient is ready to accept staged data. If the message was
already partially-staged at a previous time the recipient will report the number of octets
already staged.
</doc>
<implement role="server" handle="MUST" />
<implement role="client" handle="MUST" />
<response name="stage" />
<field name="staged-size" type="uint64" label="already staged amount">
<doc>
The amount of previously-staged content in octets. For a new message this will be zero.
</doc>
<rule name="behavior">
<doc>
The sender MUST start sending data from this octet offset in the message, counting from
zero.
</doc>
</rule>
<rule name="staging">
<doc>
The recipient MAY decide how long to hold partially-staged content and MAY implement
staging by always discarding partially-staged content. However if it uses the file
content type it MUST support the staging commands.
</doc>
</rule>
</field>
</command>
<!-- - Command: file.stage - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="stage" code="0x8" label="stage message content">
<doc>
This command stages the message, sending the message content to the recipient from the octet
offset specified in the Open-Ok command.
</doc>
<implement role="server" handle="MUST" />
<implement role="client" handle="MUST" />
<segments>
<header required="true">
<entry type="file-properties"/>
</header>
<body/>
</segments>
</command>
<!-- - Command: file.publish - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="publish" code="0x9" label="publish a message">
<doc>
This command publishes a staged file message to a specific exchange. The file message will
be routed to queues as defined by the exchange configuration and distributed to any active
consumers when the transaction, if any, is committed.
</doc>
<implement role="server" handle="MUST" />
<field name="exchange" type="exchange.name">
<doc>
Specifies the name of the exchange to publish to. The exchange name can be empty, meaning
the default exchange. If the exchange name is specified, and that exchange does not exist,
the server will raise an exception.
</doc>
<rule name="default">
<doc>
The server MUST accept a blank exchange name to mean the default exchange.
</doc>
</rule>
<exception name="refusal" error-code="not-implemented">
<doc>
The exchange MAY refuse file content in which case it MUST send an exception.
</doc>
</exception>
</field>
<field name="routing-key" type="str8" label="Message routing key">
<doc>
Specifies the routing key for the message. The routing key is used for routing messages
depending on the exchange configuration.
</doc>
</field>
<field name="mandatory" type="bit" label="indicate mandatory routing">
<doc>
This flag tells the server how to react if the message cannot be routed to a queue. If
this flag is set, the server will return an unroutable message with a Return command. If
this flag is zero, the server silently drops the message.
</doc>
<rule name="implementation">
<doc>
The server SHOULD implement the mandatory flag.
</doc>
</rule>
</field>
<field name="immediate" type="bit" label="request immediate delivery">
<doc>
This flag tells the server how to react if the message cannot be routed to a queue
consumer immediately. If this flag is set, the server will return an undeliverable message
with a Return command. If this flag is zero, the server will queue the message, but with
no guarantee that it will ever be consumed.
</doc>
<rule name="implementation">
<doc>
The server SHOULD implement the immediate flag.
</doc>
</rule>
</field>
<field name="identifier" type="str8" label="staging identifier">
<doc>
This is the staging identifier of the message to publish. The message must have been
staged. Note that a client can send the Publish command asynchronously without waiting for
staging to finish.
</doc>
</field>
</command>
<!-- - Command: file.return - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="return" code="0xa" label="return a failed message">
<doc>
This command returns an undeliverable message that was published with the "immediate" flag
set, or an unroutable message published with the "mandatory" flag set. The reply code and
text provide information about the reason that the message was undeliverable.
</doc>
<implement role="client" handle="MUST" />
<field name="reply-code" type="return-code" />
<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>
<field name="exchange" type="exchange.name">
<doc>
Specifies the name of the exchange that the message was originally published to.
</doc>
</field>
<field name="routing-key" type="str8" label="Message routing key">
<doc>
Specifies the routing key name specified when the message was published.
</doc>
</field>
<segments>
<header required="true">
<entry type="file-properties"/>
</header>
<body/>
</segments>
</command>
<!-- - Command: file.deliver - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="deliver" code="0xb" label="notify the client of a consumer message">
<doc>
This command delivers a staged file message to the client, via a consumer. In the
asynchronous message delivery model, the client starts a consumer using the consume command,
then the server responds with Deliver commands as and when messages arrive for that
consumer.
</doc>
<rule name="redelivery-tracking">
<doc>
The server SHOULD track the number of times a message has been delivered to clients and
when a message is redelivered a certain number of times - e.g. 5 times - without being
acknowledged, the server SHOULD consider the message to be non-processable (possibly
causing client applications to abort), and move the message to a dead letter queue.
</doc>
</rule>
<implement role="client" handle="MUST" />
<field name="consumer-tag" type="str8" />
<field name="delivery-tag" type="uint64" >
<doc>
The server-assigned and session-specific delivery tag
</doc>
<rule name="non-zero">
<doc>
The server MUST NOT use a zero value for delivery tags. Zero is reserved for client use,
meaning "all messages so far received".
</doc>
</rule>
</field>
<field name="redelivered" type="bit" label="Indicate possible duplicate delivery">
<doc>
This boolean flag indicates that the message may have been previously delivered to this
or another client.
</doc>
</field>
<field name="exchange" type="exchange.name">
<doc>
Specifies the name of the exchange that the message was originally published to.
</doc>
</field>
<field name="routing-key" type="str8" label="Message routing key">
<doc>
Specifies the routing key name specified when the message was published.
</doc>
</field>
<field name="identifier" type="str8" label="staging identifier">
<doc>
This is the staging identifier of the message to deliver. The message must have been
staged. Note that a server can send the Deliver command asynchronously without waiting for
staging to finish.
</doc>
</field>
</command>
<!-- - Command: file.ack - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="ack" code="0xc" label="acknowledge one or more messages">
<doc>
This command acknowledges one or more messages delivered via the Deliver command. The client
can ask to confirm a single message or a set of messages up to and including a specific
message.
</doc>
<implement role="server" handle="MUST" />
<field name="delivery-tag" type="uint64" >
<doc>
The identifier of the message being acknowledged
</doc>
<rule name="session-local">
<doc>
The delivery tag is valid only within the session from which the message was received.
i.e. A client MUST NOT receive a message on one session and then acknowledge it on
another.
</doc>
</rule>
</field>
<field name="multiple" type="bit" label="acknowledge multiple messages">
<doc>
If set to 1, the delivery tag is treated as "up to and including", so that the client can
acknowledge multiple messages with a single command. If set to zero, the delivery tag
refers to a single message. If the multiple field is 1, and the delivery tag is zero,
tells the server to acknowledge all outstanding messages.
</doc>
<rule name="validation">
<doc>
The server MUST validate that a non-zero delivery-tag refers to an delivered message,
and raise an exception if this is not the case.
</doc>
</rule>
</field>
</command>
<!-- - Command: file.reject - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="reject" code="0xd" label="reject an incoming message">
<doc>
This command allows a client to reject a message. It can be used to return untreatable
messages to their original queue. Note that file content is staged before delivery, so the
client will not use this command to interrupt delivery of a large message.
</doc>
<rule name="server-interpretation">
<doc>
The server SHOULD interpret this command as meaning that the client is unable to process
the message at this time.
</doc>
</rule>
<rule name="not-selection">
<doc>
A client MUST NOT use this command as a means of selecting messages to process. A rejected
message MAY be discarded or dead-lettered, not necessarily passed to another client.
</doc>
</rule>
<implement role="server" handle="MUST" />
<field name="delivery-tag" type="uint64">
<doc>
the identifier of the message to be rejected
</doc>
<rule name="session-local">
<doc>
The delivery tag is valid only within the session from which the message was received.
i.e. A client MUST NOT receive a message on one session and then reject it on another.
</doc>
</rule>
</field>
<field name="requeue" type="bit" label="requeue the message">
<doc>
If this field is zero, the message will be discarded. If this bit is 1, the server will
attempt to requeue the message.
</doc>
<rule name="requeue-strategy">
<doc>
The server MUST NOT deliver the message to the same client within the context of the
current session. The recommended strategy is to attempt to deliver the message to an
alternative consumer, and if that is not possible, to move the message to a dead-letter
queue. The server MAY use more sophisticated tracking to hold the message on the queue
and redeliver it to the same client at a later stage.
</doc>
</rule>
</field>
</command>
</class>
<!-- == Class: stream ======================================================================== -->
<class name="stream" code="0xa" label="work with streaming content">
<doc>
The stream class provides commands that support multimedia streaming. The stream class uses
the following semantics: one message is one packet of data; delivery is unacknowledged and
unreliable; the consumer can specify quality of service parameters that the server can try to
adhere to; lower-priority messages may be discarded in favor of high priority messages.
</doc>
<doc type="grammar">
stream = C:QOS S:QOS-OK
/ C:CONSUME S:CONSUME-OK
/ C:CANCEL
/ C:PUBLISH content
/ S:RETURN
/ S:DELIVER content
</doc>
<rule name="overflow-discard">
<doc>
The server SHOULD discard stream messages on a priority basis if the queue size exceeds some
configured limit.
</doc>
</rule>
<rule name="priority-levels">
<doc>
The server MUST implement at least 2 priority levels for stream messages, where priorities
0-4 and 5-9 are treated as two distinct levels. The server MAY implement up to 10 priority
levels.
</doc>
</rule>
<rule name="acknowledgement-support">
<doc>
The server MUST implement automatic acknowledgements on stream content. That is, as soon as
a message is delivered to a client via a Deliver command, the server must remove it from the
queue.
</doc>
</rule>
<role name="server" implement="MAY" />
<role name="client" implement="MAY" />
<!-- These are the properties for a Stream content -->
<struct name="stream-properties" size="4" code="0x1" pack="2">
<field name="content-type" type="str8" label="MIME content type" />
<field name="content-encoding" type="str8" label="MIME content encoding" />
<field name="headers" type="map" label="message header field table" />
<field name="priority" type="uint8" label="message priority, 0 to 9" />
<field name="timestamp" type="datetime" label="message timestamp" />
</struct>
<domain name="return-code" type="uint16" label="return code from server">
<doc>
The return code. The AMQP return codes are defined by this enum.
</doc>
<enum>
<choice name="content-too-large" value="311">
<doc>
The client attempted to transfer content larger than the server could accept.
</doc>
</choice>
<choice name="no-route" value="312">
<doc>
The exchange cannot route a message, most likely due to an invalid routing key. Only
when the mandatory flag is set.
</doc>
</choice>
<choice name="no-consumers" value="313">
<doc>
The exchange cannot deliver to a consumer when the immediate flag is set. As a result of
pending data on the queue or the absence of any consumers of the queue.
</doc>
</choice>
</enum>
</domain>
<!-- - Command: stream.qos - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="qos" code="0x1" label="specify quality of service">
<doc>
This command requests a specific quality of service. The QoS can be specified for the
current session or for all sessions on the connection. The particular properties and
semantics of a qos command always depend on the content class semantics. Though the qos
command could in principle apply to both peers, it is currently meaningful only for the
server.
</doc>
<implement role="server" handle="MUST" />
<response name="qos-ok" />
<field name="prefetch-size" type="uint32" label="pre-fetch window in octets">
<doc>
The client can request that messages be sent in advance so that when the client finishes
processing a message, the following message is already held locally, rather than needing
to be sent within the session. Pre-fetching gives a performance improvement. This field
specifies the pre-fetch window size in octets. May be set to zero, meaning "no specific
limit". Note that other pre-fetch limits may still apply.
</doc>
</field>
<field name="prefetch-count" type="uint16" label="pre-fetch window in messages">
<doc>
Specifies a pre-fetch window in terms of whole messages. This field may be used in
combination with the prefetch-size field; a message will only be sent in advance if both
pre-fetch windows (and those at the session and connection level) allow it.
</doc>
</field>
<field name="consume-rate" type="uint32" label="transfer rate in octets/second">
<doc>
Specifies a desired transfer rate in octets per second. This is usually determined by the
application that uses the streaming data. A value of zero means "no limit", i.e. as
rapidly as possible.
</doc>
<rule name="ignore-prefetch">
<doc>
The server MAY ignore the pre-fetch values and consume rates, depending on the type of
stream and the ability of the server to queue and/or reply it.
</doc>
</rule>
<rule name="drop-by-priority">
<doc>
The server MAY drop low-priority messages in favor of high-priority messages.
</doc>
</rule>
</field>
<field name="global" type="bit" label="apply to entire connection">
<doc>
By default the QoS settings apply to the current session only. If this field is set, they
are applied to the entire connection.
</doc>
</field>
</command>
<!-- - Command: stream.qos-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="qos-ok" code="0x2" label="confirm the requested qos">
<doc>
This command tells the client that the requested QoS levels could be handled by the server.
The requested QoS applies to all active consumers until a new QoS is defined.
</doc>
<implement role="client" handle="MUST" />
</command>
<!-- - Command: stream.consume - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="consume" code="0x3" label="start a queue consumer">
<doc>
This command asks the server to start a "consumer", which is a transient request for
messages from a specific queue. Consumers last as long as the session they were created on,
or until the client cancels them.
</doc>
<rule name="min-consumers">
<doc>
The server SHOULD support at least 16 consumers per queue, unless the queue was declared
as private, and ideally, impose no limit except as defined by available resources.
</doc>
</rule>
<rule name="priority-based-delivery">
<doc>
Streaming applications SHOULD use different sessions to select different streaming
resolutions. AMQP makes no provision for filtering and/or transforming streams except on
the basis of priority-based selective delivery of individual messages.
</doc>
</rule>
<implement role="server" handle="MUST" />
<response name="consume-ok" />
<field name="queue" type="queue.name">
<doc>
Specifies the name of the queue to consume from.
</doc>
<exception name="queue-exists-if-empty" error-code="not-allowed">
<doc>
If the queue name in this command is empty, the server MUST raise an exception.
</doc>
</exception>
</field>
<field name="consumer-tag" type="str8">
<doc>
Specifies the identifier for the consumer. The consumer tag is local to a connection, so
two clients can use the same consumer tags.
</doc>
<exception name="not-existing-consumer" error-code="not-allowed">
<doc>
The tag MUST NOT refer to an existing consumer. If the client attempts to create two
consumers with the same non-empty tag the server MUST raise an exception.
</doc>
</exception>
<exception name="not-empty-consumer-tag" error-code="not-allowed">
<doc>
The client MUST NOT specify a tag that is empty or blank.
</doc>
<doc type="scenario">
Attempt to create a consumers with an empty tag.
</doc>
</exception>
</field>
<field name="no-local" type="bit">
<doc>If the no-local field is set the server will not send messages to the connection that
published them.</doc>
</field>
<field name="exclusive" type="bit" label="request exclusive access">
<doc>
Request exclusive consumer access, meaning only this consumer can access the queue.
</doc>
<exception name="in-use" error-code="resource-locked">
<doc>
If the server cannot grant exclusive access to the queue when asked, - because there are
other consumers active - it MUST raise an exception with return code 405
(resource locked).
</doc>
</exception>
</field>
<field name="nowait" type="bit" label="do not send a reply command">
<doc>
If set, the server will not respond to the command. The client should not wait for a reply
command. If the server could not complete the command it will raise an exception.
</doc>
</field>
<field name="arguments" type="map" label="arguments for consuming">
<doc>
A set of arguments for the consume. The syntax and semantics of these arguments depends on
the providers implementation.
</doc>
</field>
</command>
<!-- - Command: stream.consume-ok - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="consume-ok" code="0x4" label="confirm a new consumer">
<doc>
This command provides the client with a consumer tag which it may use in commands that work
with the consumer.
</doc>
<implement role="client" handle="MUST" />
<field name="consumer-tag" type="str8">
<doc>
Holds the consumer tag specified by the client or provided by the server.
</doc>
</field>
</command>
<!-- - Command: stream.cancel - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="cancel" code="0x5" label="end a queue consumer">
<doc>
This command cancels a consumer. Since message delivery is asynchronous the client may
continue to receive messages for a short while after cancelling a consumer. It may process
or discard these as appropriate.
</doc>
<implement role="server" handle="MUST" />
<field name="consumer-tag" type="str8" />
</command>
<!-- - Command: stream.publish - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="publish" code="0x6" label="publish a message">
<doc>
This command publishes a message to a specific exchange. The message will be routed to
queues as defined by the exchange configuration and distributed to any active consumers as
appropriate.
</doc>
<implement role="server" handle="MUST" />
<field name="exchange" type="exchange.name">
<doc>
Specifies the name of the exchange to publish to. The exchange name can be empty, meaning
the default exchange. If the exchange name is specified, and that exchange does not exist,
the server will raise an exception.
</doc>
<rule name="default">
<doc>
The server MUST accept a blank exchange name to mean the default exchange.
</doc>
</rule>
<exception name="refusal" error-code="not-implemented">
<doc>
The exchange MAY refuse stream content in which case it MUST respond with an exception.
</doc>
</exception>
</field>
<field name="routing-key" type="str8" label="Message routing key">
<doc>
Specifies the routing key for the message. The routing key is used for routing messages
depending on the exchange configuration.
</doc>
</field>
<field name="mandatory" type="bit" label="indicate mandatory routing">
<doc>
This flag tells the server how to react if the message cannot be routed to a queue. If
this flag is set, the server will return an unroutable message with a Return command. If
this flag is zero, the server silently drops the message.
</doc>
<rule name="implementation">
<doc>
The server SHOULD implement the mandatory flag.
</doc>
</rule>
</field>
<field name="immediate" type="bit" label="request immediate delivery">
<doc>
This flag tells the server how to react if the message cannot be routed to a queue
consumer immediately. If this flag is set, the server will return an undeliverable message
with a Return command. If this flag is zero, the server will queue the message, but with
no guarantee that it will ever be consumed.
</doc>
<rule name="implementation">
<doc>
The server SHOULD implement the immediate flag.
</doc>
</rule>
</field>
<segments>
<header required="true">
<entry type="stream-properties"/>
</header>
<body/>
</segments>
</command>
<!-- - Command: stream.return - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="return" code="0x7" label="return a failed message">
<doc>
This command returns an undeliverable message that was published with the "immediate" flag
set, or an unroutable message published with the "mandatory" flag set. The reply code and
text provide information about the reason that the message was undeliverable.
</doc>
<implement role="client" handle="MUST" />
<field name="reply-code" type="return-code" />
<field name="reply-text" type="str8" label="The localized reply text.">
<doc>
The localized reply text. This text can be logged as an aid to resolving issues.
</doc>
</field>
<field name="exchange" type="exchange.name">
<doc>
Specifies the name of the exchange that the message was originally published to.
</doc>
</field>
<field name="routing-key" type="str8" label="Message routing key">
<doc>
Specifies the routing key name specified when the message was published.
</doc>
</field>
<segments>
<header required="true">
<entry type="stream-properties"/>
</header>
<body/>
</segments>
</command>
<!-- - Command: stream.deliver - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<command name="deliver" code="0x8" label="notify the client of a consumer message">
<doc>
This command delivers a message to the client, via a consumer. In the asynchronous message
delivery model, the client starts a consumer using the Consume command, then the server
responds with Deliver commands as and when messages arrive for that consumer.
</doc>
<implement role="client" handle="MUST" />
<field name="consumer-tag" type="str8" />
<field name="delivery-tag" type="uint64">
<doc>
The server-assigned and session-specific delivery tag
</doc>
<rule name="session-local">
<doc>
The delivery tag is valid only within the session from which the message was received.
i.e. A client MUST NOT receive a message on one session and then acknowledge it on
another.
</doc>
</rule>
</field>
<field name="exchange" type="exchange.name">
<doc>
Specifies the name of the exchange that the message was originally published to.
</doc>
</field>
<field name="queue" type="queue.name" required="true">
<doc>
Specifies the name of the queue that the message came from. Note that a single session can
start many consumers on different queues.
</doc>
</field>
<segments>
<header required="true">
<entry type="stream-properties"/>
</header>
<body/>
</segments>
</command>
</class>
</amqp>