diff options
author | Rafael H. Schloming <rhs@apache.org> | 2010-02-15 06:49:30 +0000 |
---|---|---|
committer | Rafael H. Schloming <rhs@apache.org> | 2010-02-15 06:49:30 +0000 |
commit | e5e8ff38dbead6870ba2413b2420d4ae02ff8119 (patch) | |
tree | 1e388f04ee60c0290a90bece55b6baf61b0235fc | |
parent | ae8a567adb7cc36898fe65ed9ce7b5c016acf924 (diff) | |
download | qpid-python-e5e8ff38dbead6870ba2413b2420d4ae02ff8119.tar.gz |
more futzing with setup.py; pulled specs into python/qpid package
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@910165 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | qpid/cpp/src/tests/Makefile.am | 9 | ||||
-rw-r--r-- | qpid/python/MANIFEST.in | 1 | ||||
-rw-r--r-- | qpid/python/qpid/client.py | 4 | ||||
-rw-r--r-- | qpid/python/qpid/connection08.py | 1 | ||||
-rw-r--r-- | qpid/python/qpid/ops.py | 98 | ||||
-rw-r--r-- | qpid/python/qpid/spec.py | 61 | ||||
-rw-r--r-- | qpid/python/qpid/specs/amqp.0-10-qpid-errata.xml | 6654 | ||||
-rw-r--r-- | qpid/python/qpid/specs/amqp.0-10.dtd | 246 | ||||
-rw-r--r-- | qpid/python/qpid/specs/amqp.0-8.xml | 3998 | ||||
-rw-r--r-- | qpid/python/qpid/specs/amqp.0-9.xml | 5248 | ||||
-rw-r--r-- | qpid/python/qpid/specs_config.py (renamed from qpid/python/qpid_config.py) | 2 | ||||
-rw-r--r-- | qpid/python/qpid/tests/codec.py | 4 | ||||
-rwxr-xr-x[-rw-r--r--] | qpid/python/setup.py | 74 |
13 files changed, 16228 insertions, 172 deletions
diff --git a/qpid/cpp/src/tests/Makefile.am b/qpid/cpp/src/tests/Makefile.am index 55d76ec6a5..4d65803ac1 100644 --- a/qpid/cpp/src/tests/Makefile.am +++ b/qpid/cpp/src/tests/Makefile.am @@ -370,16 +370,13 @@ check: python_prep PYTHON_SRC_DIR=$(abs_srcdir)/../../../python PYTHON_BLD_DIR=$(abs_builddir)/python -AMQP_SPEC_DIR=$(abs_srcdir)/../../../specs # Generate python client as part of the all-am target so it gets built before tests. all-am: python_prep python_prep: - if test -d $(PYTHON_SRC_DIR) -a -d $(AMQP_SPEC_DIR); \ + if test -d $(PYTHON_SRC_DIR); \ then cd $(PYTHON_SRC_DIR) && python $(PYTHON_SRC_DIR)/setup.py install \ --prefix=$(PYTHON_BLD_DIR) --install-lib=$(PYTHON_BLD_DIR) \ - --install-scripts=$(PYTHON_BLD_DIR)/commands \ - --amqp-spec-dir=$(AMQP_SPEC_DIR); \ - else echo "WARNING: python client not built, missing one of $(PYTHON_SRC_DIR) $(AMQP_SPEC_DIR)"; fi - + --install-scripts=$(PYTHON_BLD_DIR)/commands; \ + else echo "WARNING: python client not built, missing $(PYTHON_SRC_DIR)"; fi diff --git a/qpid/python/MANIFEST.in b/qpid/python/MANIFEST.in index 92d8259f19..19a9554a99 100644 --- a/qpid/python/MANIFEST.in +++ b/qpid/python/MANIFEST.in @@ -1,3 +1,2 @@ -include qpid_config.py recursive-include examples * recursive-exclude examples verify verify.in diff --git a/qpid/python/qpid/client.py b/qpid/python/qpid/client.py index 6107a4bc35..45ce8498e8 100644 --- a/qpid/python/qpid/client.py +++ b/qpid/python/qpid/client.py @@ -26,7 +26,7 @@ import os, threading from peer import Peer, Channel, Closed from delegate import Delegate from connection08 import Connection, Frame, connect -from spec import load +from spec08 import load from queue import Queue from reference import ReferenceId, References @@ -39,7 +39,7 @@ class Client: if spec: self.spec = spec else: - from qpid_config import amqp_spec_0_9 + from specs_config import amqp_spec_0_9 self.spec = load(amqp_spec_0_9) self.structs = StructFactory(self.spec) self.sessions = {} diff --git a/qpid/python/qpid/connection08.py b/qpid/python/qpid/connection08.py index d34cfe2847..654148dad2 100644 --- a/qpid/python/qpid/connection08.py +++ b/qpid/python/qpid/connection08.py @@ -25,7 +25,6 @@ server, or even a proxy implementation. import socket, codec, logging, qpid from cStringIO import StringIO -from spec import load from codec import EOF from compat import SHUT_RDWR from exceptions import VersionError diff --git a/qpid/python/qpid/ops.py b/qpid/python/qpid/ops.py index a8ba826857..ac1819e6da 100644 --- a/qpid/python/qpid/ops.py +++ b/qpid/python/qpid/ops.py @@ -144,7 +144,7 @@ def default(f): else: return None -def make_compound(decl, base): +def make_compound(decl, base, domains): dict = {} fields = decl.query["field"] dict["__doc__"] = pydoc(decl, fields) @@ -152,11 +152,13 @@ def make_compound(decl, base): dict["SIZE"] = num(decl["@size"]) dict["CODE"] = code(decl) dict["PACK"] = num(decl["@pack"]) - dict["FIELDS"] = [Field(pythonize(f["@name"]), resolve(f), default(f)) for f in fields] + dict["FIELDS"] = [Field(pythonize(f["@name"]), resolve(f, domains), + default(f)) + for f in fields] dict["ARGS"] = dict["FIELDS"] + base.UNENCODED return str(studly(decl["@name"])), (base,), dict -def make_restricted(decl): +def make_restricted(decl, domains): name = pythonize(decl["@name"]) dict = {} choices = decl.query["choice"] @@ -171,7 +173,7 @@ def make_restricted(decl): dict["VALUES"] = values return name, (Enum,), dict -def make_type(decl): +def make_type(decl, domains): name = pythonize(decl["@name"]) dict = {} dict["__doc__"] = pydoc(decl) @@ -179,65 +181,55 @@ def make_type(decl): dict["CODE"] = code(decl) return str(studly(decl["@name"])), (Primitive,), dict -def make_command(decl): +def make_command(decl, domains): decl.set_attr("name", "%s-%s" % (decl.parent["@name"], decl["@name"])) decl.set_attr("size", "0") decl.set_attr("pack", "2") - name, bases, dict = make_compound(decl, Command) + name, bases, dict = make_compound(decl, Command, domains) dict["RESULT"] = pythonize(decl["result/@type"]) or pythonize(decl["result/struct/@name"]) return name, bases, dict -def make_control(decl): +def make_control(decl, domains): decl.set_attr("name", "%s-%s" % (decl.parent["@name"], decl["@name"])) decl.set_attr("size", "0") decl.set_attr("pack", "2") - return make_compound(decl, Control) + return make_compound(decl, Control, domains) -def make_struct(decl): - return make_compound(decl, Compound) +def make_struct(decl, domains): + return make_compound(decl, Compound, domains) -def make_enum(decl): +def make_enum(decl, domains): decl.set_attr("name", decl.parent["@name"]) - return make_restricted(decl) + return make_restricted(decl, domains) vars = globals() -def make(nd): - return vars["make_%s" % nd.name](nd) +def make(nd, domains): + return vars["make_%s" % nd.name](nd, domains) -from qpid_config import amqp_spec as file -pclfile = "%s.ops.pcl" % file +def qualify(nd, field="@name"): + cls = klass(nd) + if cls is None: + return pythonize(nd[field]) + else: + return pythonize("%s.%s" % (cls["@name"], nd[field])) + +def resolve(nd, domains): + candidates = qualify(nd, "@type"), pythonize(nd["@type"]) + for c in candidates: + if domains.has_key(c): + while domains.has_key(c): + c = domains[c] + return c + else: + return c -if os.path.exists(pclfile) and \ - os.path.getmtime(pclfile) > os.path.getmtime(file): - f = open(pclfile, "r") - types = pickle.load(f) - f.close() -else: +def load_types_from_xml(file): spec = mllib.xml_parse(file) - - def qualify(nd, field="@name"): - cls = klass(nd) - if cls is None: - return pythonize(nd[field]) - else: - return pythonize("%s.%s" % (cls["@name"], nd[field])) - domains = dict([(qualify(d), pythonize(d["@type"])) for d in spec.query["amqp/domain", included] + \ spec.query["amqp/class/domain", included]]) - - def resolve(nd): - candidates = qualify(nd, "@type"), pythonize(nd["@type"]) - for c in candidates: - if domains.has_key(c): - while domains.has_key(c): - c = domains[c] - return c - else: - return c - type_decls = \ spec.query["amqp/class/command", included] + \ spec.query["amqp/class/control", included] + \ @@ -246,12 +238,26 @@ else: spec.query["amqp/class/domain/enum", included] + \ spec.query["amqp/domain/enum", included] + \ spec.query["amqp/type"] - types = [make(nd) for nd in type_decls] - - if os.access(os.path.dirname(os.path.abspath(pclfile)), os.W_OK): - f = open(pclfile, "w") - pickle.dump(types, f) + types = [make(nd, domains) for nd in type_decls] + return types + +def load_types(file): + pclfile = "%s.ops.pcl" % file + if os.path.exists(pclfile) and \ + os.path.getmtime(pclfile) > os.path.getmtime(file): + f = open(pclfile, "rb") + types = pickle.load(f) f.close() + else: + types = load_types_from_xml(file) + if os.access(os.path.dirname(os.path.abspath(pclfile)), os.W_OK): + f = open(pclfile, "wb") + pickle.dump(types, f) + f.close() + return types + +from specs_config import amqp_spec as file +types = load_types(file) ENUMS = {} PRIMITIVE = {} diff --git a/qpid/python/qpid/spec.py b/qpid/python/qpid/spec.py deleted file mode 100644 index e9bfef1fa6..0000000000 --- a/qpid/python/qpid/spec.py +++ /dev/null @@ -1,61 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one -# or more contributor license agreements. See the NOTICE file -# distributed with this work for additional information -# regarding copyright ownership. The ASF licenses this file -# to you under the Apache License, Version 2.0 (the -# "License"); you may not use this file except in compliance -# with the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an -# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY -# KIND, either express or implied. See the License for the -# specific language governing permissions and limitations -# under the License. -# - -""" -This module loads protocol metadata into python objects. It provides -access to spec metadata via a python object model, and can also -dynamically creating python methods, classes, and modules based on the -spec metadata. All the generated methods have proper signatures and -doc strings based on the spec metadata so the python help system can -be used to browse the spec documentation. The generated methods all -dispatch to the self.invoke(meth, args) callback of the containing -class so that the generated code can be reused in a variety of -situations. -""" - -import os, mllib, spec08 - -def default(): - try: - amqp_spec = os.environ["AMQP_SPEC"] - return amqp_spec - except KeyError: - try: - from qpid_config import amqp_spec - return amqp_spec - except ImportError: - raise Exception("unable to locate the amqp specification, please set " - "the AMQP_SPEC environment variable or supply " - "qpid_config.py on the PYTHONPATH") - -def load(specfile, *errata): - for name in (specfile,) + errata: - if not os.path.exists(name): - raise IOError("No such file or directory: '%s'" % name) - - doc = mllib.xml_parse(specfile) - major = doc["amqp/@major"] - minor = doc["amqp/@minor"] - - if major == "0" and minor == "10": - return None - else: - return spec08.load(specfile, *errata) - -SPEC = load(default()) diff --git a/qpid/python/qpid/specs/amqp.0-10-qpid-errata.xml b/qpid/python/qpid/specs/amqp.0-10-qpid-errata.xml new file mode 100644 index 0000000000..365928ea4e --- /dev/null +++ b/qpid/python/qpid/specs/amqp.0-10-qpid-errata.xml @@ -0,0 +1,6654 @@ +<?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> diff --git a/qpid/python/qpid/specs/amqp.0-10.dtd b/qpid/python/qpid/specs/amqp.0-10.dtd new file mode 100644 index 0000000000..2be198525a --- /dev/null +++ b/qpid/python/qpid/specs/amqp.0-10.dtd @@ -0,0 +1,246 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<!-- + Copyright Notice + ================ + (c) Copyright Cisco Systems, Credit Suisse, Deutsche Börse 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 + ======= + JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix Corporation, IONA + Technologies, Red Hat, Inc., TWIST Process Innovations, 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 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 +--> + +<!ELEMENT amqp (doc|type|struct|domain|constant|class)*> +<!ATTLIST amqp + xmlns CDATA #IMPLIED + major CDATA #REQUIRED + minor CDATA #REQUIRED + port CDATA #REQUIRED + comment CDATA #IMPLIED +> + +<!ELEMENT constant (doc|rule)*> +<!ATTLIST constant + name CDATA #REQUIRED + value CDATA #REQUIRED + label CDATA #IMPLIED +> + +<!ELEMENT type (doc|rule)*> +<!ATTLIST type + name CDATA #REQUIRED + label CDATA #IMPLIED + code CDATA #IMPLIED + fixed-width CDATA #IMPLIED + variable-width CDATA #IMPLIED +> + +<!ELEMENT domain (doc|rule|enum)*> +<!ATTLIST domain + name CDATA #REQUIRED + type CDATA #IMPLIED + label CDATA #IMPLIED +> + +<!ELEMENT struct (field|doc|rule)*> +<!ATTLIST struct + name CDATA #REQUIRED + label CDATA #IMPLIED + size (0|1|2|4) #IMPLIED + pack (0|1|2|4) #IMPLIED + code CDATA #IMPLIED> + +<!ELEMENT enum (choice)*> + +<!ELEMENT choice (doc|rule)*> +<!ATTLIST choice + name CDATA #REQUIRED + value CDATA #REQUIRED +> + +<!ELEMENT class (doc|role|rule|struct|domain|control|command)*> +<!ATTLIST class + name CDATA #REQUIRED + code CDATA #REQUIRED + label CDATA #IMPLIED +> + +<!ELEMENT role (doc|rule)*> +<!ATTLIST role + name CDATA #REQUIRED + implement (MAY|SHOULD|MUST) #REQUIRED +> + +<!ELEMENT control (doc|implement|rule|field|response)*> +<!ATTLIST control + name CDATA #REQUIRED + code CDATA #REQUIRED + label CDATA #IMPLIED +> + +<!ELEMENT command ((doc|implement|rule|exception|field|response)*, result?, segments?)> +<!ATTLIST command + name CDATA #REQUIRED + code CDATA #REQUIRED + label CDATA #IMPLIED +> + +<!ELEMENT implement (doc|rule)*> +<!ATTLIST implement + role CDATA #REQUIRED + handle (MAY|SHOULD|MUST) #REQUIRED + send (MAY|SHOULD|MUST) #IMPLIED +> + +<!ELEMENT field (doc|rule|exception)*> +<!ATTLIST field + name CDATA #REQUIRED + type CDATA #IMPLIED + default CDATA #IMPLIED + code CDATA #IMPLIED + label CDATA #IMPLIED + required CDATA #IMPLIED +> + +<!ELEMENT rule (doc*)> +<!ATTLIST rule + name CDATA #REQUIRED + label CDATA #IMPLIED +> + +<!ELEMENT exception (doc*)> +<!ATTLIST exception + name CDATA #REQUIRED + error-code CDATA #IMPLIED + label CDATA #IMPLIED +> + +<!ELEMENT response (doc|rule)*> +<!ATTLIST response + name CDATA #IMPLIED +> + +<!ELEMENT result (doc|rule|struct)*> +<!ATTLIST result + type CDATA #IMPLIED +> + +<!ELEMENT segments (doc|rule|header|body)*> + +<!ELEMENT header (doc|rule|entry)*> +<!ATTLIST header + required (true|false) #IMPLIED +> + +<!ELEMENT entry (doc|rule)*> +<!ATTLIST entry + type CDATA #REQUIRED +> + +<!ELEMENT body (doc|rule)*> +<!ATTLIST body + required (true|false) #IMPLIED +> + +<!ELEMENT doc (#PCDATA|xref)*> +<!ATTLIST doc + type (grammar|scenario|picture|bnf|todo) #IMPLIED + title CDATA #IMPLIED +> + +<!ELEMENT xref (#PCDATA)> +<!ATTLIST xref + ref CDATA #REQUIRED> diff --git a/qpid/python/qpid/specs/amqp.0-8.xml b/qpid/python/qpid/specs/amqp.0-8.xml new file mode 100644 index 0000000000..0463f45fa9 --- /dev/null +++ b/qpid/python/qpid/specs/amqp.0-8.xml @@ -0,0 +1,3998 @@ +<?xml version="1.0"?> + +<!-- + Copyright Notice + ================ + (c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., + iMatix Corporation, IONA\ufffd Technologies, Red Hat, Inc., + TWIST Process Innovations, and 29West Inc. 2006. All rights reserved. + + License + ======= + JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix + Corporation, IONA Technologies, Red Hat, Inc., TWIST Process Innovations, 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 + +--> + +<!-- +======================================================== +EDITORS: (PH) Pieter Hintjens <ph@imatix.com> + (KvdR) Kim van der Riet <kim.vdriet@redhat.com> + +NOTE: These editors have been assigned by the AMQP working group. Please do not +edit/commit this file without consulting with one of the above editors. +======================================================== + +Revision history: + 2006-06-07 (PH) - version number changed to 0.8 to conform to public + release documentation. + + 2006-05-15 (PH) - fixed comments on queue name in basic.get to clarify + use of current queue in this method. + + 2006-05-15 (PH) - fixed comments on routing key in queue.bind to clarify + how routing key is filled when empty (to allow asynch queue.declare). + + 2006-05-11 (PH) - reset version to 0.70 so that putatitive standards + group can release 2-3 major new versions before hitting 1.0 (again). + + 2006-05-11 (PH) - TODO in documentation: cycle field in frame header + has been removed. + + 2006-05-11 (PH) - added nowait option to exchange.declare, delete, + queue.declare, delete, bind, purge, basic.consume, cancel, + file.consume, cancel, stream.consume and cancel methods. + + 2006-05-11 (PH) - removed notnull rule and added explanations on queue + name in queue.bind, purge, delete, basic.consume, cancel, file.consume, + cancel, stream.consume and cancel methods. + + 2006-05-11 (PH) - added basic.qos, file.qos, and stream.qos methods that + regroup all prefetch options from the consume methods. Also removed the + prefetch option from channel.open. + + 2006-05-11 (PH) - renumbered method indexes to show request-response + nature of methods; requests are 10, 20, 30 while responses are 11, 21, + etc. + + 2006-05-11 (PH) - removed OpenAMQ extension methods from this definition + since these are maintained seperately. + + 2006-05-26 (RG) - added Basic.Recover method to allow replay of + unacknowledged messages on a channel. + + 2006-07-03 (PH) - cosmetic clean-up of Basic.Recover comments. +--> + +<amqp major="8" minor="0" port="5672" comment="AMQ protocol 0.80"> + AMQ Protocol 0.80 + +<!-- +====================================================== +== CONSTANTS +====================================================== +--> + <constant name="frame method" value="1"/> + <constant name="frame header" value="2"/> + <constant name="frame body" value="3"/> + <constant name="frame oob method" value="4"/> + <constant name="frame oob header" value="5"/> + <constant name="frame oob body" value="6"/> + <constant name="frame trace" value="7"/> + <constant name="frame heartbeat" value="8"/> + <constant name="frame min size" value="4096"/> + <constant name="frame end" value="206"/> + <constant name="reply success" value="200"> + Indicates that the method completed successfully. This reply code is + reserved for future use - the current protocol design does not use + positive confirmation and reply codes are sent only in case of an + error. +</constant> + <constant name="not delivered" value="310" class="soft error"> + The client asked for a specific message that is no longer available. + The message was delivered to another client, or was purged from the + queue for some other reason. +</constant> + <constant name="content too large" value="311" class="soft error"> + The client attempted to transfer content larger than the server + could accept at the present time. The client may retry at a later + time. +</constant> + <constant name="connection forced" value="320" class="hard error"> + An operator intervened to close the connection for some reason. + The client may retry at some later date. +</constant> + <constant name="invalid path" value="402" class="hard error"> + The client tried to work with an unknown virtual host or cluster. +</constant> + <constant name="access refused" value="403" class="soft error"> + The client attempted to work with a server entity to which it has + no due to security settings. +</constant> + <constant name="not found" value="404" class="soft error"> + The client attempted to work with a server entity that does not exist. +</constant> + <constant name="resource locked" value="405" class="soft error"> + The client attempted to work with a server entity to which it has + no access because another client is working with it. +</constant> + <constant name="frame error" value="501" class="hard error"> + The client sent a malformed frame that the server could not decode. + This strongly implies a programming error in the client. +</constant> + <constant name="syntax error" value="502" class="hard error"> + The client sent a frame that contained illegal values for one or more + fields. This strongly implies a programming error in the client. +</constant> + <constant name="command invalid" value="503" class="hard error"> + The client sent an invalid sequence of frames, attempting to perform + an operation that was considered invalid by the server. This usually + implies a programming error in the client. +</constant> + <constant name="channel error" value="504" class="hard error"> + The client attempted to work with a channel that had not been + correctly opened. This most likely indicates a fault in the client + layer. +</constant> + <constant name="resource error" value="506" class="hard error"> + The server could not complete the method because it lacked sufficient + resources. This may be due to the client creating too many of some + type of entity. +</constant> + <constant name="not allowed" value="530" class="hard error"> + The client tried to work with some entity in a manner that is + prohibited by the server, due to security settings or by some other + criteria. +</constant> + <constant name="not implemented" value="540" class="hard error"> + The client tried to use functionality that is not implemented in the + server. +</constant> + <constant name="internal error" value="541" class="hard error"> + The server could not complete the method because of an internal error. + The server may require intervention by an operator in order to resume + normal operations. +</constant> + <!-- +====================================================== +== DOMAIN TYPES +====================================================== +--> + <domain name="access ticket" type="short"> + access ticket granted by server + <doc> + An access ticket granted by the server for a certain set of access + rights within a specific realm. Access tickets are valid within the + channel where they were created, and expire when the channel closes. + </doc> + <assert check="ne" value="0"/> + </domain> + <domain name="class id" type="short"/> + <domain name="consumer tag" type="shortstr"> + consumer tag + <doc> + Identifier for the consumer, valid within the current connection. + </doc> + <rule implement="MUST"> + The consumer tag is valid only within the channel from which the + consumer was created. I.e. a client MUST NOT create a consumer in + one channel and then use it in another. + </rule> + </domain> + <domain name="delivery tag" type="longlong"> + server-assigned delivery tag + <doc> + The server-assigned and channel-specific delivery tag + </doc> + <rule implement="MUST"> + The delivery tag is valid only within the channel from which the + message was received. I.e. a client MUST NOT receive a message on + one channel and then acknowledge it on another. + </rule> + <rule implement="MUST"> + The server MUST NOT use a zero value for delivery tags. Zero is + reserved for client use, meaning "all messages so far received". + </rule> + </domain> + <domain name="exchange name" type="shortstr"> + exchange name + <doc> + The exchange name is a client-selected string that identifies + the exchange for publish methods. Exchange names may consist + of any mixture of digits, letters, and underscores. Exchange + names are scoped by the virtual host. + </doc> + <assert check="length" value="127"/> + </domain> + <domain name="known hosts" type="shortstr"> +list of known hosts +<doc> +Specifies the list of equivalent or alternative hosts that the server +knows about, which will normally include the current server itself. +Clients can cache this information and use it when reconnecting to a +server after a failure. +</doc> + <rule implement="MAY"> +The server MAY leave this field empty if it knows of no other +hosts than itself. +</rule> + </domain> + <domain name="method id" type="short"/> + <domain name="no ack" type="bit"> + no acknowledgement needed + <doc> + If this field is set the server does not expect acknowledgments + 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> + </domain> + <domain name="no local" type="bit"> + do not deliver own messages + <doc> + If the no-local field is set the server will not send messages to + the client that published them. + </doc> + </domain> + <domain name="path" type="shortstr"> + <doc> + Must start with a slash "/" and continue with path names + separated by slashes. A path name consists of any combination + of at least one of [A-Za-z0-9] plus zero or more of [.-_+!=:]. +</doc> + <assert check="notnull"/> + <assert check="syntax" rule="path"/> + <assert check="length" value="127"/> + </domain> + <domain name="peer properties" type="table"> + <doc> +This string provides a set of peer properties, used for +identification, debugging, and general information. +</doc> + <rule implement="SHOULD"> +The properties SHOULD contain these fields: +"product", giving the name of the peer product, "version", giving +the name of the peer version, "platform", giving the name of the +operating system, "copyright", if appropriate, and "information", +giving other general information. +</rule> + </domain> + <domain name="queue name" type="shortstr"> + queue name + <doc> + The queue name identifies the queue within the vhost. Queue + names may consist of any mixture of digits, letters, and + underscores. + </doc> + <assert check="length" value="127"/> + </domain> + <domain name="redelivered" type="bit"> + message is being redelivered + <doc> + This indicates that the message has been previously delivered to + this or another client. + </doc> + <rule implement="SHOULD"> + The server SHOULD try to signal redelivered messages when it can. + When redelivering a message that was not successfully acknowledged, + the server SHOULD deliver it to the original client if possible. + </rule> + <rule implement="MUST"> + The client MUST NOT rely on the redelivered field but MUST take it + as a hint that the message may already have been processed. A + fully robust client must be able to track duplicate received messages + on non-transacted, and locally-transacted channels. + </rule> + </domain> + <domain name="reply code" type="short"> +reply code from server +<doc> + The reply code. The AMQ reply codes are defined in AMQ RFC 011. +</doc> + <assert check="notnull"/> + </domain> + <domain name="reply text" type="shortstr"> +localised reply text +<doc> + The localised reply text. This text can be logged as an aid to + resolving issues. +</doc> + <assert check="notnull"/> + </domain> + <class name="connection" handler="connection" index="10"> + <!-- +====================================================== +== CONNECTION +====================================================== +--> + work with socket connections +<doc> + The connection class provides methods for a client to establish a + network connection to a server, and for both peers to operate the + connection thereafter. +</doc> + <doc name="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> + <chassis name="server" implement="MUST"/> + <chassis name="client" implement="MUST"/> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="start" synchronous="1" index="10"> + start connection negotiation + <doc> + This method starts the connection negotiation process by telling + the client the protocol version that the server proposes, along + with a list of security mechanisms which the client can use for + authentication. + </doc> + <rule implement="MUST"> + If the client cannot handle the protocol version suggested by the + server it MUST close the socket connection. + </rule> + <rule implement="MUST"> + The server MUST provide a protocol version that is lower than or + equal to that requested by the client in the protocol header. If + the server cannot support the specified protocol it MUST NOT send + this method, but MUST close the socket connection. + </rule> + <chassis name="client" implement="MUST"/> + <response name="start-ok"/> + <field name="version major" type="octet"> + protocol major version + <doc> + The protocol major version that the server agrees to use, which + cannot be higher than the client's major version. + </doc> + </field> + <field name="version minor" type="octet"> + protocol major version + <doc> + The protocol minor version that the server agrees to use, which + cannot be higher than the client's minor version. + </doc> + </field> + <field name="server properties" domain="peer properties"> + server properties + </field> + <field name="mechanisms" type="longstr"> + available security mechanisms + <doc> + A list of the security mechanisms that the server supports, delimited + by spaces. Currently ASL supports these mechanisms: PLAIN. + </doc> + <see name="security mechanisms"/> + <assert check="notnull"/> + </field> + <field name="locales" type="longstr"> + available message locales + <doc> + A list of the message locales that the server supports, delimited + by spaces. The locale defines the language in which the server + will send reply texts. + </doc> + <rule implement="MUST"> + All servers MUST support at least the en_US locale. + </rule> + <assert check="notnull"/> + </field> + </method> + <method name="start-ok" synchronous="1" index="11"> + select security mechanism and locale + <doc> + This method selects a SASL security mechanism. ASL uses SASL + (RFC2222) to negotiate authentication and encryption. + </doc> + <chassis name="server" implement="MUST"/> + <field name="client properties" domain="peer properties"> + client properties + </field> + <field name="mechanism" type="shortstr"> + selected security mechanism + <doc> + A single security mechanisms selected by the client, which must be + one of those specified by the server. + </doc> + <rule implement="SHOULD"> + The client SHOULD authenticate using the highest-level security + profile it can handle from the list provided by the server. + </rule> + <rule implement="MUST"> + The mechanism field MUST contain one of the security mechanisms + proposed by the server in the Start method. If it doesn't, the + server MUST close the socket. + </rule> + <assert check="notnull"/> + </field> + <field name="response" type="longstr"> + security response data + <doc> + A block of opaque data passed to the security mechanism. The contents + of this data are defined by the SASL security mechanism. For the + PLAIN security mechanism this is defined as a field table holding + two fields, LOGIN and PASSWORD. + </doc> + <assert check="notnull"/> + </field> + <field name="locale" type="shortstr"> + selected message locale + <doc> + A single message local selected by the client, which must be one + of those specified by the server. + </doc> + <assert check="notnull"/> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="secure" synchronous="1" index="20"> + 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 method challenges the client to provide more information. + </doc> + <chassis name="client" implement="MUST"/> + <response name="secure-ok"/> + <field name="challenge" type="longstr"> + security challenge data + <doc> + Challenge information, a block of opaque binary data passed to + the security mechanism. + </doc> + <see name="security mechanisms"/> + </field> + </method> + <method name="secure-ok" synchronous="1" index="21"> + security mechanism response + <doc> + This method attempts to authenticate, passing a block of SASL data + for the security mechanism at the server side. + </doc> + <chassis name="server" implement="MUST"/> + <field name="response" type="longstr"> + security response data + <doc> + A block of opaque data passed to the security mechanism. The contents + of this data are defined by the SASL security mechanism. + </doc> + <assert check="notnull"/> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="tune" synchronous="1" index="30"> + propose connection tuning parameters + <doc> + This method proposes a set of connection configuration values + to the client. The client can accept and/or adjust these. + </doc> + <chassis name="client" implement="MUST"/> + <response name="tune-ok"/> + <field name="channel max" type="short"> + proposed maximum channels + <doc> + The maximum total number of channels that the server allows + per connection. Zero 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="frame max" type="long"> + proposed maximum frame size + <doc> + The largest frame size that the server proposes for the + connection. The client can negotiate a lower value. Zero 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 implement="MUST"> + Until the frame-max has been negotiated, both peers MUST accept + frames of up to 4096 octets large. The minimum non-zero value for + the frame-max field is 4096. + </rule> + </field> + <field name="heartbeat" type="short"> + desired heartbeat delay + <doc> + The delay, in seconds, of the connection heartbeat that the server + wants. Zero means the server does not want a heartbeat. + </doc> + </field> + </method> + <method name="tune-ok" synchronous="1" index="31"> + negotiate connection tuning parameters + <doc> + This method sends the client's connection tuning parameters to the + server. Certain fields are negotiated, others provide capability + information. + </doc> + <chassis name="server" implement="MUST"/> + <field name="channel max" type="short"> + negotiated maximum channels + <doc> + The maximum total number of channels that the client will use + per connection. May not be higher than the value specified by + the server. + </doc> + <rule implement="MAY"> + The server MAY ignore the channel-max value or MAY use it for + tuning its resource allocation. + </rule> + <assert check="notnull"/> + <assert check="le" method="tune" field="channel max"/> + </field> + <field name="frame max" type="long"> + negotiated maximum frame size + <doc> + The largest frame size that the client and server will use for + the connection. Zero 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 frame-max limit + applies principally to content frames, where large contents + can be broken into frames of arbitrary size. + </doc> + <rule implement="MUST"> + Until the frame-max has been negotiated, both peers must accept + frames of up to 4096 octets large. The minimum non-zero value for + the frame-max field is 4096. + </rule> + </field> + <field name="heartbeat" type="short"> + desired heartbeat delay + <doc> + The delay, in seconds, of the connection heartbeat that the client + wants. Zero means the client does not want a heartbeat. + </doc> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="open" synchronous="1" index="40"> + open connection to virtual host + <doc> + This method opens a connection to a virtual host, which is a + collection of resources, and acts to separate multiple application + domains within a server. + </doc> + <rule implement="MUST"> + The client MUST open the context before doing any work on the + connection. + </rule> + <chassis name="server" implement="MUST"/> + <response name="open-ok"/> + <response name="redirect"/> + <field name="virtual host" domain="path"> + virtual host name + <assert check="regexp" value="^[a-zA-Z0-9/-_]+$"/> + <doc> + The name of the virtual host to work with. + </doc> + <rule implement="MUST"> + 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. + </rule> + <rule implement="SHOULD"> + The server SHOULD verify that the client has permission to access + the specified virtual host. + </rule> + <rule implement="MAY"> + The server MAY configure arbitrary limits per virtual host, such + as the number of each type of entity that may be used, per + connection and/or in total. + </rule> + </field> + <field name="capabilities" type="shortstr"> + required capabilities + <doc> + The client may specify a number of capability names, delimited by + spaces. The server can use this string to how to process the + client's connection request. + </doc> + </field> + <field name="insist" type="bit"> + insist on connecting to server + <doc> + In a configuration with multiple load-sharing servers, the server + may respond to a Connection.Open method with a Connection.Redirect. + The insist option tells the server that the client is insisting on + a connection to the specified server. + </doc> + <rule implement="SHOULD"> + When the client uses the insist option, the server SHOULD accept + the client connection unless it is technically unable to do so. + </rule> + </field> + </method> + <method name="open-ok" synchronous="1" index="41"> + signal that the connection is ready + <doc> + This method signals to the client that the connection is ready for + use. + </doc> + <chassis name="client" implement="MUST"/> + <field name="known hosts" domain="known hosts"/> + </method> + <method name="redirect" synchronous="1" index="50"> + asks the client to use a different server + <doc> + This method redirects the client to another server, based on the + requested virtual host and/or capabilities. + </doc> + <rule implement="SHOULD"> + When getting the Connection.Redirect method, 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. + </rule> + <chassis name="client" implement="MAY"/> + <field name="host" type="shortstr"> + server to connect to + <doc> + Specifies the server to connect to. This is an IP address or a + DNS name, optionally followed by a colon and a port number. If + no port number is specified, the client should use the default + port number for the protocol. + </doc> + <assert check="notnull"/> + </field> + <field name="known hosts" domain="known hosts"/> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="close" synchronous="1" index="60"> + request a connection close + <doc> + This method indicates that the sender wants to close the connection. + This may be due to internal conditions (e.g. a forced shut-down) or + due to an error handling a specific method, i.e. an exception. When + a close is due to an exception, the sender provides the class and + method id of the method which caused the exception. + </doc> + <rule implement="MUST"> + After sending this method any received method except the Close-OK + method MUST be discarded. + </rule> + <rule implement="MAY"> + The peer sending this method MAY use a counter or timeout to + detect failure of the other peer to respond correctly with + the Close-OK method. + </rule> + <rule implement="MUST"> + When a server receives the Close method from a client it MUST + delete all server-side resources associated with the client's + context. A client CANNOT reconnect to a context after sending + or receiving a Close method. + </rule> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <response name="close-ok"/> + <field name="reply code" domain="reply code"/> + <field name="reply text" domain="reply text"/> + <field name="class id" domain="class id"> + failing method class + <doc> + When the close is provoked by a method exception, this is the + class of the method. + </doc> + </field> + <field name="method id" domain="method id"> + failing method ID + <doc> + When the close is provoked by a method exception, this is the + ID of the method. + </doc> + </field> + </method> + <method name="close-ok" synchronous="1" index="61"> + confirm a connection close + <doc> + This method confirms a Connection.Close method and tells the + recipient that it is safe to release resources for the connection + and close the socket. + </doc> + <rule implement="SHOULD"> + A peer that detects a socket closure without having received a + Close-Ok handshake method SHOULD log the error. + </rule> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + </method> + </class> + <class name="channel" handler="channel" index="20"> + <!-- +====================================================== +== CHANNEL +====================================================== +--> + work with channels +<doc> + The channel class provides methods for a client to establish a virtual + connection - a channel - to a server and for both peers to operate the + virtual connection thereafter. +</doc> + <doc name="grammar"> + channel = open-channel *use-channel close-channel + open-channel = C:OPEN S:OPEN-OK + use-channel = C:FLOW S:FLOW-OK + / S:FLOW C:FLOW-OK + / S:ALERT + / functional-class + close-channel = C:CLOSE S:CLOSE-OK + / S:CLOSE C:CLOSE-OK +</doc> + <chassis name="server" implement="MUST"/> + <chassis name="client" implement="MUST"/> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="open" synchronous="1" index="10"> + open a channel for use + <doc> + This method opens a virtual connection (a channel). + </doc> + <rule implement="MUST"> + This method MUST NOT be called when the channel is already open. + </rule> + <chassis name="server" implement="MUST"/> + <response name="open-ok"/> + <field name="out of band" type="shortstr"> + out-of-band settings + <doc> + Configures out-of-band transfers on this channel. The syntax and + meaning of this field will be formally defined at a later date. + </doc> + <assert check="null"/> + </field> + </method> + <method name="open-ok" synchronous="1" index="11"> + signal that the channel is ready + <doc> + This method signals to the client that the channel is ready for use. + </doc> + <chassis name="client" implement="MUST"/> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="flow" synchronous="1" index="20"> + enable/disable flow from peer + <doc> + This method asks the peer to pause or restart the flow of content + data. This is a simple flow-control mechanism that a peer can use + to avoid oveflowing its queues or otherwise finding itself receiving + more messages than it can process. Note that this method is not + intended for window control. The peer that receives a request to + stop sending content should finish sending the current content, if + any, and then wait until it receives a Flow restart method. + </doc> + <rule implement="MAY"> + When a new channel is opened, it is active. Some applications + assume that channels are inactive until started. To emulate this + behaviour a client MAY open the channel, then pause it. + </rule> + <rule implement="SHOULD"> + When sending content data in multiple frames, a peer SHOULD monitor + the channel for incoming methods and respond to a Channel.Flow as + rapidly as possible. + </rule> + <rule implement="MAY"> + A peer MAY use the Channel.Flow method to throttle incoming content + data for internal reasons, for example, when exchangeing data over a + slower connection. + </rule> + <rule implement="MAY"> + The peer that requests a Channel.Flow method MAY disconnect and/or + ban a peer that does not respect the request. + </rule> + <chassis name="server" implement="MUST"/> + <chassis name="client" implement="MUST"/> + <response name="flow-ok"/> + <field name="active" type="bit"> + start/stop content frames + <doc> + If 1, the peer starts sending content frames. If 0, the peer + stops sending content frames. + </doc> + </field> + </method> + <method name="flow-ok" index="21"> + confirm a flow method + <doc> + Confirms to the peer that a flow command was received and processed. + </doc> + <chassis name="server" implement="MUST"/> + <chassis name="client" implement="MUST"/> + <field name="active" type="bit"> + current flow setting + <doc> + Confirms the setting of the processed flow method: 1 means the + peer will start sending or continue to send content frames; 0 + means it will not. + </doc> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="alert" index="30"> + send a non-fatal warning message + <doc> + This method allows the server to send a non-fatal warning to the + client. This is used for methods that are normally asynchronous + and thus do not have confirmations, and for which the server may + detect errors that need to be reported. Fatal errors are handled + as channel or connection exceptions; non-fatal errors are sent + through this method. + </doc> + <chassis name="client" implement="MUST"/> + <field name="reply code" domain="reply code"/> + <field name="reply text" domain="reply text"/> + <field name="details" type="table"> + detailed information for warning + <doc> + A set of fields that provide more information about the + problem. The meaning of these fields are defined on a + per-reply-code basis (TO BE DEFINED). + </doc> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="close" synchronous="1" index="40"> + request a channel close + <doc> + This method indicates that the sender wants to close the channel. + This may be due to internal conditions (e.g. a forced shut-down) or + due to an error handling a specific method, i.e. an exception. When + a close is due to an exception, the sender provides the class and + method id of the method which caused the exception. + </doc> + <rule implement="MUST"> + After sending this method any received method except + Channel.Close-OK MUST be discarded. + </rule> + <rule implement="MAY"> + The peer sending this method MAY use a counter or timeout to detect + failure of the other peer to respond correctly with Channel.Close-OK.. + </rule> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <response name="close-ok"/> + <field name="reply code" domain="reply code"/> + <field name="reply text" domain="reply text"/> + <field name="class id" domain="class id"> + failing method class + <doc> + When the close is provoked by a method exception, this is the + class of the method. + </doc> + </field> + <field name="method id" domain="method id"> + failing method ID + <doc> + When the close is provoked by a method exception, this is the + ID of the method. + </doc> + </field> + </method> + <method name="close-ok" synchronous="1" index="41"> + confirm a channel close + <doc> + This method confirms a Channel.Close method and tells the recipient + that it is safe to release resources for the channel and close the + socket. + </doc> + <rule implement="SHOULD"> + A peer that detects a socket closure without having received a + Channel.Close-Ok handshake method SHOULD log the error. + </rule> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + </method> + </class> + <class name="access" handler="connection" index="30"> + <!-- +====================================================== +== ACCESS CONTROL +====================================================== +--> + work with access tickets +<doc> + The protocol control access to server resources using access tickets. + A client must explicitly request access tickets before doing work. + An access ticket grants a client the right to use a specific set of + resources - called a "realm" - in specific ways. +</doc> + <doc name="grammar"> + access = C:REQUEST S:REQUEST-OK +</doc> + <chassis name="server" implement="MUST"/> + <chassis name="client" implement="MUST"/> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="request" synchronous="1" index="10"> + request an access ticket + <doc> + This method requests an access ticket for an access realm. + The server responds by granting the access ticket. If the + client does not have access rights to the requested realm + this causes a connection exception. Access tickets are a + per-channel resource. + </doc> + <rule implement="MUST"> + The realm name MUST start with either "/data" (for application + resources) or "/admin" (for server administration resources). + If the realm starts with any other path, the server MUST raise + a connection exception with reply code 403 (access refused). + </rule> + <rule implement="MUST"> + The server MUST implement the /data realm and MAY implement the + /admin realm. The mapping of resources to realms is not + defined in the protocol - this is a server-side configuration + issue. + </rule> + <chassis name="server" implement="MUST"/> + <response name="request-ok"/> + <field name="realm" domain="path"> + name of requested realm + <rule implement="MUST"> + If the specified realm is not known to the server, the server + must raise a channel exception with reply code 402 (invalid + path). + </rule> + </field> + <field name="exclusive" type="bit"> + request exclusive access + <doc> + Request exclusive access to the realm. If the server cannot grant + this - because there are other active tickets for the realm - it + raises a channel exception. + </doc> + </field> + <field name="passive" type="bit"> + request passive access + <doc> + Request message passive access to the specified access realm. + Passive access lets a client get information about resources in + the realm but not to make any changes to them. + </doc> + </field> + <field name="active" type="bit"> + request active access + <doc> + Request message active access to the specified access realm. + Acvtive access lets a client get create and delete resources in + the realm. + </doc> + </field> + <field name="write" type="bit"> + request write access + <doc> + Request write access to the specified access realm. Write access + lets a client publish messages to all exchanges in the realm. + </doc> + </field> + <field name="read" type="bit"> + request read access + <doc> + Request read access to the specified access realm. Read access + lets a client consume messages from queues in the realm. + </doc> + </field> + </method> + <method name="request-ok" synchronous="1" index="11"> + grant access to server resources + <doc> + This method provides the client with an access ticket. The access + ticket is valid within the current channel and for the lifespan of + the channel. + </doc> + <rule implement="MUST"> + The client MUST NOT use access tickets except within the same + channel as originally granted. + </rule> + <rule implement="MUST"> + The server MUST isolate access tickets per channel and treat an + attempt by a client to mix these as a connection exception. + </rule> + <chassis name="client" implement="MUST"/> + <field name="ticket" domain="access ticket"/> + </method> + </class> + <class name="exchange" handler="channel" index="40"> + <!-- +====================================================== +== EXCHANGES (or "routers", if you prefer) +== (Or matchers, plugins, extensions, agents,... Routing is just one of +== the many fun things an exchange can do.) +====================================================== +--> + work with exchanges +<doc> + Exchanges match and distribute messages across queues. Exchanges can be + configured in the server or created at runtime. +</doc> + <doc name="grammar"> + exchange = C:DECLARE S:DECLARE-OK + / C:DELETE S:DELETE-OK +</doc> + <chassis name="server" implement="MUST"/> + <chassis name="client" implement="MUST"/> + <rule implement="MUST"> + <test>amq_exchange_19</test> + The server MUST implement the direct and fanout exchange types, and + predeclare the corresponding exchanges named amq.direct and amq.fanout + in each virtual host. The server MUST also predeclare a direct + exchange to act as the default exchange for content Publish methods + and for default queue bindings. +</rule> + <rule implement="SHOULD"> + <test>amq_exchange_20</test> + The server SHOULD implement the topic exchange type, and predeclare + the corresponding exchange named amq.topic in each virtual host. +</rule> + <rule implement="MAY"> + <test>amq_exchange_21</test> + The server MAY implement the system exchange type, and predeclare the + corresponding exchanges named amq.system in each virtual host. If the + client attempts to bind a queue to the system exchange, the server + MUST raise a connection exception with reply code 507 (not allowed). +</rule> + <rule implement="MUST"> + <test>amq_exchange_22</test> + The default exchange MUST be defined as internal, and be inaccessible + to the client except by specifying an empty exchange name in a content + Publish method. That is, the server MUST NOT let clients make explicit + bindings to this exchange. +</rule> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="declare" synchronous="1" index="10"> + declare exchange, create if needed + <doc> + This method 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 implement="SHOULD"> + <test>amq_exchange_23</test> + The server SHOULD support a minimum of 16 exchanges per virtual host + and ideally, impose no limit except as defined by available resources. + </rule> + <chassis name="server" implement="MUST"/> + <response name="declare-ok"/> + <field name="ticket" domain="access ticket"> + <doc> + When a client defines a new exchange, this belongs to the access realm + of the ticket used. All further work done with that exchange must be + done with an access ticket for the same realm. + </doc> + <rule implement="MUST"> + The client MUST provide a valid access ticket giving "active" access + to the realm in which the exchange exists or will be created, or + "passive" access if the if-exists flag is set. + </rule> + </field> + <field name="exchange" domain="exchange name"> + <rule implement="MUST"> + <test>amq_exchange_15</test> + Exchange names starting with "amq." are reserved for predeclared + and standardised exchanges. If the client attempts to create an + exchange starting with "amq.", the server MUST raise a channel + exception with reply code 403 (access refused). + </rule> + <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/> + </field> + <field name="type" type="shortstr"> + exchange type + <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> + <rule implement="MUST"> + <test>amq_exchange_16</test> + If the exchange already exists with a different type, the server + MUST raise a connection exception with a reply code 507 (not allowed). + </rule> + <rule implement="MUST"> + <test>amq_exchange_18</test> + If the server does not support the requested exchange type it MUST + raise a connection exception with a reply code 503 (command invalid). + </rule> + <assert check="regexp" value="^[a-zA-Z0-9-_.:]+$"/> + </field> + <field name="passive" type="bit"> + 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> + <rule implement="MUST"> + <test>amq_exchange_05</test> + If set, and the exchange does not already exist, the server MUST + raise a channel exception with reply code 404 (not found). + </rule> + </field> + <field name="durable" type="bit"> + 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 implement="MUST"> + <test>amq_exchange_24</test> + The server MUST support both durable and transient exchanges. + </rule> + <rule implement="MUST"> + The server MUST ignore the durable field if the exchange already + exists. + </rule> + </field> + <field name="auto delete" type="bit"> + auto-delete when unused + <doc> + If set, the exchange is deleted when all queues have finished + using it. + </doc> + <rule implement="SHOULD"> + <test>amq_exchange_02</test> + The server SHOULD allow for a reasonable delay between the point + when it determines that an exchange is not being used (or no longer + used), and the point when it deletes the exchange. At the least it + must allow a client to create an exchange and then bind a queue to + it, with a small but non-zero delay between these two actions. + </rule> + <rule implement="MUST"> + <test>amq_exchange_25</test> + The server MUST ignore the auto-delete field if the exchange already + exists. + </rule> + </field> + <field name="internal" type="bit"> + create internal exchange + <doc> + If set, the exchange may not be used directly by publishers, but + only when bound to other exchanges. Internal exchanges are used to + construct wiring that is not visible to applications. + </doc> + </field> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> + + <field name="arguments" type="table"> + 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> + </field> + </method> + <method name="declare-ok" synchronous="1" index="11"> + confirms an exchange declaration + <doc> + This method confirms a Declare method and confirms the name of the + exchange, essential for automatically-named exchanges. + </doc> + <chassis name="client" implement="MUST"/> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="delete" synchronous="1" index="20"> + delete an exchange + <doc> + This method deletes an exchange. When an exchange is deleted all queue + bindings on the exchange are cancelled. + </doc> + <chassis name="server" implement="MUST"/> + <response name="delete-ok"/> + <field name="ticket" domain="access ticket"> + <rule implement="MUST"> + The client MUST provide a valid access ticket giving "active" + access rights to the exchange's access realm. + </rule> + </field> + <field name="exchange" domain="exchange name"> + <rule implement="MUST"> + <test>amq_exchange_11</test> + The exchange MUST exist. Attempting to delete a non-existing exchange + causes a channel exception. + </rule> + <assert check="notnull"/> + </field> + <field name="if unused" type="bit"> + 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 a channel exception instead. + </doc> + <rule implement="SHOULD"> + <test>amq_exchange_12</test> + If set, the server SHOULD delete the exchange but only if it has + no queue bindings. + </rule> + <rule implement="SHOULD"> + <test>amq_exchange_13</test> + If set, the server SHOULD raise a channel exception if the exchange is in + use. + </rule> + </field> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> + + </method> + <method name="delete-ok" synchronous="1" index="21"> + confirm deletion of an exchange + <doc> + This method confirms the deletion of an exchange. + </doc> + <chassis name="client" implement="MUST"/> + </method> + + <method name="bound" synchronous="1" index="22"> + <chassis name="server" implement="SHOULD"/> + <field name="exchange" domain="exchange name"/> + <field name = "routing key" type = "shortstr"> + 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 = "queue" domain = "queue name"/> + </method> + + <method name="bound-ok" synchronous="1" index="23"> + <field name="reply code" domain="reply code"/> + <field name="reply text" domain="reply text"/> + <chassis name="client" implement="SHOULD"/> + </method> + + </class> + + + <class name="queue" handler="channel" index="50"> + <!-- +====================================================== +== QUEUES +====================================================== +--> + 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 name="grammar"> + queue = C:DECLARE S:DECLARE-OK + / C:BIND S:BIND-OK + / C:PURGE S:PURGE-OK + / C:DELETE S:DELETE-OK +</doc> + <chassis name="server" implement="MUST"/> + <chassis name="client" implement="MUST"/> + <rule implement="MUST"> + <test>amq_queue_33</test> + A server MUST allow any content class to be sent to any queue, in any + mix, and queue and delivery these content classes independently. Note + that all methods that fetch content off queues are specific to a given + content class. +</rule> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="declare" synchronous="1" index="10"> + declare queue, create if needed + <doc> + This method 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 implement="MUST"> + <test>amq_queue_34</test> + The server MUST create a default binding for a newly-created queue + to the default exchange, which is an exchange of type 'direct'. + </rule> + <rule implement="SHOULD"> + <test>amq_queue_35</test> + The server SHOULD support a minimum of 256 queues per virtual host + and ideally, impose no limit except as defined by available resources. + </rule> + <chassis name="server" implement="MUST"/> + <response name="declare-ok"/> + <field name="ticket" domain="access ticket"> + <doc> + When a client defines a new queue, this belongs to the access realm + of the ticket used. All further work done with that queue must be + done with an access ticket for the same realm. + </doc> + <doc> + The client provides a valid access ticket giving "active" access + to the realm in which the queue exists or will be created, or + "passive" access if the if-exists flag is set. + </doc> + </field> + <field name="queue" domain="queue name"> + <rule implement="MAY"> + <test>amq_queue_10</test> + The queue name MAY be empty, in which case the server MUST create + a new queue with a unique generated name and return this to the + client in the Declare-Ok method. + </rule> + <rule implement="MUST"> + <test>amq_queue_32</test> + Queue names starting with "amq." are reserved for predeclared and + standardised server queues. If the queue name starts with "amq." + and the passive option is zero, the server MUST raise a connection + exception with reply code 403 (access refused). + </rule> + <assert check="regexp" value="^[a-zA-Z0-9-_.:]*$"/> + </field> + <field name="passive" type="bit"> + do not create queue + <doc> + If set, the server will not create the queue. The client can use + this to check whether a queue exists without modifying the server + state. + </doc> + <rule implement="MUST"> + <test>amq_queue_05</test> + If set, and the queue does not already exist, the server MUST + respond with a reply code 404 (not found) and raise a channel + exception. + </rule> + </field> + <field name="durable" type="bit"> + 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 implement="MUST"> + <test>amq_queue_03</test> + The server MUST recreate the durable queue after a restart. + </rule> + <rule implement="MUST"> + <test>amq_queue_36</test> + The server MUST support both durable and transient queues. + </rule> + <rule implement="MUST"> + <test>amq_queue_37</test> + The server MUST ignore the durable field if the queue already + exists. + </rule> + </field> + <field name="exclusive" type="bit"> + request an exclusive queue + <doc> + Exclusive queues may only be consumed from by the current connection. + Setting the 'exclusive' flag always implies 'auto-delete'. + </doc> + <rule implement="MUST"> + <test>amq_queue_38</test> + The server MUST support both exclusive (private) and non-exclusive + (shared) queues. + </rule> + <rule implement="MUST"> + <test>amq_queue_04</test> + The server MUST raise a channel exception if 'exclusive' is specified + and the queue already exists and is owned by a different connection. + </rule> + </field> + <field name="auto delete" type="bit"> + auto-delete queue when unused + <doc> + If set, the queue is deleted when all consumers have finished + using it. Last consumer can be cancelled either explicitly or because + its channel is closed. If there was no consumer ever on the queue, it + won't be deleted. + </doc> + <rule implement="SHOULD"> + <test>amq_queue_02</test> + The server SHOULD allow for a reasonable delay between the point + when it determines that a queue is not being used (or no longer + used), and the point when it deletes the queue. At the least it + must allow a client to create a queue and then create a consumer + to read from it, with a small but non-zero delay between these + two actions. The server should equally allow for clients that may + be disconnected prematurely, and wish to re-consume from the same + queue without losing messages. We would recommend a configurable + timeout, with a suitable default value being one minute. + </rule> + <rule implement="MUST"> + <test>amq_queue_31</test> + The server MUST ignore the auto-delete field if the queue already + exists. + </rule> + </field> + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> + + <field name="arguments" type="table"> + 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> + </field> + </method> + <method name="declare-ok" synchronous="1" index="11"> + confirms a queue definition + <doc> + This method confirms a Declare method and confirms the name of the + queue, essential for automatically-named queues. + </doc> + <chassis name="client" implement="MUST"/> + <field name="queue" domain="queue name"> + <doc> + Reports the name of the queue. If the server generated a queue + name, this field contains that name. + </doc> + <assert check="notnull"/> + </field> + <field name="message count" type="long"> + number of messages in queue + <doc> + Reports the number of messages in the queue, which will be zero + for newly-created queues. + </doc> + </field> + <field name="consumer count" type="long"> + number of consumers + <doc> + Reports the number of active consumers for the queue. Note that + consumers can suspend activity (Channel.Flow) in which case they + do not appear in this count. + </doc> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="bind" synchronous="1" index="20"> + bind queue to an exchange + <doc> + This method 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 dest exchange + and subscription queues are bound to a dest_wild exchange. + </doc> + <rule implement="MUST"> + <test>amq_queue_25</test> + A server MUST allow ignore duplicate bindings - that is, two or + more bind methods for a specific queue, with identical arguments + - without treating these as an error. + </rule> + <rule implement="MUST"> + <test>amq_queue_39</test> + If a bind fails, the server MUST raise a connection exception. + </rule> + <rule implement="MUST"> + <test>amq_queue_12</test> + The server MUST NOT allow a durable queue to bind to a transient + exchange. If the client attempts this the server MUST raise a + channel exception. + </rule> + <rule implement="SHOULD"> + <test>amq_queue_13</test> + Bindings for durable queues are automatically durable and the + server SHOULD restore such bindings after a server restart. + </rule> + <rule implement="MUST"> + <test>amq_queue_17</test> + If the client attempts to an exchange that was declared as internal, + the server MUST raise a connection exception with reply code 530 + (not allowed). + </rule> + <rule implement="SHOULD"> + <test>amq_queue_40</test> + The server SHOULD support at least 4 bindings per queue, and + ideally, impose no limit except as defined by available resources. + </rule> + <chassis name="server" implement="MUST"/> + <response name="bind-ok"/> + <field name="ticket" domain="access ticket"> + <doc> + The client provides a valid access ticket giving "active" + access rights to the queue's access realm. + </doc> + </field> + + <field name = "queue" domain = "queue name"> + <doc> + Specifies the name of the queue to bind. If the queue name is + empty, refers to the current queue for the channel, which is + the last declared queue. + </doc> + <doc name = "rule"> + If the client did not previously declare a queue, and the queue + name in this method is empty, the server MUST raise a connection + exception with reply code 530 (not allowed). + </doc> + <doc name = "rule" test = "amq_queue_26"> + If the queue does not exist the server MUST raise a channel exception + with reply code 404 (not found). + </doc> + </field> + + <field name="exchange" domain="exchange name"> + The name of the exchange to bind to. + <rule implement="MUST"> + <test>amq_queue_14</test> + If the exchange does not exist the server MUST raise a channel + exception with reply code 404 (not found). + </rule> + </field> + <field name="routing key" type="shortstr"> + message routing key + <doc> + Specifies the routing key for the binding. The routing key is + used for routing messages depending on the exchange configuration. + Not all exchanges use a routing key - refer to the specific + exchange documentation. If the routing key is empty and the queue + name is empty, the routing key will be the current queue for the + channel, which is the last declared queue. + </doc> + </field> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> + + <field name="arguments" type="table"> + arguments for binding + <doc> + A set of arguments for the binding. The syntax and semantics of + these arguments depends on the exchange class. + </doc> + </field> + </method> + <method name="bind-ok" synchronous="1" index="21"> + confirm bind successful + <doc> + This method confirms that the bind was successful. + </doc> + <chassis name="client" implement="MUST"/> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="purge" synchronous="1" index="30"> + purge a queue + <doc> + This method removes all messages from a queue. It does not cancel + consumers. Purged messages are deleted without any formal "undo" + mechanism. + </doc> + <rule implement="MUST"> + <test>amq_queue_15</test> + A call to purge MUST result in an empty queue. + </rule> + <rule implement="MUST"> + <test>amq_queue_41</test> + On transacted channels the server MUST not purge messages that have + already been sent to a client but not yet acknowledged. + </rule> + <rule implement="MAY"> + <test>amq_queue_42</test> + 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. + </rule> + <chassis name="server" implement="MUST"/> + <response name="purge-ok"/> + <field name="ticket" domain="access ticket"> + <doc> + The access ticket must be for the access realm that holds the + queue. + </doc> + <rule implement="MUST"> + The client MUST provide a valid access ticket giving "read" access + rights to the queue's access realm. Note that purging a queue is + equivalent to reading all messages and discarding them. + </rule> + </field> + <field name = "queue" domain = "queue name"> + <doc> + Specifies the name of the queue to purge. If the queue name is + empty, refers to the current queue for the channel, which is + the last declared queue. + </doc> + <doc name = "rule"> + If the client did not previously declare a queue, and the queue + name in this method is empty, the server MUST raise a connection + exception with reply code 530 (not allowed). + </doc> + <doc name = "rule" test = "amq_queue_16"> + The queue must exist. Attempting to purge a non-existing queue + causes a channel exception. + </doc> + </field> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> + </method> + <method name="purge-ok" synchronous="1" index="31"> + confirms a queue purge + <doc> + This method confirms the purge of a queue. + </doc> + <chassis name="client" implement="MUST"/> + <field name="message count" type="long"> + number of messages purged + <doc> + Reports the number of messages purged. + </doc> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="delete" synchronous="1" index="40"> + delete a queue + <doc> + This method deletes a queue. When a queue is deleted any pending + messages are sent to a dead-letter queue if this is defined in the + server configuration, and all consumers on the queue are cancelled. + </doc> + <rule implement="SHOULD"> + <test>amq_queue_43</test> + The server SHOULD use a dead-letter queue to hold messages that + were pending on a deleted queue, and MAY provide facilities for + a system administrator to move these messages back to an active + queue. + </rule> + <chassis name="server" implement="MUST"/> + <response name="delete-ok"/> + <field name="ticket" domain="access ticket"> + <doc> + The client provides a valid access ticket giving "active" + access rights to the queue's access realm. + </doc> + </field> + + <field name = "queue" domain = "queue name"> + <doc> + Specifies the name of the queue to delete. If the queue name is + empty, refers to the current queue for the channel, which is the + last declared queue. + </doc> + <doc name = "rule"> + If the client did not previously declare a queue, and the queue + name in this method is empty, the server MUST raise a connection + exception with reply code 530 (not allowed). + </doc> + <doc name = "rule" test = "amq_queue_21"> + The queue must exist. Attempting to delete a non-existing queue + causes a channel exception. + </doc> + </field> + + <field name="if unused" type="bit"> + 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 a channel exception instead. + </doc> + <rule implement="MUST"> + <test>amq_queue_29</test> + <test>amq_queue_30</test> + The server MUST respect the if-unused flag when deleting a queue. + </rule> + </field> + <field name="if empty" type="bit"> + delete only if empty + <test>amq_queue_27</test> + <doc> + If set, the server will only delete the queue if it has no + messages. If the queue is not empty the server raises a channel + exception. + </doc> + </field> + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> + </method> + + <method name="delete-ok" synchronous="1" index="41"> + confirm deletion of a queue + <doc> + This method confirms the deletion of a queue. + </doc> + <chassis name="client" implement="MUST"/> + <field name="message count" type="long"> + number of messages purged + <doc> + Reports the number of messages purged. + </doc> + </field> + </method> + </class> + <class name="basic" handler="channel" index="60"> + <!-- +====================================================== +== BASIC MIDDLEWARE +====================================================== +--> + work with basic content +<doc> + The Basic class provides methods that support an industry-standard + messaging model. +</doc> + +<doc name = "grammar"> + basic = C:QOS S:QOS-OK + / C:CONSUME S:CONSUME-OK + / C:CANCEL S:CANCEL-OK + / C:PUBLISH content + / S:RETURN content + / S:DELIVER content + / C:GET ( S:GET-OK content / S:GET-EMPTY ) + / C:ACK + / C:REJECT +</doc> + +<chassis name = "server" implement = "MUST" /> +<chassis name = "client" implement = "MAY" /> + +<doc name = "rule" test = "amq_basic_08"> + The server SHOULD respect the persistent property of basic messages + and SHOULD make a best-effort to hold persistent basic messages on a + reliable storage mechanism. +</doc> +<doc name = "rule" test = "amq_basic_09"> + The server MUST NOT discard a persistent basic message in case of a + queue overflow. The server MAY use the Channel.Flow method to slow + or stop a basic message publisher when necessary. +</doc> +<doc name = "rule" test = "amq_basic_10"> + The server MAY overflow non-persistent basic messages to persistent + storage and MAY discard or dead-letter non-persistent basic messages + on a priority basis if the queue size exceeds some configured limit. +</doc> +<doc name = "rule" test = "amq_basic_11"> + The server MUST implement at least 2 priority levels for basic + messages, where priorities 0-4 and 5-9 are treated as two distinct + levels. The server MAY implement up to 10 priority levels. +</doc> +<doc name = "rule" test = "amq_basic_12"> + The server MUST deliver messages of the same priority in order + irrespective of their individual persistence. +</doc> +<doc name = "rule" test = "amq_basic_13"> + The server MUST support both automatic and explicit acknowledgements + on Basic content. +</doc> + +<!-- These are the properties for a Basic content --> + +<field name = "content type" type = "shortstr"> + MIME content type +</field> +<field name = "content encoding" type = "shortstr"> + MIME content encoding +</field> +<field name = "headers" type = "table"> + Message header field table +</field> +<field name = "delivery mode" type = "octet"> + Non-persistent (1) or persistent (2) +</field> +<field name = "priority" type = "octet"> + The message priority, 0 to 9 +</field> +<field name = "correlation id" type = "shortstr"> + The application correlation identifier +</field> +<field name = "reply to" type = "shortstr"> + The destination to reply to +</field> +<field name = "expiration" type = "shortstr"> + Message expiration specification +</field> +<field name = "message id" type = "shortstr"> + The application message identifier +</field> +<field name = "timestamp" type = "timestamp"> + The message timestamp +</field> +<field name = "type" type = "shortstr"> + The message type name +</field> +<field name = "user id" type = "shortstr"> + The creating user id +</field> +<field name = "app id" type = "shortstr"> + The creating application id +</field> +<field name = "cluster id" type = "shortstr"> + Intra-cluster routing identifier +</field> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "qos" synchronous = "1" index = "10"> + specify quality of service + <doc> + This method requests a specific quality of service. The QoS can + be specified for the current channel or for all channels on the + connection. The particular properties and semantics of a qos method + always depend on the content class semantics. Though the qos method + could in principle apply to both peers, it is currently meaningful + only for the server. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "qos-ok" /> + + <field name = "prefetch size" type = "long"> + prefetch 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 + down the channel. Prefetching gives a performance improvement. + This field specifies the prefetch window size in octets. The + server will send a message in advance if it is equal to or + smaller in size than the available prefetch size (and also falls + into other prefetch limits). May be set to zero, meaning "no + specific limit", although other prefetch limits may still apply. + The prefetch-size is ignored if the no-ack option is set. + </doc> + <doc name = "rule" test = "amq_basic_17"> + The server MUST ignore this setting when the client is not + processing any messages - i.e. the prefetch size does not limit + the transfer of single messages to a client, only the sending in + advance of more messages while the client still has one or more + unacknowledged messages. + </doc> + </field> + + <field name = "prefetch count" type = "short"> + prefetch window in messages + <doc> + Specifies a prefetch 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 prefetch windows + (and those at the channel and connection level) allow it. + The prefetch-count is ignored if the no-ack option is set. + </doc> + <doc name = "rule" test = "amq_basic_18"> + The server MAY send less data in advance than allowed by the + client's specified prefetch windows but it MUST NOT send more. + </doc> + </field> + + <field name = "global" type = "bit"> + apply to entire connection + <doc> + By default the QoS settings apply to the current channel only. If + this field is set, they are applied to the entire connection. + </doc> + </field> +</method> + +<method name = "qos-ok" synchronous = "1" index = "11"> + confirm the requested qos + <doc> + This method 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> + <chassis name = "client" implement = "MUST" /> +</method> + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "consume" synchronous = "1" index = "20"> + start a queue consumer + <doc> + This method asks the server to start a "consumer", which is a + transient request for messages from a specific queue. Consumers + last as long as the channel they were created on, or until the + client cancels them. + </doc> + <doc name = "rule" test = "amq_basic_01"> + 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> + <chassis name = "server" implement = "MUST" /> + <response name = "consume-ok" /> + + <field name = "ticket" domain = "access ticket"> + <doc name = "rule"> + The client MUST provide a valid access ticket giving "read" access + rights to the realm for the queue. + </doc> + </field> + + <field name = "queue" domain = "queue name"> + <doc> + Specifies the name of the queue to consume from. If the queue name + is null, refers to the current queue for the channel, which is the + last declared queue. + </doc> + <doc name = "rule"> + If the client did not previously declare a queue, and the queue name + in this method is empty, the server MUST raise a connection exception + with reply code 530 (not allowed). + </doc> + </field> + + <field name = "consumer tag" domain = "consumer tag"> + <doc> + Specifies the identifier for the consumer. The consumer tag is + local to a connection, so two clients can use the same consumer + tags. If this field is empty the server will generate a unique + tag. + </doc> + <doc name = "rule" test = "todo"> + 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 a connection exception with reply code + 530 (not allowed). + </doc> + </field> + + <field name = "no local" domain = "no local" /> + + <field name = "no ack" domain = "no ack" /> + + <field name = "exclusive" type = "bit"> + request exclusive access + <doc> + Request exclusive consumer access, meaning only this consumer can + access the queue. + </doc> + <doc name = "rule" test = "amq_basic_02"> + If the server cannot grant exclusive access to the queue when asked, + - because there are other consumers active - it MUST raise a channel + exception with return code 403 (access refused). + </doc> + </field> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> + + <field name="arguments" type="table" label="arguments for consuming"> + <doc> + A set of arguments for the consume. The syntax and semantics + of these arguments depends on the server implementation. This + field is ignored if passive is 1. + </doc> + </field> +</method> + +<method name = "consume-ok" synchronous = "1" index = "21"> + confirm a new consumer + <doc> + The server provides the client with a consumer tag, which is used + by the client for methods called on the consumer at a later stage. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag"> + <doc> + Holds the consumer tag specified by the client or provided by + the server. + </doc> + </field> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "cancel" synchronous = "1" index = "30"> + end a queue consumer + <doc test = "amq_basic_04"> + This method 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. The client may receive an + abitrary number of messages in between sending the cancel method + and receiving the cancel-ok reply. + </doc> + <doc name = "rule" test = "todo"> + If the queue no longer exists when the client sends a cancel command, + or the consumer has been cancelled for other reasons, this command + has no effect. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "cancel-ok" /> + + <field name = "consumer tag" domain = "consumer tag" /> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> +</method> + +<method name = "cancel-ok" synchronous = "1" index = "31"> + confirm a cancelled consumer + <doc> + This method confirms that the cancellation was completed. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag" /> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "publish" content = "1" index = "40"> + publish a message + <doc> + This method 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 when the transaction, if any, + is committed. + </doc> + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access ticket"> + <doc name = "rule"> + The client MUST provide a valid access ticket giving "write" + access rights to the access realm for the exchange. + </doc> + </field> + + <field name = "exchange" domain = "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 a channel exception. + </doc> + <doc name = "rule" test = "amq_basic_06"> + The server MUST accept a blank exchange name to mean the default + exchange. + </doc> + <doc name = "rule" test = "amq_basic_14"> + If the exchange was declared as an internal exchange, the server + MUST raise a channel exception with a reply code 403 (access + refused). + </doc> + <doc name = "rule" test = "amq_basic_15"> + The exchange MAY refuse basic content in which case it MUST raise + a channel exception with reply code 540 (not implemented). + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + 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"> + 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 method. If this flag is zero, the + server silently drops the message. + </doc> + <doc name = "rule" test = "amq_basic_07"> + The server SHOULD implement the mandatory flag. + </doc> + </field> + + <field name = "immediate" type = "bit"> + 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 method. + If this flag is zero, the server will queue the message, but with + no guarantee that it will ever be consumed. + </doc> + <doc name = "rule" test = "amq_basic_16"> + The server SHOULD implement the immediate flag. + </doc> + </field> +</method> + +<method name = "return" content = "1" index = "50"> + return a failed message + <doc> + This method 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> + <chassis name = "client" implement = "MUST" /> + + <field name = "reply code" domain = "reply code" /> + <field name = "reply text" domain = "reply text" /> + + <field name = "exchange" domain = "exchange name"> + <doc> + Specifies the name of the exchange that the message was + originally published to. + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + Message routing key + <doc> + Specifies the routing key name specified when the message was + published. + </doc> + </field> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "deliver" content = "1" index = "60"> + notify the client of a consumer message + <doc> + This method delivers a message to the client, via a consumer. In + the asynchronous message delivery model, the client starts a + consumer using the Consume method, then the server responds with + Deliver methods as and when messages arrive for that consumer. + </doc> + <doc name = "rule" test = "amq_basic_19"> + 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 unprocessable (possibly + causing client applications to abort), and move the message to a + dead letter queue. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag" /> + + <field name = "delivery tag" domain = "delivery tag" /> + + <field name = "redelivered" domain = "redelivered" /> + + <field name = "exchange" domain = "exchange name"> + <doc> + Specifies the name of the exchange that the message was + originally published to. + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + Message routing key + <doc> + Specifies the routing key name specified when the message was + published. + </doc> + </field> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "get" synchronous = "1" index = "70"> + direct access to a queue + <doc> + This method provides a direct access to the messages in a queue + using a synchronous dialogue that is designed for specific types of + application where synchronous functionality is more important than + performance. + </doc> + <response name = "get-ok" /> + <response name = "get-empty" /> + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access ticket"> + <doc name = "rule"> + The client MUST provide a valid access ticket giving "read" + access rights to the realm for the queue. + </doc> + </field> + + <field name = "queue" domain = "queue name"> + <doc> + Specifies the name of the queue to consume from. If the queue name + is null, refers to the current queue for the channel, which is the + last declared queue. + </doc> + <doc name = "rule"> + If the client did not previously declare a queue, and the queue name + in this method is empty, the server MUST raise a connection exception + with reply code 530 (not allowed). + </doc> + </field> + + <field name = "no ack" domain = "no ack" /> +</method> + +<method name = "get-ok" synchronous = "1" content = "1" index = "71"> + provide client with a message + <doc> + This method delivers a message to the client following a get + method. A message delivered by 'get-ok' must be acknowledged + unless the no-ack option was set in the get method. + </doc> + <chassis name = "client" implement = "MAY" /> + + <field name = "delivery tag" domain = "delivery tag" /> + + <field name = "redelivered" domain = "redelivered" /> + + <field name = "exchange" domain = "exchange name"> + <doc> + Specifies the name of the exchange that the message was originally + published to. If empty, the message was published to the default + exchange. + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + Message routing key + <doc> + Specifies the routing key name specified when the message was + published. + </doc> + </field> + + <field name = "message count" type = "long" > + number of messages pending + <doc> + This field reports the number of messages pending on the queue, + excluding the message being delivered. Note that this figure is + indicative, not reliable, and can change arbitrarily as messages + are added to the queue and removed by other clients. + </doc> + </field> +</method> + + +<method name = "get-empty" synchronous = "1" index = "72"> + indicate no messages available + <doc> + This method tells the client that the queue has no messages + available for the client. + </doc> + <chassis name = "client" implement = "MAY" /> + + <field name = "cluster id" type = "shortstr"> + Cluster id + <doc> + For use by cluster applications, should not be used by + client applications. + </doc> + </field> +</method> + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "ack" index = "80"> + acknowledge one or more messages + <doc> + This method acknowledges one or more messages delivered via the + Deliver or Get-Ok methods. The client can ask to confirm a + single message or a set of messages up to and including a specific + message. + </doc> + <chassis name = "server" implement = "MUST" /> + <field name = "delivery tag" domain = "delivery tag" /> + + <field name = "multiple" type = "bit"> + 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 + method. 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 mesages. + </doc> + <doc name = "rule" test = "amq_basic_20"> + The server MUST validate that a non-zero delivery-tag refers to an + delivered message, and raise a channel exception if this is not the + case. + </doc> + </field> +</method> + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "reject" index = "90"> + reject an incoming message + <doc> + This method allows a client to reject a message. It can be used to + interrupt and cancel large incoming messages, or return untreatable + messages to their original queue. + </doc> + <doc name = "rule" test = "amq_basic_21"> + The server SHOULD be capable of accepting and process the Reject + method while sending message content with a Deliver or Get-Ok + method. I.e. the server should read and process incoming methods + while sending output frames. To cancel a partially-send content, + the server sends a content body frame of size 1 (i.e. with no data + except the frame-end octet). + </doc> + <doc name = "rule" test = "amq_basic_22"> + The server SHOULD interpret this method as meaning that the client + is unable to process the message at this time. + </doc> + <doc name = "rule"> + A client MUST NOT use this method as a means of selecting messages + to process. A rejected message MAY be discarded or dead-lettered, + not necessarily passed to another client. + </doc> + <chassis name = "server" implement = "MUST" /> + + <field name = "delivery tag" domain = "delivery tag" /> + + <field name = "requeue" type = "bit"> + 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> + <doc name = "rule" test = "amq_basic_23"> + The server MUST NOT deliver the message to the same client within + the context of the current channel. 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> + </field> +</method> + +<method name = "recover" index = "100"> + redeliver unacknowledged messages + <doc> + This method asks the broker to redeliver all unacknowledged messages on a + specified channel. Zero or more messages may be redelivered. This method + is only allowed on non-transacted channels. + </doc> + <chassis name = "server" implement = "MUST" /> + + <field name = "requeue" type = "bit"> + requeue the message + <doc> + If this field is zero, the message will be redelivered to the original + recipient. If this bit is 1, the server will attempt to requeue the + message, potentially then delivering it to an alternative subscriber. + </doc> + </field> + <doc name="rule"> + The server MUST set the redelivered flag on all messages that are resent. + </doc> + <doc name="rule"> + The server MUST raise a channel exception if this is called on a + transacted channel. + </doc> + <response name="recover-ok"/> + </method> + <method name="recover-ok" synchronous="1" index="101"> + confirm a successful recover + <doc> + This method confirms to the client that the recover succeeded. + Note that if an recover fails, the server raises a channel exception. + </doc> + <chassis name="client" implement="MUST"/> + </method> + +</class> + + + <class name="file" handler="channel" index="70"> + <!-- +====================================================== +== FILE TRANSFER +====================================================== +--> + work with file content +<doc> + The file class provides methods 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 channel transactions. Note that the + file class does not provide message browsing methods; these are not + compatible with the staging model. Applications that need browsable + file transfer should use Basic content and the Basic class. +</doc> + +<doc name = "grammar"> + file = C:QOS S:QOS-OK + / C:CONSUME S:CONSUME-OK + / C:CANCEL S:CANCEL-OK + / 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> + +<chassis name = "server" implement = "MAY" /> +<chassis name = "client" implement = "MAY" /> + +<doc name = "rule"> + The server MUST make a best-effort to hold file messages on a + reliable storage mechanism. +</doc> +<doc name = "rule"> + The server MUST NOT discard a file message in case of a queue + overflow. The server MUST use the Channel.Flow method to slow or stop + a file message publisher when necessary. +</doc> +<doc name = "rule"> + 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> +<doc name = "rule"> + The server MUST support both automatic and explicit acknowledgements + on file content. +</doc> + +<!-- These are the properties for a File content --> + +<field name = "content type" type = "shortstr"> + MIME content type +</field> +<field name = "content encoding" type = "shortstr"> + MIME content encoding +</field> +<field name = "headers" type = "table"> + Message header field table +</field> +<field name = "priority" type = "octet"> + The message priority, 0 to 9 +</field> +<field name = "reply to" type = "shortstr"> + The destination to reply to +</field> +<field name = "message id" type = "shortstr"> + The application message identifier +</field> +<field name = "filename" type = "shortstr"> + The message filename +</field> +<field name = "timestamp" type = "timestamp"> + The message timestamp +</field> +<field name = "cluster id" type = "shortstr"> + Intra-cluster routing identifier +</field> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "qos" synchronous = "1" index = "10"> + specify quality of service + <doc> + This method requests a specific quality of service. The QoS can + be specified for the current channel or for all channels on the + connection. The particular properties and semantics of a qos method + always depend on the content class semantics. Though the qos method + could in principle apply to both peers, it is currently meaningful + only for the server. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "qos-ok" /> + + <field name = "prefetch size" type = "long"> + prefetch 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 + down the channel. Prefetching gives a performance improvement. + This field specifies the prefetch window size in octets. May be + set to zero, meaning "no specific limit". Note that other + prefetch limits may still apply. The prefetch-size is ignored + if the no-ack option is set. + </doc> + </field> + + <field name = "prefetch count" type = "short"> + prefetch window in messages + <doc> + Specifies a prefetch 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 prefetch windows + (and those at the channel and connection level) allow it. + The prefetch-count is ignored if the no-ack option is set. + </doc> + <doc name = "rule"> + The server MAY send less data in advance than allowed by the + client's specified prefetch windows but it MUST NOT send more. + </doc> + </field> + + <field name = "global" type = "bit"> + apply to entire connection + <doc> + By default the QoS settings apply to the current channel only. If + this field is set, they are applied to the entire connection. + </doc> + </field> +</method> + +<method name = "qos-ok" synchronous = "1" index = "11"> + confirm the requested qos + <doc> + This method 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> + <chassis name = "client" implement = "MUST" /> +</method> + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "consume" synchronous = "1" index = "20"> + start a queue consumer + <doc> + This method asks the server to start a "consumer", which is a + transient request for messages from a specific queue. Consumers + last as long as the channel they were created on, or until the + client cancels them. + </doc> + <doc name = "rule"> + 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> + <chassis name = "server" implement = "MUST" /> + <response name = "consume-ok" /> + + <field name = "ticket" domain = "access ticket"> + <doc name = "rule"> + The client MUST provide a valid access ticket giving "read" access + rights to the realm for the queue. + </doc> + </field> + + <field name = "queue" domain = "queue name"> + <doc> + Specifies the name of the queue to consume from. If the queue name + is null, refers to the current queue for the channel, which is the + last declared queue. + </doc> + <doc name = "rule"> + If the client did not previously declare a queue, and the queue name + in this method is empty, the server MUST raise a connection exception + with reply code 530 (not allowed). + </doc> + </field> + + <field name = "consumer tag" domain = "consumer tag"> + <doc> + Specifies the identifier for the consumer. The consumer tag is + local to a connection, so two clients can use the same consumer + tags. If this field is empty the server will generate a unique + tag. + </doc> + <doc name = "rule" test = "todo"> + 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 a connection exception with reply code + 530 (not allowed). + </doc> + </field> + + <field name = "no local" domain = "no local" /> + + <field name = "no ack" domain = "no ack" /> + + <field name = "exclusive" type = "bit"> + request exclusive access + <doc> + Request exclusive consumer access, meaning only this consumer can + access the queue. + </doc> + <doc name = "rule" test = "amq_file_00"> + If the server cannot grant exclusive access to the queue when asked, + - because there are other consumers active - it MUST raise a channel + exception with return code 405 (resource locked). + </doc> + </field> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> +</method> + +<method name = "consume-ok" synchronous = "1" index = "21"> + confirm a new consumer + <doc> + This method provides the client with a consumer tag which it MUST + use in methods that work with the consumer. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag"> + <doc> + Holds the consumer tag specified by the client or provided by + the server. + </doc> + </field> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "cancel" synchronous = "1" index = "30"> + end a queue consumer + <doc> + This method 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> + <chassis name = "server" implement = "MUST" /> + <response name = "cancel-ok" /> + + <field name = "consumer tag" domain = "consumer tag" /> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> +</method> + +<method name = "cancel-ok" synchronous = "1" index = "31"> + confirm a cancelled consumer + <doc> + This method confirms that the cancellation was completed. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag" /> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "open" synchronous = "1" index = "40"> + request to start staging + <doc> + This method 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> + <response name = "open-ok" /> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <field name = "identifier" type = "shortstr"> + 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 = "longlong"> + 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> + <doc name = "rule"> + The sender MUST accurately fill the content-size field. + Zero-length content is permitted. + </doc> + </field> +</method> + +<method name = "open-ok" synchronous = "1" index = "41"> + confirm staging ready + <doc> + This method 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> + <response name = "stage" /> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <field name = "staged size" type = "longlong"> + already staged amount + <doc> + The amount of previously-staged content in octets. For a new + message this will be zero. + </doc> + <doc name = "rule"> + The sender MUST start sending data from this octet offset in the + message, counting from zero. + </doc> + <doc name = "rule"> + 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 methods. + </doc> + </field> +</method> + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "stage" content = "1" index = "50"> + stage message content + <doc> + This method stages the message, sending the message content to the + recipient from the octet offset specified in the Open-Ok method. + </doc> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "publish" index = "60"> + publish a message + <doc> + This method 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> + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access ticket"> + <doc name = "rule"> + The client MUST provide a valid access ticket giving "write" + access rights to the access realm for the exchange. + </doc> + </field> + + <field name = "exchange" domain = "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 a channel exception. + </doc> + <doc name = "rule"> + The server MUST accept a blank exchange name to mean the default + exchange. + </doc> + <doc name = "rule"> + If the exchange was declared as an internal exchange, the server + MUST respond with a reply code 403 (access refused) and raise a + channel exception. + </doc> + <doc name = "rule"> + The exchange MAY refuse file content in which case it MUST respond + with a reply code 540 (not implemented) and raise a channel + exception. + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + 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"> + 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 method. If this flag is zero, the + server silently drops the message. + </doc> + <doc name = "rule" test = "amq_file_00"> + The server SHOULD implement the mandatory flag. + </doc> + </field> + + <field name = "immediate" type = "bit"> + 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 method. + If this flag is zero, the server will queue the message, but with + no guarantee that it will ever be consumed. + </doc> + <doc name = "rule" test = "amq_file_00"> + The server SHOULD implement the immediate flag. + </doc> + </field> + + <field name = "identifier" type = "shortstr"> + 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 method asynchronously without waiting for staging to + finish. + </doc> + </field> +</method> + +<method name = "return" content = "1" index = "70"> + return a failed message + <doc> + This method 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> + <chassis name = "client" implement = "MUST" /> + + <field name = "reply code" domain = "reply code" /> + <field name = "reply text" domain = "reply text" /> + + <field name = "exchange" domain = "exchange name"> + <doc> + Specifies the name of the exchange that the message was + originally published to. + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + Message routing key + <doc> + Specifies the routing key name specified when the message was + published. + </doc> + </field> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "deliver" index = "80"> + notify the client of a consumer message + <doc> + This method 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 method, then the server + responds with Deliver methods as and when messages arrive for + that consumer. + </doc> + <doc name = "rule"> + 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 unprocessable (possibly + causing client applications to abort), and move the message to a + dead letter queue. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag" /> + + <field name = "delivery tag" domain = "delivery tag" /> + + <field name = "redelivered" domain = "redelivered" /> + + <field name = "exchange" domain = "exchange name"> + <doc> + Specifies the name of the exchange that the message was originally + published to. + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + Message routing key + <doc> + Specifies the routing key name specified when the message was + published. + </doc> + </field> + + <field name = "identifier" type = "shortstr"> + 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 method asynchronously without waiting for staging to + finish. + </doc> + </field> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "ack" index = "90"> + acknowledge one or more messages + <doc> + This method acknowledges one or more messages delivered via the + Deliver method. The client can ask to confirm a single message or + a set of messages up to and including a specific message. + </doc> + <chassis name = "server" implement = "MUST" /> + <field name = "delivery tag" domain = "delivery tag" /> + + <field name = "multiple" type = "bit"> + 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 + method. 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 mesages. + </doc> + <doc name = "rule"> + The server MUST validate that a non-zero delivery-tag refers to an + delivered message, and raise a channel exception if this is not the + case. + </doc> + </field> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "reject" index = "100"> + reject an incoming message + <doc> + This method 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 + method to interrupt delivery of a large message. + </doc> + <doc name = "rule"> + The server SHOULD interpret this method as meaning that the client + is unable to process the message at this time. + </doc> + <doc name = "rule"> + A client MUST NOT use this method as a means of selecting messages + to process. A rejected message MAY be discarded or dead-lettered, + not necessarily passed to another client. + </doc> + <chassis name = "server" implement = "MUST" /> + + <field name = "delivery tag" domain = "delivery tag" /> + + <field name = "requeue" type = "bit"> + 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> + <doc name = "rule"> + The server MUST NOT deliver the message to the same client within + the context of the current channel. 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> + </field> +</method> + +</class> + + <class name="stream" handler="channel" index="80"> + <!-- +====================================================== +== STREAMING +====================================================== +--> + work with streaming content + +<doc> + The stream class provides methods that support multimedia streaming. + The stream class uses the following semantics: one message is one + packet of data; delivery is unacknowleged 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 favour of high + priority messages. +</doc> + +<doc name = "grammar"> + stream = C:QOS S:QOS-OK + / C:CONSUME S:CONSUME-OK + / C:CANCEL S:CANCEL-OK + / C:PUBLISH content + / S:RETURN + / S:DELIVER content +</doc> + +<chassis name = "server" implement = "MAY" /> +<chassis name = "client" implement = "MAY" /> + +<doc name = "rule"> + The server SHOULD discard stream messages on a priority basis if + the queue size exceeds some configured limit. +</doc> +<doc name = "rule"> + 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> +<doc name = "rule"> + The server MUST implement automatic acknowledgements on stream + content. That is, as soon as a message is delivered to a client + via a Deliver method, the server must remove it from the queue. +</doc> + + +<!-- These are the properties for a Stream content --> + +<field name = "content type" type = "shortstr"> + MIME content type +</field> +<field name = "content encoding" type = "shortstr"> + MIME content encoding +</field> +<field name = "headers" type = "table"> + Message header field table +</field> +<field name = "priority" type = "octet"> + The message priority, 0 to 9 +</field> +<field name = "timestamp" type = "timestamp"> + The message timestamp +</field> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "qos" synchronous = "1" index = "10"> + specify quality of service + <doc> + This method requests a specific quality of service. The QoS can + be specified for the current channel or for all channels on the + connection. The particular properties and semantics of a qos method + always depend on the content class semantics. Though the qos method + could in principle apply to both peers, it is currently meaningful + only for the server. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "qos-ok" /> + + <field name = "prefetch size" type = "long"> + prefetch 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 + down the channel. Prefetching gives a performance improvement. + This field specifies the prefetch window size in octets. May be + set to zero, meaning "no specific limit". Note that other + prefetch limits may still apply. + </doc> + </field> + + <field name = "prefetch count" type = "short"> + prefetch window in messages + <doc> + Specifies a prefetch 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 prefetch windows + (and those at the channel and connection level) allow it. + </doc> + </field> + + <field name = "consume rate" type = "long"> + 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> + <doc name = "rule"> + The server MAY ignore the prefetch values and consume rates, + depending on the type of stream and the ability of the server + to queue and/or reply it. The server MAY drop low-priority + messages in favour of high-priority messages. + </doc> + </field> + + <field name = "global" type = "bit"> + apply to entire connection + <doc> + By default the QoS settings apply to the current channel only. If + this field is set, they are applied to the entire connection. + </doc> + </field> +</method> + +<method name = "qos-ok" synchronous = "1" index = "11"> + confirm the requested qos + <doc> + This method 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> + <chassis name = "client" implement = "MUST" /> +</method> + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "consume" synchronous = "1" index = "20"> + start a queue consumer + <doc> + This method asks the server to start a "consumer", which is a + transient request for messages from a specific queue. Consumers + last as long as the channel they were created on, or until the + client cancels them. + </doc> + <doc name = "rule"> + 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> + <doc name = "rule"> + Streaming applications SHOULD use different channels 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> + <chassis name = "server" implement = "MUST" /> + <response name = "consume-ok" /> + + <field name = "ticket" domain = "access ticket"> + <doc name = "rule"> + The client MUST provide a valid access ticket giving "read" access + rights to the realm for the queue. + </doc> + </field> + + <field name = "queue" domain = "queue name"> + <doc> + Specifies the name of the queue to consume from. If the queue name + is null, refers to the current queue for the channel, which is the + last declared queue. + </doc> + <doc name = "rule"> + If the client did not previously declare a queue, and the queue name + in this method is empty, the server MUST raise a connection exception + with reply code 530 (not allowed). + </doc> + </field> + + <field name = "consumer tag" domain = "consumer tag"> + <doc> + Specifies the identifier for the consumer. The consumer tag is + local to a connection, so two clients can use the same consumer + tags. If this field is empty the server will generate a unique + tag. + </doc> + <doc name = "rule" test = "todo"> + 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 a connection exception with reply code + 530 (not allowed). + </doc> + </field> + + <field name = "no local" domain = "no local" /> + + <field name = "exclusive" type = "bit"> + request exclusive access + <doc> + Request exclusive consumer access, meaning only this consumer can + access the queue. + </doc> + <doc name = "rule" test = "amq_file_00"> + If the server cannot grant exclusive access to the queue when asked, + - because there are other consumers active - it MUST raise a channel + exception with return code 405 (resource locked). + </doc> + </field> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> +</method> + + +<method name = "consume-ok" synchronous = "1" index = "21"> + confirm a new consumer + <doc> + This method provides the client with a consumer tag which it may + use in methods that work with the consumer. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag"> + <doc> + Holds the consumer tag specified by the client or provided by + the server. + </doc> + </field> +</method> + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "cancel" synchronous = "1" index = "30"> + end a queue consumer + <doc> + This method cancels a consumer. Since message delivery is + asynchronous the client may continue to receive messages for + a short while after canceling a consumer. It may process or + discard these as appropriate. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "cancel-ok" /> + + <field name = "consumer tag" domain = "consumer tag" /> + + <field name = "nowait" type = "bit"> + do not send a reply method + <doc> + If set, the server will not respond to the method. The client should + not wait for a reply method. If the server could not complete the + method it will raise a channel or connection exception. + </doc> + </field> +</method> + +<method name = "cancel-ok" synchronous = "1" index = "31"> + confirm a cancelled consumer + <doc> + This method confirms that the cancellation was completed. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag" /> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "publish" content = "1" index = "40"> + publish a message + <doc> + This method 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> + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access ticket"> + <doc name = "rule"> + The client MUST provide a valid access ticket giving "write" + access rights to the access realm for the exchange. + </doc> + </field> + + <field name = "exchange" domain = "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 a channel exception. + </doc> + <doc name = "rule"> + The server MUST accept a blank exchange name to mean the default + exchange. + </doc> + <doc name = "rule"> + If the exchange was declared as an internal exchange, the server + MUST respond with a reply code 403 (access refused) and raise a + channel exception. + </doc> + <doc name = "rule"> + The exchange MAY refuse stream content in which case it MUST + respond with a reply code 540 (not implemented) and raise a + channel exception. + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + 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"> + 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 method. If this flag is zero, the + server silently drops the message. + </doc> + <doc name = "rule" test = "amq_stream_00"> + The server SHOULD implement the mandatory flag. + </doc> + </field> + + <field name = "immediate" type = "bit"> + 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 method. + If this flag is zero, the server will queue the message, but with + no guarantee that it will ever be consumed. + </doc> + <doc name = "rule" test = "amq_stream_00"> + The server SHOULD implement the immediate flag. + </doc> + </field> +</method> + +<method name = "return" content = "1" index = "50"> + return a failed message + <doc> + This method 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> + <chassis name = "client" implement = "MUST" /> + + <field name = "reply code" domain = "reply code" /> + <field name = "reply text" domain = "reply text" /> + + <field name = "exchange" domain = "exchange name"> + <doc> + Specifies the name of the exchange that the message was + originally published to. + </doc> + </field> + + <field name = "routing key" type = "shortstr"> + Message routing key + <doc> + Specifies the routing key name specified when the message was + published. + </doc> + </field> +</method> + + +<!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + +<method name = "deliver" content = "1" index = "60"> + notify the client of a consumer message + <doc> + This method delivers a message to the client, via a consumer. In + the asynchronous message delivery model, the client starts a + consumer using the Consume method, then the server responds with + Deliver methods as and when messages arrive for that consumer. + </doc> + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer tag" domain = "consumer tag" /> + + <field name = "delivery tag" domain = "delivery tag" /> + + <field name = "exchange" domain = "exchange name"> + <doc> + Specifies the name of the exchange that the message was originally + published to. + </doc> + </field> + + <field name = "queue" domain = "queue name"> + <doc> + Specifies the name of the queue that the message came from. Note + that a single channel can start many consumers on different + queues. + </doc> + <assert check = "notnull" /> + </field> +</method> + </class> + + <class name="tx" handler="channel" index="90"> + <!-- +====================================================== +== TRANSACTIONS +====================================================== +--> + 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> + <rule implement="SHOULD"> + 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. +</rule> + <doc name="grammar"> + tx = C:SELECT S:SELECT-OK + / C:COMMIT S:COMMIT-OK + / C:ROLLBACK S:ROLLBACK-OK +</doc> + <chassis name="server" implement="SHOULD"/> + <chassis name="client" implement="MAY"/> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="select" synchronous="1" index="10"> +select standard transaction mode + <doc> + This method sets the channel to use standard transactions. The + client must use this method at least once on a channel before + using the Commit or Rollback methods. + </doc> + <chassis name="server" implement="MUST"/> + <response name="select-ok"/> + </method> + <method name="select-ok" synchronous="1" index="11"> +confirm transaction mode + <doc> + This method confirms to the client that the channel was successfully + set to use standard transactions. + </doc> + <chassis name="client" implement="MUST"/> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="commit" synchronous="1" index="20"> +commit the current transaction + <doc> + This method commits all messages published and acknowledged in + the current transaction. A new transaction starts immediately + after a commit. + </doc> + <chassis name="server" implement="MUST"/> + <response name="commit-ok"/> + </method> + <method name="commit-ok" synchronous="1" index="21"> +confirm a successful commit + <doc> + This method confirms to the client that the commit succeeded. + Note that if a commit fails, the server raises a channel exception. + </doc> + <chassis name="client" implement="MUST"/> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="rollback" synchronous="1" index="30"> +abandon the current transaction + <doc> + This method abandons all messages published and acknowledged in + the current transaction. A new transaction starts immediately + after a rollback. + </doc> + <chassis name="server" implement="MUST"/> + <response name="rollback-ok"/> + </method> + <method name="rollback-ok" synchronous="1" index="31"> +confirm a successful rollback + <doc> + This method confirms to the client that the rollback succeeded. + Note that if an rollback fails, the server raises a channel exception. + </doc> + <chassis name="client" implement="MUST"/> + </method> + </class> + <class name="dtx" handler="channel" index="100"> + <!-- +====================================================== +== DISTRIBUTED TRANSACTIONS +====================================================== +--> + work with distributed transactions + +<doc> + Distributed transactions provide so-called "2-phase commit". The + AMQP distributed transaction model supports the X-Open XA + architecture and other distributed transaction implementations. + The Dtx class assumes that the server has a private communications + channel (not AMQP) to a distributed transaction coordinator. +</doc> + <doc name="grammar"> + dtx = C:SELECT S:SELECT-OK + C:START S:START-OK +</doc> + <chassis name="server" implement="MAY"/> + <chassis name="client" implement="MAY"/> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="select" synchronous="1" index="10"> +select standard transaction mode + <doc> + This method sets the channel to use distributed transactions. The + client must use this method at least once on a channel before + using the Start method. + </doc> + <chassis name="server" implement="MUST"/> + <response name="select-ok"/> + </method> + <method name="select-ok" synchronous="1" index="11"> +confirm transaction mode + <doc> + This method confirms to the client that the channel was successfully + set to use distributed transactions. + </doc> + <chassis name="client" implement="MUST"/> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="start" synchronous="1" index="20"> + start a new distributed transaction + <doc> + This method starts a new distributed transaction. This must be + the first method on a new channel that uses the distributed + transaction mode, before any methods that publish or consume + messages. + </doc> + <chassis name="server" implement="MAY"/> + <response name="start-ok"/> + <field name="dtx identifier" type="shortstr"> + transaction identifier + <doc> + The distributed transaction key. This identifies the transaction + so that the AMQP server can coordinate with the distributed + transaction coordinator. + </doc> + <assert check="notnull"/> + </field> + </method> + <method name="start-ok" synchronous="1" index="21"> + confirm the start of a new distributed transaction + <doc> + This method confirms to the client that the transaction started. + Note that if a start fails, the server raises a channel exception. + </doc> + <chassis name="client" implement="MUST"/> + </method> + </class> + <class name="tunnel" handler="tunnel" index="110"> + <!-- +====================================================== +== TUNNEL +====================================================== +--> + methods for protocol tunneling. + +<doc> + The tunnel methods are used to send blocks of binary data - which + can be serialised AMQP methods or other protocol frames - between + AMQP peers. +</doc> + <doc name="grammar"> + tunnel = C:REQUEST + / S:REQUEST +</doc> + <chassis name="server" implement="MAY"/> + <chassis name="client" implement="MAY"/> + <field name="headers" type="table"> + Message header field table +</field> + <field name="proxy name" type="shortstr"> + The identity of the tunnelling proxy +</field> + <field name="data name" type="shortstr"> + The name or type of the message being tunnelled +</field> + <field name="durable" type="octet"> + The message durability indicator +</field> + <field name="broadcast" type="octet"> + The message broadcast mode +</field> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="request" content="1" index="10"> + sends a tunnelled method + <doc> + This method tunnels a block of binary data, which can be an + encoded AMQP method or other data. The binary data is sent + as the content for the Tunnel.Request method. + </doc> + <chassis name="server" implement="MUST"/> + <field name="meta data" type="table"> + meta data for the tunnelled block + <doc> + This field table holds arbitrary meta-data that the sender needs + to pass to the recipient. + </doc> + </field> + </method> + </class> + <class name="test" handler="channel" index="120"> + <!-- +====================================================== +== TEST - CHECK FUNCTIONAL CAPABILITIES OF AN IMPLEMENTATION +====================================================== +--> + test functional primitives of the implementation + +<doc> + The test class provides methods for a peer to test the basic + operational correctness of another peer. The test methods are + intended to ensure that all peers respect at least the basic + elements of the protocol, such as frame and content organisation + and field types. We assume that a specially-designed peer, a + "monitor client" would perform such tests. +</doc> + <doc name="grammar"> + test = C:INTEGER S:INTEGER-OK + / S:INTEGER C:INTEGER-OK + / C:STRING S:STRING-OK + / S:STRING C:STRING-OK + / C:TABLE S:TABLE-OK + / S:TABLE C:TABLE-OK + / C:CONTENT S:CONTENT-OK + / S:CONTENT C:CONTENT-OK +</doc> + <chassis name="server" implement="MUST"/> + <chassis name="client" implement="SHOULD"/> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="integer" synchronous="1" index="10"> + test integer handling + <doc> + This method tests the peer's capability to correctly marshal integer + data. + </doc> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <response name="integer-ok"/> + <field name="integer 1" type="octet"> + octet test value + <doc> + An octet integer test value. + </doc> + </field> + <field name="integer 2" type="short"> + short test value + <doc> + A short integer test value. + </doc> + </field> + <field name="integer 3" type="long"> + long test value + <doc> + A long integer test value. + </doc> + </field> + <field name="integer 4" type="longlong"> + long-long test value + <doc> + A long long integer test value. + </doc> + </field> + <field name="operation" type="octet"> + operation to test + <doc> + The client must execute this operation on the provided integer + test fields and return the result. + </doc> + <assert check="enum"> + <value name="add">return sum of test values</value> + <value name="min">return lowest of test values</value> + <value name="max">return highest of test values</value> + </assert> + </field> + </method> + <method name="integer-ok" synchronous="1" index="11"> + report integer test result + <doc> + This method reports the result of an Integer method. + </doc> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <field name="result" type="longlong"> + result value + <doc> + The result of the tested operation. + </doc> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="string" synchronous="1" index="20"> + test string handling + <doc> + This method tests the peer's capability to correctly marshal string + data. + </doc> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <response name="string-ok"/> + <field name="string 1" type="shortstr"> + short string test value + <doc> + An short string test value. + </doc> + </field> + <field name="string 2" type="longstr"> + long string test value + <doc> + A long string test value. + </doc> + </field> + <field name="operation" type="octet"> + operation to test + <doc> + The client must execute this operation on the provided string + test fields and return the result. + </doc> + <assert check="enum"> + <value name="add">return concatentation of test strings</value> + <value name="min">return shortest of test strings</value> + <value name="max">return longest of test strings</value> + </assert> + </field> + </method> + <method name="string-ok" synchronous="1" index="21"> + report string test result + <doc> + This method reports the result of a String method. + </doc> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <field name="result" type="longstr"> + result value + <doc> + The result of the tested operation. + </doc> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="table" synchronous="1" index="30"> + test field table handling + <doc> + This method tests the peer's capability to correctly marshal field + table data. + </doc> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <response name="table-ok"/> + <field name="table" type="table"> + field table of test values + <doc> + A field table of test values. + </doc> + </field> + <field name="integer op" type="octet"> + operation to test on integers + <doc> + The client must execute this operation on the provided field + table integer values and return the result. + </doc> + <assert check="enum"> + <value name="add">return sum of numeric field values</value> + <value name="min">return min of numeric field values</value> + <value name="max">return max of numeric field values</value> + </assert> + </field> + <field name="string op" type="octet"> + operation to test on strings + <doc> + The client must execute this operation on the provided field + table string values and return the result. + </doc> + <assert check="enum"> + <value name="add">return concatenation of string field values</value> + <value name="min">return shortest of string field values</value> + <value name="max">return longest of string field values</value> + </assert> + </field> + </method> + <method name="table-ok" synchronous="1" index="31"> + report table test result + <doc> + This method reports the result of a Table method. + </doc> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <field name="integer result" type="longlong"> + integer result value + <doc> + The result of the tested integer operation. + </doc> + </field> + <field name="string result" type="longstr"> + string result value + <doc> + The result of the tested string operation. + </doc> + </field> + </method> + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <method name="content" synchronous="1" content="1" index="40"> + test content handling + <doc> + This method tests the peer's capability to correctly marshal content. + </doc> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <response name="content-ok"/> + </method> + <method name="content-ok" synchronous="1" content="1" index="41"> + report content test result + <doc> + This method reports the result of a Content method. It contains the + content checksum and echoes the original content as provided. + </doc> + <chassis name="client" implement="MUST"/> + <chassis name="server" implement="MUST"/> + <field name="content checksum" type="long"> + content hash + <doc> + The 32-bit checksum of the content, calculated by adding the + content into a 32-bit accumulator. + </doc> + </field> + </method> + </class> +</amqp> diff --git a/qpid/python/qpid/specs/amqp.0-9.xml b/qpid/python/qpid/specs/amqp.0-9.xml new file mode 100644 index 0000000000..73cace7015 --- /dev/null +++ b/qpid/python/qpid/specs/amqp.0-9.xml @@ -0,0 +1,5248 @@ +<?xml version = "1.0"?> + +<!-- + EDITORS: (PH) Pieter Hintjens <ph@imatix.com> + (KvdR) Kim van der Riet <kim.vdriet@redhat.com> + + These editors have been assigned by the AMQP working group. + Please do not edit/commit this file without consulting with + one of the above editors. + ======================================================== + + TODOs + - see TODO comments in the text +--> + +<!-- + Copyright Notice + ================ + (c) Copyright JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., + iMatix Corporation, IONA\ufffd Technologies, Red Hat, Inc., + TWIST Process Innovations, and 29West Inc. 2006. All rights reserved. + + License + ======= + JPMorgan Chase Bank & Co., Cisco Systems, Inc., Envoy Technologies Inc., iMatix + Corporation, IONA Technologies, Red Hat, Inc., TWIST Process Innovations, 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 +--> + +<!-- + <!DOCTYPE amqp SYSTEM "amqp.dtd"> +--> + +<!-- 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 spaces to seperate words in names, so that we can print names in + their natural form depending on the context - underlines for source code, + hyphens for written text, etc. + + 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. + + --> + +<amqp major = "0" minor = "9" port = "5672" comment = "AMQ Protocol version 0-9"> + <!-- + ====================================================== + == CONSTANTS + ====================================================== + --> + <!-- Frame types --> + <constant name = "frame-method" value = "1" /> + <constant name = "frame-header" value = "2" /> + <constant name = "frame-body" value = "3" /> + <constant name = "frame-oob-method" value = "4" /> + <constant name = "frame-oob-header" value = "5" /> + <constant name = "frame-oob-body" value = "6" /> + <constant name = "frame-trace" value = "7" /> + <constant name = "frame-heartbeat" value = "8" /> + + <!-- Protocol constants --> + <constant name = "frame-min-size" value = "4096" /> + <constant name = "frame-end" value = "206" /> + + <!-- Reply codes --> + <constant name = "reply-success" value = "200"> + <doc> + Indicates that the method completed successfully. This reply code is + reserved for future use - the current protocol design does not use positive + confirmation and reply codes are sent only in case of an error. + </doc> + </constant> + + <constant name = "not-delivered" value = "310" class = "soft-error"> + <doc> + The client asked for a specific message that is no longer available. + The message was delivered to another client, or was purged from the queue + for some other reason. + </doc> + </constant> + + <constant name = "content-too-large" value = "311" class = "soft-error"> + <doc> + The client attempted to transfer content larger than the server could accept + at the present time. The client may retry at a later time. + </doc> + </constant> + + <constant name = "no-route" value = "312" class = "soft-error"> + <doc> + When the exchange cannot route the result of a .Publish, most likely due + to an invalid routing key. Only when the mandatory flag is set. + </doc> + </constant> + + <constant name = "no-consumers" value = "313" class = "soft-error"> + <doc> + When 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> + </constant> + + <constant name = "connection-forced" value = "320" class = "hard-error"> + <doc> + An operator intervened to close the connection for some reason. The client + may retry at some later date. + </doc> + </constant> + + <constant name = "invalid-path" value = "402" class = "hard-error"> + <doc> + The client tried to work with an unknown virtual host. + </doc> + </constant> + + <constant name = "access-refused" value = "403" class = "soft-error"> + <doc> + The client attempted to work with a server entity to which it has no + access due to security settings. + </doc> + </constant> + + <constant name = "not-found" value = "404" class = "soft-error"> + <doc>The client attempted to work with a server entity that does not exist.</doc> + </constant> + + <constant name = "resource-locked" value = "405" class = "soft-error"> + <doc> + The client attempted to work with a server entity to which it has no + access because another client is working with it. + </doc> + </constant> + + <constant name = "precondition-failed" value = "406" class = "soft-error"> + <doc> + The client requested a method that was not allowed because some precondition + failed. + </doc> + </constant> + + <constant name = "frame-error" value = "501" class = "hard-error"> + <doc> + The client sent a malformed frame that the server could not decode. This + strongly implies a programming error in the client. + </doc> + </constant> + + <constant name = "syntax-error" value = "502" class = "hard-error"> + <doc> + The client sent a frame that contained illegal values for one or more + fields. This strongly implies a programming error in the client. + </doc> + </constant> + + <constant name = "command-invalid" value = "503" class = "hard-error"> + <doc> + The client sent an invalid sequence of frames, attempting to perform an + operation that was considered invalid by the server. This usually implies + a programming error in the client. + </doc> + </constant> + + <constant name = "channel-error" value = "504" class = "hard-error"> + <doc> + The client attempted to work with a channel that had not been correctly + opened. This most likely indicates a fault in the client layer. + </doc> + </constant> + + <constant name = "resource-error" value = "506" class = "hard-error"> + <doc> + The server could not complete the method because it lacked sufficient + resources. This may be due to the client creating too many of some type + of entity. + </doc> + </constant> + + <constant name = "not-allowed" value = "530" class = "hard-error"> + <doc> + The client tried to work with some entity in a manner that is prohibited + by the server, due to security settings or by some other criteria. + </doc> + </constant> + + <constant name = "not-implemented" value = "540" class = "hard-error"> + <doc> + The client tried to use functionality that is not implemented in the + server. + </doc> + </constant> + + <constant name = "internal-error" value = "541" class = "hard-error"> + <doc> + The server could not complete the method because of an internal error. + The server may require intervention by an operator in order to resume + normal operations. + </doc> + </constant> + + <!-- + ====================================================== + == DOMAIN TYPES + ====================================================== + --> + + <domain name = "access-ticket" type = "short" label = "access ticket granted by server"> + <doc> + An access ticket granted by the server for a certain set of access rights + within a specific realm. Access tickets are valid within the channel where + they were created, and expire when the channel closes. + </doc> + <assert check = "ne" value = "0" /> + </domain> + + <domain name = "class-id" type = "short" /> + + <domain name = "consumer-tag" type = "shortstr" label = "consumer tag"> + <doc> + Identifier for the consumer, valid within the current connection. + </doc> + </domain> + + <domain name = "delivery-tag" type = "longlong" label = "server-assigned delivery tag"> + <doc> + The server-assigned and channel-specific delivery tag + </doc> + <rule name = "channel-local"> + <doc> + The delivery tag is valid only within the channel from which the message was + received. I.e. a client MUST NOT receive a message on one channel and then + acknowledge it on another. + </doc> + </rule> + <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> + </domain> + + <domain name = "exchange-name" type = "shortstr" label = "exchange name"> + <doc> + The exchange name is a client-selected string that identifies the exchange for publish + methods. Exchange names may consist of any mixture of digits, letters, and underscores. + Exchange names are scoped by the virtual host. + </doc> + <assert check = "length" value = "127" /> + </domain> + + <domain name = "known-hosts" type = "shortstr" label = "list of known hosts"> + <doc> + Specifies the list of equivalent or alternative hosts that the server knows about, + which will normally include the current server itself. Clients can cache this + information and use it when reconnecting to a server after a failure. This field + may be empty. + </doc> + </domain> + + <domain name = "method-id" type = "short" /> + + <domain 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> + </domain> + + <domain name = "no-local" type = "bit" label = "do not deliver own messages"> + <doc> + If the no-local field is set the server will not send messages to the connection that + published them. + </doc> + </domain> + + <domain name = "path" type = "shortstr"> + <doc> + Must start with a slash "/" and continue with path names separated by slashes. A path + name consists of any combination of at least one of [A-Za-z0-9] plus zero or more of + [.-_+!=:]. + </doc> + + <assert check = "notnull" /> + <assert check = "syntax" rule = "path" /> + <assert check = "length" value = "127" /> + </domain> + + <domain name = "peer-properties" type = "table"> + <doc> + This string provides a set of peer properties, used for identification, debugging, and + general information. + </doc> + </domain> + + <domain name = "queue-name" type = "shortstr" label = "queue name"> + <doc> + The queue name identifies the queue within the vhost. Queue names may consist of any + mixture of digits, letters, and underscores. + </doc> + <assert check = "length" value = "127" /> + </domain> + + <domain name = "redelivered" type = "bit" label = "message is being redelivered"> + <doc> + This indicates that the message has been previously delivered to this or + another client. + </doc> + <rule name = "implementation"> + <doc> + The server SHOULD try to signal redelivered messages when it can. When + redelivering a message that was not successfully acknowledged, 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. Consume the + message using explicit acknowledgements, but do not acknowledge the + message. Close the connection, reconnect, and consume from the queue + again. The message should arrive with the redelivered flag set. + </doc> + </rule> + <rule name = "hinting"> + <doc> + The client MUST NOT rely on the redelivered field but should take it as a + hint that the message may already have been processed. A fully robust + client must be able to track duplicate received messages on non-transacted, + and locally-transacted channels. + </doc> + </rule> + </domain> + + <domain name = "reply-code" type = "short" label = "reply code from server"> + <doc> + The reply code. The AMQ reply codes are defined as constants at the start + of this formal specification. + </doc> + <assert check = "notnull" /> + </domain> + + <domain name = "reply-text" type = "shortstr" label = "localised reply text"> + <doc> + The localised reply text. This text can be logged as an aid to resolving + issues. + </doc> + <assert check = "notnull" /> + </domain> + + <domain name = "channel-id" type = "longstr" label = "unique identifier for a channel" /> + + <!-- Domains for the message class --> + <domain name = "duration" type = "longlong" label = "duration in milliseconds" /> + <domain name = "offset" type = "longlong" label = "offset into a message body" /> + <domain name = "reference" type = "longstr" label = "pointer to a message body" /> + <domain name = "destination" type = "shortstr" label = "destination for a message"> + <doc> + Specifies the destination to which the message is to be + transferred. The destination can be empty, meaning the + default exchange or consumer. + </doc> + </domain> + <domain name = "reject-code" type = "short" label = "reject code for transfer"> + <rule name = "01"> + <doc> + The reject code must be one of 0 (generic) or 1 (immediate + delivery was attempted but failed). + </doc> + </rule> + </domain> + <domain name = "reject-text" type = "shortstr" label = "informational text for message reject"/> + <domain name = "security-token" type = "longstr" label = "security token"> + <doc> + Used for authentication, replay prevention, and encrypted bodies. + </doc> + </domain> + + <!-- Elementary domains --> + <domain name = "bit" type = "bit" label = "single bit" /> + <domain name = "octet" type = "octet" label = "single octet" /> + <domain name = "short" type = "short" label = "16-bit integer" /> + <domain name = "long" type = "long" label = "32-bit integer" /> + <domain name = "longlong" type = "longlong" label = "64-bit integer" /> + <domain name = "shortstr" type = "shortstr" label = "short string" /> + <domain name = "longstr" type = "longstr" label = "long string" /> + <domain name = "timestamp" type = "timestamp" label = "64-bit timestamp" /> + <domain name = "table" type = "table" label = "field table" /> + + <!-- == CONNECTION ======================================================= --> + + <!-- TODO 0.81 - the 'handler' attribute of methods needs to be reviewed, and if + no current implementations use it, removed. /PH 2006/07/20 + --> + + <class name = "connection" handler = "connection" index = "10" label = "work with socket connections"> + <doc> + The connection class provides methods 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> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "start" synchronous = "1" index = "10" label = "start connection negotiation"> + <doc> + This method starts the connection negotiation process by telling the client the + protocol version that the server proposes, along with a list of security mechanisms + which the client can use for authentication. + </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 method. + </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 = "server-support"> + <doc> + The server MUST provide a protocol version that is lower than or equal to + that requested by the client in the protocol header. + </doc> + <doc type = "scenario"> + The client requests a protocol version that is higher than any valid + implementation, e.g. 9.0. The server must respond with a current + protocol version, e.g. 1.0. + </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> + + <chassis name = "client" implement = "MUST" /> + <response name = "start-ok" /> + + <field name = "version-major" domain = "octet" label = "protocol major version"> + <doc> + The protocol version, major component, as transmitted in the AMQP protocol + header. This, combined with the protocol minor component fully describe the + protocol version, which is written in the format major-minor. Hence, with + major=1, minor=3, the protocol version would be "1-3". + </doc> + </field> + + <field name = "version-minor" domain = "octet" label = "protocol minor version"> + <doc> + The protocol version, minor component, as transmitted in the AMQP protocol + header. This, combined with the protocol major component fully describe the + protocol version, which is written in the format major-minor. Hence, with + major=1, minor=3, the protocol version would be "1-3". + </doc> + </field> + + <field name = "server-properties" domain = "peer-properties" 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" domain = "longstr" label = "available security mechanisms"> + <doc> + A list of the security mechanisms that the server supports, delimited by spaces. + </doc> + <assert check = "notnull" /> + </field> + + <field name = "locales" domain = "longstr" label = "available message locales"> + <doc> + A list of the message locales that the server supports, delimited by spaces. 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> + <assert check = "notnull" /> + </field> + </method> + + <method name = "start-ok" synchronous = "1" index = "11" + label = "select security mechanism and locale"> + <doc> + This method selects a SASL security mechanism. + </doc> + + <chassis name = "server" implement = "MUST" /> + + <field name = "client-properties" domain = "peer-properties" 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" domain = "shortstr" label = "selected security mechanism"> + <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 method, 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> + <assert check = "notnull" /> + </field> + + <field name = "response" domain = "longstr" label = "security response data"> + <doc> + A block of opaque data passed to the security mechanism. The contents of this + data are defined by the SASL security mechanism. + </doc> + <assert check = "notnull" /> + </field> + + <field name = "locale" domain = "shortstr" label = "selected message locale"> + <doc> + A single message locale selected by the client, which must be one of those + specified by the server. + </doc> + <assert check = "notnull" /> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "secure" synchronous = "1" index = "20" 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 method challenges + the client to provide more information. + </doc> + + <chassis name = "client" implement = "MUST" /> + <response name = "secure-ok" /> + + <field name = "challenge" domain = "longstr" label = "security challenge data"> + <doc> + Challenge information, a block of opaque binary data passed to the security + mechanism. + </doc> + </field> + </method> + + <method name = "secure-ok" synchronous = "1" index = "21" label = "security mechanism response"> + <doc> + This method attempts to authenticate, passing a block of SASL data for the security + mechanism at the server side. + </doc> + + <chassis name = "server" implement = "MUST" /> + + <field name = "response" domain = "longstr" label = "security response data"> + <doc> + A block of opaque data passed to the security mechanism. The contents of this + data are defined by the SASL security mechanism. + </doc> + <assert check = "notnull" /> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "tune" synchronous = "1" index = "30" + label = "propose connection tuning parameters"> + <doc> + This method proposes a set of connection configuration values to the client. The + client can accept and/or adjust these. + </doc> + + <chassis name = "client" implement = "MUST" /> + + <response name = "tune-ok" /> + + <field name = "channel-max" domain = "short" label = "proposed maximum channels"> + <doc> + The maximum total number of channels that the server allows per connection. Zero + 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 = "frame-max" domain = "long" label = "proposed maximum frame size"> + <doc> + The largest frame size that the server proposes for the connection. The client + can negotiate a lower value. Zero 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 frame-max has been negotiated, both peers MUST accept frames of up + to frame-min-size octets large, and the minimum negotiated value for frame-max + is also frame-min-size. + </doc> + <doc type = "scenario"> + Client connects to server and sends a large properties field, creating a frame + of frame-min-size octets. The server must accept this frame. + </doc> + </rule> + </field> + + <field name = "heartbeat" domain = "short" label = "desired heartbeat delay"> + <!-- TODO 0.82 - the heartbeat negotiation mechanism was changed during + implementation because the model documented here does not actually + work properly. The best model we found is that the server proposes + a heartbeat value to the client; the client can reply with zero, meaning + 'do not use heartbeats (as documented here), or can propose its own + heartbeat value, which the server should then accept. This is different + from the model here which is disconnected - e.g. each side requests a + heartbeat independently. Basically a connection is heartbeated in + both ways, or not at all, depending on whether both peers support + heartbeating or not, and the heartbeat value should itself be chosen + by the client so that remote links can get a higher value. Also, the + actual heartbeat mechanism needs documentation, and is as follows: so + long as there is activity on a connection - in or out - both peers + assume the connection is active. When there is no activity, each peer + must send heartbeat frames. When no heartbeat frame is received after + N cycles (where N is at least 2), the connection can be considered to + have died. /PH 2006/07/19 + --> + <doc> + The delay, in seconds, of the connection heartbeat that the server wants. + Zero means the server does not want a heartbeat. + </doc> + </field> + </method> + + <method name = "tune-ok" synchronous = "1" index = "31" + label = "negotiate connection tuning parameters"> + <doc> + This method sends the client's connection tuning parameters to the server. + Certain fields are negotiated, others provide capability information. + </doc> + + <chassis name = "server" implement = "MUST" /> + + <field name = "channel-max" domain = "short" label = "negotiated maximum channels"> + <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 + implementors. + </doc> + </rule> + <assert check = "notnull" /> + <assert check = "le" method = "tune" field = "channel-max" /> + </field> + + <field name = "frame-max" domain = "long" label = "negotiated maximum frame size"> + <doc> + The largest frame size that the client and server will use for the connection. + Zero 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 + frame-max limit applies principally to content frames, where large contents can + be broken into frames of arbitrary size. + </doc> + <rule name = "minimum"> + <doc> + Until the frame-max has been negotiated, both peers MUST accept frames of up + to frame-min-size octets large, and the minimum negotiated value for frame-max + is also frame-min-size. + </doc> + </rule> + <rule name = "upper-limit"> + <doc> + If the client specifies a frame 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 + implementors. + </doc> + </rule> + </field> + + <field name = "heartbeat" domain = "short" label = "desired heartbeat delay"> + <doc> + The delay, in seconds, of the connection heartbeat that the client wants. Zero + means the client does not want a heartbeat. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "open" synchronous = "1" index = "40" label = "open connection to virtual host"> + <doc> + This method 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> + + <chassis name = "server" implement = "MUST" /> + <response name = "open-ok" /> + <response name = "redirect" /> + + <field name = "virtual-host" domain = "path" label = "virtual host name"> + <!-- TODO 0.82 - the entire vhost model needs review. This concept was + prompted by the HTTP vhost concept but does not fit very well into + AMQP. Currently we use the vhost as a "cluster identifier" which is + inaccurate usage. /PH 2006/07/19 + --> + <assert check = "regexp" value = "^[a-zA-Z0-9/-_]+$" /> + <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" domain = "shortstr" label = "required capabilities"> + <doc> + The client can specify zero or more capability names, delimited by spaces. + The server can use this string to how to process the client's connection + request. + </doc> + </field> + + <field name = "insist" domain = "bit" label = "insist on connecting to server"> + <doc> + In a configuration with multiple collaborating servers, the server may respond + to a Connection.Open method 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 = "behaviour"> + <doc> + When the client uses the insist option, the server MUST NOT respond with a + Connection.Redirect method. If it cannot accept the client's connection + request it should respond by closing the connection with a suitable reply + code. + </doc> + </rule> + </field> + </method> + + <method name = "open-ok" synchronous = "1" index = "41" label = "signal that connection is ready"> + <doc> + This method signals to the client that the connection is ready for use. + </doc> + <chassis name = "client" implement = "MUST" /> + <field name = "known-hosts" domain = "known-hosts" /> + </method> + + <method name = "redirect" synchronous = "1" index = "42" label = "redirects client to other server"> + <doc> + This method 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 method, 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> + <chassis name = "client" implement = "MUST" /> + <field name = "host" domain = "shortstr" label = "server to connect to"> + <doc> + Specifies the server to connect to. This is an IP address or a DNS name, + optionally followed by a colon and a port number. If no port number is + specified, the client should use the default port number for the protocol. + </doc> + <assert check = "notnull" /> + </field> + <field name = "known-hosts" domain = "known-hosts" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "close" synchronous = "1" index = "50" label = "request a connection close"> + <doc> + This method indicates that the sender wants to close the connection. This may be + due to internal conditions (e.g. a forced shut-down) or due to an error handling + a specific method, i.e. an exception. When a close is due to an exception, the + sender provides the class and method id of the method which caused the exception. + </doc> + <!-- TODO: the connection close mechanism needs to be reviewed from the ODF + documentation and better expressed as rules here. /PH 2006/07/20 + --> + <rule name = "stability"> + <doc> + After sending this method any received method except the Close-OK method MUST + be discarded. + </doc> + </rule> + + <chassis name = "client" implement = "MUST" /> + <chassis name = "server" implement = "MUST" /> + <response name = "close-ok" /> + + <field name = "reply-code" domain = "reply-code" /> + <field name = "reply-text" domain = "reply-text" /> + + <field name = "class-id" domain = "class-id" label = "failing method class"> + <doc> + When the close is provoked by a method exception, this is the class of the + method. + </doc> + </field> + + <field name = "method-id" domain = "method-id" label = "failing method ID"> + <doc> + When the close is provoked by a method exception, this is the ID of the method. + </doc> + </field> + </method> + + <method name = "close-ok" synchronous = "1" index = "51" label = "confirm a connection close"> + <doc> + This method confirms a Connection.Close method 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 method SHOULD log the error. + </doc> + </rule> + <chassis name = "client" implement = "MUST" /> + <chassis name = "server" implement = "MUST" /> + </method> + </class> + + <!-- == CHANNEL ========================================================== --> + + <class name = "channel" handler = "channel" index = "20" label = "work with channels"> + <doc> + The channel class provides methods for a client to establish a channel to a + server and for both peers to operate the channel thereafter. + </doc> + + <doc type = "grammar"> + channel = open-channel *use-channel close-channel + open-channel = C:OPEN S:OPEN-OK + / C:RESUME S:OK + use-channel = C:FLOW S:FLOW-OK + / S:FLOW C:FLOW-OK + / S:PING C:OK + / C:PONG S:OK + / C:PING S:OK + / S:PONG C:OK + / functional-class + close-channel = C:CLOSE S:CLOSE-OK + / S:CLOSE C:CLOSE-OK + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "open" synchronous = "1" index = "10" label = "open a channel for use"> + <doc> + This method opens a channel to the server. + </doc> + <rule name = "state" on-failure = "channel-error"> + <doc> + The client MUST NOT use this method on an already-opened channel. + </doc> + <doc type = "scenario"> + Client opens a channel and then reopens the same channel. + </doc> + </rule> + <chassis name = "server" implement = "MUST" /> + <response name = "open-ok" /> + <field name = "out-of-band" domain = "shortstr" label = "out-of-band settings"> + <doc> + Configures out-of-band transfers on this channel. The syntax and meaning of this + field will be formally defined at a later date. + </doc> + <assert check = "null" /> + </field> + </method> + + <method name = "open-ok" synchronous = "1" index = "11" label = "signal that the channel is ready"> + <doc> + This method signals to the client that the channel is ready for use. + </doc> + <chassis name = "client" implement = "MUST" /> + <field name = "channel-id" domain = "channel-id" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "flow" synchronous = "1" index = "20" label = "enable/disable flow from peer"> + <doc> + This method asks the peer to pause or restart the flow of content data. This is a + simple flow-control mechanism that a peer can use to avoid overflowing its queues or + otherwise finding itself receiving more messages than it can process. Note that this + method is not intended for window control. The peer that receives a disable flow + method should finish sending the current content frame, if any, then pause. + </doc> + + <rule name = "initial-state"> + <doc> + When a new channel is opened, it is active (flow is active). Some applications + assume that channels are inactive until started. To emulate this behaviour a + client MAY open the channel, then pause it. + </doc> + </rule> + + <rule name = "bidirectional"> + <doc> + When sending content frames, a peer SHOULD monitor the channel for incoming + methods and respond to a Channel.Flow as rapidly as possible. + </doc> + </rule> + + <rule name = "throttling"> + <doc> + A peer MAY use the Channel.Flow method to throttle incoming content data for + internal reasons, for example, when exchanging data over a slower connection. + </doc> + </rule> + + <rule name = "expected-behaviour"> + <doc> + The peer that requests a Channel.Flow method MAY disconnect and/or ban a peer + that does not respect the request. This is to prevent badly-behaved clients + from overwhelming a broker. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <response name = "flow-ok" /> + + <field name = "active" domain = "bit" label = "start/stop content frames"> + <doc> + If 1, the peer starts sending content frames. If 0, the peer stops sending + content frames. + </doc> + </field> + </method> + + <method name = "flow-ok" index = "21" label = "confirm a flow method"> + <doc> + Confirms to the peer that a flow command was received and processed. + </doc> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + <field name = "active" domain = "bit" label = "current flow setting"> + <doc> + Confirms the setting of the processed flow method: 1 means the peer will start + sending or continue to send content frames; 0 means it will not. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "close" synchronous = "1" index = "40" label = "request a channel close"> + <doc> + This method indicates that the sender wants to close the channel. This may be due to + internal conditions (e.g. a forced shut-down) or due to an error handling a specific + method, i.e. an exception. When a close is due to an exception, the sender provides + the class and method id of the method which caused the exception. + </doc> + + <!-- TODO: the channel close behaviour needs to be reviewed from the ODF + documentation and better expressed as rules here. /PH 2006/07/20 + --> + <rule name = "stability"> + <doc> + After sending this method any received method except the Close-OK method MUST + be discarded. + </doc> + </rule> + + <chassis name = "client" implement = "MUST" /> + <chassis name = "server" implement = "MUST" /> + <response name = "close-ok" /> + + <field name = "reply-code" domain = "reply-code" /> + <field name = "reply-text" domain = "reply-text" /> + + <field name = "class-id" domain = "class-id" label = "failing method class"> + <doc> + When the close is provoked by a method exception, this is the class of the + method. + </doc> + </field> + + <field name = "method-id" domain = "method-id" label = "failing method ID"> + <doc> + When the close is provoked by a method exception, this is the ID of the method. + </doc> + </field> + </method> + + <method name = "close-ok" synchronous = "1" index = "41" label = "confirm a channel close"> + <doc> + This method confirms a Channel.Close method and tells the recipient that it is safe + to release resources for the channel. + </doc> + <rule name = "reporting"> + <doc> + A peer that detects a socket closure without having received a Channel.Close-Ok + handshake method SHOULD log the error. + </doc> + </rule> + <chassis name = "client" implement = "MUST" /> + <chassis name = "server" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "resume" index = "50" label = "resume an interrupted channel"> + <doc> + This method resume a previously interrupted channel. + </doc> + <response name = "ok" /> + <chassis name = "server" implement = "MAY" /> + <field name = "channel-id" domain = "channel-id" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "ping" index = "60" label = "[WORK IN PROGRESS] initiates a pong"> + <doc> + [WORK IN PROGRESS] Request that the recipient issue a pong request. + </doc> + <response name = "ok" /> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + </method> + + <method name = "pong" index = "70" label = "[WORK IN PROGRESS] issued after receiving a ping"> + <doc> + [WORK IN PROGRESS] Issued after a ping request is received. Note that this is a + request issued after receiving a ping, not a response to + receiving a ping. + </doc> + <response name = "ok" /> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + </method> + + <method name = "ok" index = "80" label = "[WORK IN PROGRESS] signals normal completion"> + <doc> + [WORK IN PROGRESS] Signals normal completion of a method. + </doc> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + </method> + </class> + + <!-- == ACCESS =========================================================== --> + + <!-- TODO 0.82 - this class must be implemented by two teams before we can + consider it matured. + --> + + <class name = "access" handler = "connection" index = "30" label = "work with access tickets"> + <doc> + The protocol control access to server resources using access tickets. A + client must explicitly request access tickets before doing work. An access + ticket grants a client the right to use a specific set of resources - + called a "realm" - in specific ways. + </doc> + + <doc type = "grammar"> + access = C:REQUEST S:REQUEST-OK + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "request" synchronous = "1" index = "10" label = "request an access ticket"> + <doc> + This method requests an access ticket for an access realm. The server + responds by granting the access ticket. If the client does not have + access rights to the requested realm this causes a connection exception. + Access tickets are a per-channel resource. + </doc> + + <chassis name = "server" implement = "MUST" /> + <response name = "request-ok" /> + + <field name = "realm" domain = "shortstr" label = "name of requested realm"> + <doc> + Specifies the name of the realm to which the client is requesting access. + The realm is a configured server-side object that collects a set of + resources (exchanges, queues, etc.). If the channel has already requested + an access ticket onto this realm, the previous ticket is destroyed and a + new ticket is created with the requested access rights, if allowed. + </doc> + <rule name = "validity" on-failure = "access-refused"> + <doc> + The client MUST specify a realm that is known to the server. The server + makes an identical response for undefined realms as it does for realms + that are defined but inaccessible to this client. + </doc> + <doc type = "scenario"> + Client specifies an undefined realm. + </doc> + </rule> + </field> + + <field name = "exclusive" domain = "bit" label = "request exclusive access"> + <doc> + Request exclusive access to the realm, meaning that this will be the only + channel that uses the realm's resources. + </doc> + <rule name = "validity" on-failure = "access-refused"> + <doc> + The client MAY NOT request exclusive access to a realm that has active + access tickets, unless the same channel already had the only access + ticket onto that realm. + </doc> + <doc type = "scenario"> + Client opens two channels and requests exclusive access to the same realm. + </doc> + </rule> + </field> + <field name = "passive" domain = "bit" label = "request passive access"> + <doc> + Request message passive access to the specified access realm. Passive + access lets a client get information about resources in the realm but + not to make any changes to them. + </doc> + </field> + <field name = "active" domain = "bit" label = "request active access"> + <doc> + Request message active access to the specified access realm. Active access lets + a client get create and delete resources in the realm. + </doc> + </field> + <field name = "write" domain = "bit" label = "request write access"> + <doc> + Request write access to the specified access realm. Write access lets a client + publish messages to all exchanges in the realm. + </doc> + </field> + <field name = "read" domain = "bit" label = "request read access"> + <doc> + Request read access to the specified access realm. Read access lets a client + consume messages from queues in the realm. + </doc> + </field> + </method> + + <method name = "request-ok" synchronous = "1" index = "11" label = "grant access to server resources"> + <doc> + This method provides the client with an access ticket. The access ticket is valid + within the current channel and for the lifespan of the channel. + </doc> + <rule name = "per-channel" on-failure = "not-allowed"> + <doc> + The client MUST NOT use access tickets except within the same channel as + originally granted. + </doc> + <doc type = "scenario"> + Client opens two channels, requests a ticket on one channel, and then + tries to use that ticket in a second channel. + </doc> + </rule> + <chassis name = "client" implement = "MUST" /> + <field name = "ticket" domain = "access-ticket" /> + </method> + </class> + + <!-- == EXCHANGE ========================================================= --> + + <class name = "exchange" handler = "channel" index = "40" 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 S:DECLARE-OK + / C:DELETE S:DELETE-OK + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <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. + </doc> + <doc> + 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 methods. + </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 methods and for default queue bindings. + </doc> + <doc type = "scenario"> + Client checks that the default exchange is active by specifying a queue + binding with no exchange name, and 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 server MUST NOT allow clients to access the default exchange except + by specifying an empty exchange name in the Queue.Bind and content Publish + methods. + </doc> + </rule> + <rule name = "extensions"> + <doc> + The server MAY implement other exchange types as wanted. + </doc> + </rule> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "declare" synchronous = "1" index = "10" label = "verify exchange exists, create if needed"> + <doc> + This method 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> + + <chassis name = "server" implement = "MUST" /> + <response name = "declare-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <doc> + When a client defines a new exchange, this belongs to the access realm of the + ticket used. All further work done with that exchange must be done with an + access ticket for the same realm. + </doc> + <rule name = "validity" on-failure = "access-refused"> + <doc> + The client MUST provide a valid access ticket giving "active" access to + the realm in which the exchange exists or will be created, or "passive" + access if the if-exists flag is set. + </doc> + <doc type = "scenario"> + Client creates access ticket with wrong access rights and attempts to use + in this method. + </doc> + </rule> + </field> + + <field name = "exchange" domain = "exchange-name"> + <rule name = "reserved" on-failure = "access-refused"> + <doc> + Exchange names starting with "amq." are reserved for pre-declared and + standardised exchanges. The client MUST NOT attempt to create an exchange + starting with "amq.". + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]+$" /> + </field> + + <field name = "type" domain = "shortstr" label = "exchange type"> + <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> + <rule name = "typed" on-failure = "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 method. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + <rule name = "support" on-failure = "command-invalid"> + <doc> + The client MUST NOT attempt to create an exchange with a type that the + server does not support. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]+$" /> + </field> + + <field name = "passive" domain = "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> + <rule name = "not-found"> + <doc> + If set, and the exchange does not already exist, the server MUST raise a + channel exception with reply code 404 (not found). + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + + <field name = "durable" domain = "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> + <doc type = "scenario"> + TODO. + </doc> + </rule> + <rule name = "sticky"> + <doc> + The server MUST ignore the durable field if the exchange already exists. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + + <!-- TODO 0.82 - clarify how this works; there is no way to cancel a binding + except by deleting a queue. + --> + <field name = "auto-delete" domain = "bit" label = "auto-delete when unused"> + <doc> + If set, the exchange is deleted when all queues have finished using it. + </doc> + <rule name = "sticky"> + <doc> + The server MUST ignore the auto-delete field if the exchange already + exists. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + + <field name = "internal" domain = "bit" label = "create internal exchange"> + <doc> + If set, the exchange may not be used directly by publishers, but only when bound + to other exchanges. Internal exchanges are used to construct wiring that is not + visible to applications. + </doc> + </field> + + <field name = "nowait" domain = "bit" label = "do not send reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + + <field name = "arguments" domain = "table" 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> + </field> + </method> + + <method name = "declare-ok" synchronous = "1" index = "11" label = "confirm exchange declaration"> + <doc> + This method confirms a Declare method and confirms the name of the exchange, + essential for automatically-named exchanges. + </doc> + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "delete" synchronous = "1" index = "20" label = "delete an exchange"> + <doc> + This method deletes an exchange. When an exchange is deleted all queue bindings on + the exchange are cancelled. + </doc> + + <chassis name = "server" implement = "MUST" /> + <response name = "delete-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "validity" on-failure = "access-refused"> + <doc> + The client MUST provide a valid access ticket giving "active" access + rights to the exchange's access realm. + </doc> + <doc type = "scenario"> + Client creates access ticket with wrong access rights and attempts to use + in this method. + </doc> + </rule> + </field> + + <field name = "exchange" domain = "exchange-name"> + <rule name = "exists" on-failure = "not-found"> + <doc> + The client MUST NOT attempt to delete an exchange that does not exist. + </doc> + </rule> + <assert check = "notnull" /> + </field> + + <!-- TODO 0.82 - discuss whether this option is useful or not. I don't have + any real use case for it. /PH 2006-07-23. + --> + <field name = "if-unused" domain = "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 a + channel exception instead. + </doc> + </field> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + </method> + + <method name = "delete-ok" synchronous = "1" index = "21" + label = "confirm deletion of an exchange"> + <doc>This method confirms the deletion of an exchange.</doc> + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- RG : Added Exchange.bound and Exchange.bound-ok --> + <method name="bound" synchronous="1" index="22"> + <chassis name="server" implement="SHOULD"/> + <response name="bound-ok"/> + <field name="exchange" domain="exchange-name"/> + <field name = "routing-key" type = "shortstr"> + 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 = "queue" domain = "queue name"/> + </method> + + <method name="bound-ok" synchronous="1" index="23"> + <field name="reply-code" domain="reply-code"/> + <field name="reply-text" domain="reply-text"/> + <chassis name="client" implement="SHOULD"/> + </method> + + </class> + + <!-- == QUEUE ============================================================ --> + + <class name = "queue" handler = "channel" index = "50" 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 S:DECLARE-OK + / C:BIND S:BIND-OK + / C:PURGE S:PURGE-OK + / C:DELETE S:DELETE-OK + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <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 methods + 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> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "declare" synchronous = "1" index = "10" label = "declare queue, create if needed"> + <doc> + This method 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 routing 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 routing + key. + </doc> + </rule> + + <!-- Rule test name: was "amq_queue_35" --> + <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> + + <chassis name = "server" implement = "MUST" /> + <response name = "declare-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <doc> + When a client defines a new queue, this belongs to the access realm of the + ticket used. All further work done with that queue must be done with an access + ticket for the same realm. + </doc> + <rule name = "validity" on-failure = "access-refused"> + <doc> + The client MUST provide a valid access ticket giving "active" access to + the realm in which the queue exists or will be created. + </doc> + <doc type = "scenario"> + Client creates access ticket with wrong access rights and attempts to use + in this method. + </doc> + </rule> + </field> + + <field name = "queue" domain = "queue-name"> + <rule name = "default-name"> + <doc> + The queue name MAY be empty, in which case the server MUST create a new + queue with a unique generated name and return this to the client in the + Declare-Ok method. + </doc> + <doc type = "scenario"> + Client attempts to create several queues with an empty name. The client then + verifies that the server-assigned names are unique and different. + </doc> + </rule> + <rule name = "reserved-prefix" on-failure = "not-allowed"> + <doc> + Queue names starting with "amq." are reserved for pre-declared and + standardised server queues. A client MAY 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> + </rule> + <assert check = "regexp" value = "^[a-zA-Z0-9-_.:]*$" /> + </field> + + <field name = "passive" domain = "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> + <rule name = "passive" on-failure = "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 server to respond with a declare-ok. Client then attempts to declare + a non-existent queue with the passive option, and the server must close + the channel with the correct reply-code. + </doc> + </rule> + </field> + + <field name = "durable" domain = "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 test name: was "amq_queue_03" --> + <rule name = "persistence"> + <doc>The server MUST recreate the durable queue after a restart.</doc> + + <!-- TODO: use 'client does something' rather than 'a client does something'. --> + <doc type = "scenario"> + A client creates a durable queue. The server is then restarted. The client + then attempts to send a message to the queue. The message should be successfully + delivered. + </doc> + </rule> + <!-- Rule test name: was "amq_queue_36" --> + <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 test name: was "amq_queue_37" --> + <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. + <!-- TODO: but how? --> + </doc> + </rule> + </field> + + <field name = "exclusive" domain = "bit" label = "request an exclusive queue"> + <doc> + Exclusive queues may only be consumed from by the current connection. Setting + the 'exclusive' flag always implies 'auto-delete'. + </doc> + + <!-- Rule test name: was "amq_queue_38" --> + <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> + + <!-- Rule test name: was "amq_queue_04" --> + <rule name = "02" on-failure = "channel-error"> + <doc> + The client MAY NOT attempt to declare any existing and exclusive queue + on multiple connections. + </doc> + <doc type = "scenario"> + A client declares an exclusive named queue. A second client on a different + connection attempts to declare a queue of the same name. + </doc> + </rule> + </field> + + <field name = "auto-delete" domain = "bit" label = "auto-delete queue when unused"> + <doc> + If set, the queue is deleted when all consumers have finished using it. Last + consumer can be cancelled either explicitly or because its channel is closed. If + there was no consumer ever on the queue, it won't be deleted. + </doc> + + <!-- Rule test name: was "amq_queue_31" --> + <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. + <!-- TODO: but how? --> + </doc> + </rule> + </field> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + + <field name = "arguments" domain = "table" 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> + </field> + </method> + + <method name = "declare-ok" synchronous = "1" index = "11" label = "confirms a queue definition"> + <doc> + This method confirms a Declare method and confirms the name of the queue, essential + for automatically-named queues. + </doc> + + <chassis name = "client" implement = "MUST" /> + + <field name = "queue" domain = "queue-name"> + <doc> + Reports the name of the queue. If the server generated a queue name, this field + contains that name. + </doc> + <assert check = "notnull" /> + </field> + + <field name = "message-count" domain = "long" label = "number of messages in queue"> + <doc> + Reports the number of messages in the queue, which will be zero for + newly-created queues. + </doc> + </field> + + <field name = "consumer-count" domain = "long" label = "number of consumers"> + <doc> + Reports the number of active consumers for the queue. Note that consumers can + suspend activity (Channel.Flow) in which case they do not appear in this count. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "bind" synchronous = "1" index = "20" label = "bind queue to an exchange"> + <doc> + This method 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 test name: was "amq_queue_25" --> + <rule name = "duplicates"> + <doc> + A server MUST allow ignore duplicate bindings - that is, two or more bind + methods for a specific queue, with identical arguments - without treating these + as an error. + </doc> + <doc type = "scenario"> + A client binds a named queue to an exchange. The client then repeats the bind + (with identical arguments). + </doc> + </rule> + + <!-- Rule test name: was "amq_queue_39" --> + <rule name = "failure"> + <!-- + TODO: Find correct on-failure code. The on-failure code returned should depend on why the bind + failed. Assuming that failures owing to bad parameters are covered in the rules relating + to those parameters, the only remaining reason for a failure would be the lack of + server resorces or some internal error - such as too many queues open. Would these + cases qualify as "resource error" 506 or "internal error" 541? + --> + <doc>If a bind fails, the server MUST raise a connection exception.</doc> + <doc type = "scenario"> + TODO + </doc> + </rule> + + <!-- Rule test name: was "amq_queue_12" --> + <rule name = "transient-exchange" on-failure = "not-allowed"> + <doc> + The server MUST NOT allow a durable queue to bind to a transient exchange. + </doc> + <doc type = "scenario"> + A client creates a transient exchange. The client then declares a named durable + queue and then attempts to bind the transient exchange to the durable queue. + </doc> + </rule> + + <!-- Rule test name: was "amq_queue_13" --> + <rule name = "durable-exchange"> + <doc> + Bindings for durable queues are automatically durable and the server SHOULD + 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 test name: was "amq_queue_17" --> + <rule name = "internal-exchange"> + <doc> + If the client attempts to bind to an exchange that was declared as internal, the server + MUST raise a connection exception with reply code 530 (not allowed). + </doc> + <doc type = "scenario"> + A client attempts to bind a named queue to an internal exchange. + </doc> + </rule> + + <!-- Rule test name: was "amq_queue_40" --> + <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 non-internal + exchanges. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + + <response name = "bind-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <doc> + The client provides a valid access ticket giving "active" access rights to the + queue's access realm. + </doc> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to bind. If the queue name is empty, refers to + the current queue for the channel, which is the last declared queue. + </doc> + + <rule name = "empty-queue" on-failure = "not-allowed"> + <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> + </rule> + + <!-- Rule test name: was "amq_queue_26" --> + <rule name = "queue-existence" on-failure = "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> + </rule> + </field> + + <field name = "exchange" domain = "exchange-name" label = "name of the exchange to bind to"> + <!-- Rule test name: was "amq_queue_14" --> + <rule name = "exchange-existence" on-failure = "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 an named queue to a undeclared exchange. + </doc> + </rule> + </field> + + <field name = "routing-key" domain = "shortstr" label = "message routing key"> + <doc> + Specifies the routing key for the binding. The routing key is used for routing + messages depending on the exchange configuration. Not all exchanges use a + routing key - refer to the specific exchange documentation. If the queue name + is empty, the server uses the last queue declared on the channel. If the + routing key is also empty, the server uses this queue name for the routing + key as well. If the queue name is provided but the routing key is empty, the + server does the binding with that empty routing key. The meaning of empty + routing keys depends on the exchange implementation. + </doc> + <rule name = "direct-exchange-key-matching"> + <doc> + If a message queue binds to a direct exchange using routing key K and a + publisher sends the exchange a message with routing key R, then the message + MUST be passed to the message queue if K = R. + </doc> + </rule> + </field> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + + <field name = "arguments" domain = "table" 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> + </field> + </method> + + <method name = "bind-ok" synchronous = "1" index = "21" label = "confirm bind successful"> + <doc>This method confirms that the bind was successful.</doc> + + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "unbind" synchronous = "1" index = "50" label = "unbind a queue from an exchange"> + <doc>This method unbinds a queue from an exchange.</doc> + <rule name = "01"> + <doc>If a unbind fails, the server MUST raise a connection exception.</doc> + </rule> + <chassis name="server" implement="MUST"/> + <response name="unbind-ok"/> + + <field name = "ticket" domain = "access-ticket"> + <doc> + The client provides a valid access ticket giving "active" + access rights to the queue's access realm. + </doc> + </field> + + <field name = "queue" domain = "queue-name"> + <doc>Specifies the name of the queue to unbind.</doc> + <rule name = "02"> + <doc> + If the queue does not exist the server MUST raise a channel exception + with reply code 404 (not found). + </doc> + </rule> + </field> + + <field name = "exchange" domain = "exchange-name"> + <doc>The name of the exchange to unbind from.</doc> + <rule name = "03"> + <doc> + If the exchange does not exist the server MUST raise a channel + exception with reply code 404 (not found). + </doc> + </rule> + </field> + + <field name = "routing-key" domain = "shortstr" label = "routing key of binding"> + <doc>Specifies the routing key of the binding to unbind.</doc> + </field> + + <field name = "arguments" domain = "table" label = "arguments of binding"> + <doc>Specifies the arguments of the binding to unbind.</doc> + </field> + </method> + + <method name = "unbind-ok" synchronous = "1" index = "51" label = "confirm unbind successful"> + <doc>This method confirms that the unbind was successful.</doc> + <chassis name = "client" implement = "MUST"/> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "purge" synchronous = "1" index = "30" label = "purge a queue"> + <doc> + This method removes all messages from a queue. It does not cancel consumers. Purged + messages are deleted without any formal "undo" mechanism. + </doc> + + <!-- Rule test name: was "amq_queue_15" --> + <rule name = "01"> + <doc>A call to purge MUST result in an empty queue.</doc> + </rule> + + <!-- Rule test name: was "amq_queue_41" --> + <rule name = "02"> + <doc> + On transacted channels the server MUST not purge messages that have already been + sent to a client but not yet acknowledged. + </doc> + </rule> + + <!-- TODO: Rule split? --> + + <!-- Rule test name: was "amq_queue_42" --> + <rule name = "03"> + <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> + + <chassis name = "server" implement = "MUST" /> + + <response name = "purge-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <doc>The access ticket must be for the access realm that holds the queue.</doc> + + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "read" access rights to + the queue's access realm. Note that purging a queue is equivalent to reading + all messages and discarding them. + </doc> + </rule> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to purge. If the queue name is empty, refers to + the current queue for the channel, which is the last declared queue. + </doc> + + <rule name = "01"> + <doc> + If the client did not previously declare a queue, and the queue name in this + method is empty, the server MUST raise a connection exception with reply + code 530 (not allowed). + </doc> + </rule> + + <!-- TODO Rule split? --> + + <!-- Rule test name: was "amq_queue_16" --> + <rule name = "02"> + <doc> + The queue MUST exist. Attempting to purge a non-existing queue MUST cause a + channel exception. + </doc> + </rule> + </field> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + </method> + + <method name = "purge-ok" synchronous = "1" index = "31" label = "confirms a queue purge"> + <doc>This method confirms the purge of a queue.</doc> + + <chassis name = "client" implement = "MUST" /> + + <field name = "message-count" domain = "long" label = "number of messages purged"> + <doc>Reports the number of messages purged.</doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "delete" synchronous = "1" index = "40" label = "delete a queue"> + <doc> + This method deletes a queue. When a queue is deleted any pending messages are sent + to a dead-letter queue if this is defined in the server configuration, and all + consumers on the queue are cancelled. + </doc> + + <!-- TODO: Rule split? --> + + <!-- Rule test name: was "amq_queue_43" --> + <rule name = "01"> + <doc> + The server SHOULD use a dead-letter queue to hold messages that were pending on + a deleted queue, and MAY provide facilities for a system administrator to move + these messages back to an active queue. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + + <response name = "delete-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <doc> + The client provides a valid access ticket giving "active" access rights to the + queue's access realm. + </doc> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to delete. If the queue name is empty, refers to + the current queue for the channel, which is the last declared queue. + </doc> + + <rule name = "01"> + <doc> + If the client did not previously declare a queue, and the queue name in this + method is empty, the server MUST raise a connection exception with reply + code 530 (not allowed). + </doc> + </rule> + + <!-- Rule test name: was "amq_queue_21" --> + <rule name = "02"> + <doc> + The queue must exist. If the client attempts to delete a non-existing queue + the server MUST raise a channel exception with reply code 404 (not found). + </doc> + </rule> + </field> + + <field name = "if-unused" domain = "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 a channel + exception instead. + </doc> + + <!-- Rule test name: was "amq_queue_29" and "amq_queue_30" --> + <rule name = "01"> + <doc>The server MUST respect the if-unused flag when deleting a queue.</doc> + </rule> + </field> + + <field name = "if-empty" domain = "bit" label = "delete only if empty"> + <doc> + If set, the server will only delete the queue if it has no messages. + </doc> + <rule name = "01"> + <doc> + If the queue is not empty the server MUST raise a channel exception with + reply code 406 (precondition failed). + </doc> + </rule> + </field> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + </method> + + <method name = "delete-ok" synchronous = "1" index = "41" label = "confirm deletion of a queue"> + <doc>This method confirms the deletion of a queue.</doc> + + <chassis name = "client" implement = "MUST" /> + + <field name = "message-count" domain = "long" label = "number of messages purged"> + <doc>Reports the number of messages purged.</doc> + </field> + </method> + </class> + + <!-- == BASIC ============================================================ --> + + <class name = "basic" handler = "channel" index = "60" label = "work with basic content"> + <doc> + The Basic class provides methods that support an industry-standard messaging model. + </doc> + + <doc type = "grammar"> + basic = C:QOS S:QOS-OK + / C:CONSUME S:CONSUME-OK + / C:CANCEL S:CANCEL-OK + / C:PUBLISH content + / S:RETURN content + / S:DELIVER content + / C:GET ( S:GET-OK content / S:GET-EMPTY ) + / C:ACK + / C:REJECT + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MAY" /> + + <!-- Rule test name: was "amq_basic_08" --> + <rule name = "01"> + <doc> + The server SHOULD respect the persistent property of basic messages and + SHOULD make a best-effort to hold persistent basic 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 test name: was "amq_basic_09" --> + <rule name = "02"> + <doc> + The server MUST NOT discard a persistent basic 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 = "03"> + <doc> + The server MAY use the Channel.Flow method to slow or stop a basic message + publisher when necessary. + </doc> + <doc type = "scenario"> + Create a queue overflow situation with non-persistent messages and verify + whether the server responds with Channel.Flow or not. Repeat with persistent + messages. + </doc> + </rule> + + <!-- Rule test name: was "amq_basic_10" --> + <rule name = "04"> + <doc> + The server MAY overflow non-persistent basic messages to persistent + storage. + </doc> + <!-- Test scenario: untestable --> + </rule> + + <rule name = "05"> + <doc> + The server MAY discard or dead-letter non-persistent basic messages on a + priority basis if the queue size exceeds some configured limit. + </doc> + <!-- Test scenario: untestable --> + </rule> + + <!-- Rule test name: was "amq_basic_11" --> + <rule name = "06"> + <doc> + The server MUST implement at least 2 priority levels for basic messages, + where priorities 0-4 and 5-9 are treated as two distinct levels. + </doc> + <doc type = "scenario"> + Send a number of priority 0 messages to a queue. Send one priority 9 + message. Consume messages from the queue and verify that the first message + received was priority 9. + </doc> + </rule> + + <rule name = "07"> + <doc> + The server MAY implement up to 10 priority levels. + </doc> + <doc type = "scenario"> + Send a number of messages with mixed priorities to a queue, so that all + priority values from 0 to 9 are exercised. A good scenario would be ten + messages in low-to-high priority. Consume from queue and verify how many + priority levels emerge. + </doc> + </rule> + + <!-- Rule test name: was "amq_basic_12" --> + <rule name = "08"> + <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. Consume and verify that messages arrive in same order + as originally published. + </doc> + </rule> + + <!-- Rule test name: was "amq_basic_13" --> + <rule name = "09"> + <doc> + The server MUST support automatic acknowledgements on Basic content, i.e. + consumers with the no-ack field set to FALSE. + </doc> + <doc type = "scenario"> + Create a queue and a consumer using automatic acknowledgements. Publish + a set of messages to the queue. Consume the messages and verify that all + messages are received. + </doc> + </rule> + + <rule name = "10"> + <doc> + The server MUST support explicit acknowledgements on Basic content, i.e. + consumers with the no-ack field set to TRUE. + </doc> + <doc type = "scenario"> + Create a queue and a consumer using explicit acknowledgements. Publish a + set of messages to the queue. Consume the messages but acknowledge only + half of them. Disconnect and reconnect, and consume from the queue. + Verify that the remaining messages are received. + </doc> + </rule> + + <!-- These are the properties for a Basic content --> + + <field name = "content-type" domain = "shortstr" label = "MIME content type" /> + <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> + <field name = "headers" domain = "table" label = "message header field table" /> + <field name = "delivery-mode" domain = "octet" label = "non-persistent (1) or persistent (2)" /> + <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> + <field name = "correlation-id" domain = "shortstr" label = "application correlation identifier" /> + <field name = "reply-to" domain = "shortstr" label = "destination to reply to" /> + <field name = "expiration" domain = "shortstr" label = "message expiration specification" /> + <field name = "message-id" domain = "shortstr" label = "application message identifier" /> + <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> + <field name = "type" domain = "shortstr" label = "message type name" /> + <field name = "user-id" domain = "shortstr" label = "creating user id" /> + <field name = "app-id" domain = "shortstr" label = "creating application id" /> + <!-- This field is deprecated pending review --> + <field name = "cluster-id" domain = "shortstr" label = "intra-cluster routing identifier" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> + <doc> + This method requests a specific quality of service. The QoS can be specified for the + current channel or for all channels on the connection. The particular properties and + semantics of a qos method always depend on the content class semantics. Though the + qos method could in principle apply to both peers, it is currently meaningful only + for the server. + </doc> + + <chassis name = "server" implement = "MUST" /> + <response name = "qos-ok" /> + + <field name = "prefetch-size" domain = "long" label = "prefetch 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 down the channel. Prefetching gives a performance + improvement. This field specifies the prefetch window size in octets. The server + will send a message in advance if it is equal to or smaller in size than the + available prefetch size (and also falls into other prefetch limits). May be set + to zero, meaning "no specific limit", although other prefetch limits may still + apply. The prefetch-size is ignored if the no-ack option is set. + </doc> + <!-- Rule test name: was "amq_basic_17" --> + <rule name = "01"> + <doc> + The server MUST ignore this setting when the client is not processing any + messages - i.e. the prefetch size does not limit the transfer of single + messages to a client, only the sending in advance of more messages while + the client still has one or more unacknowledged messages. + </doc> + <doc type = "scenario"> + Define a QoS prefetch-size limit and send a single message that exceeds + that limit. Verify that the message arrives correctly. + </doc> + </rule> + </field> + + <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> + <doc> + Specifies a prefetch 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 prefetch windows (and those at the channel and connection level) + allow it. The prefetch-count is ignored if the no-ack option is set. + </doc> + <!-- Rule test name: was "amq_basic_18" --> + <rule name = "01"> + <doc> + The server may send less data in advance than allowed by the client's + specified prefetch windows but it MUST NOT send more. + </doc> + <doc type = "scenario"> + Define a QoS prefetch-size limit and a prefetch-count limit greater than + one. Send multiple messages that exceed the prefetch size. Verify that + no more than one message arrives at once. + </doc> + </rule> + </field> + + <field name = "global" domain = "bit" label = "apply to entire connection"> + <doc> + By default the QoS settings apply to the current channel only. If this field is + set, they are applied to the entire connection. + </doc> + </field> + </method> + + <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> + <doc> + This method 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> + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "consume" synchronous = "1" index = "20" label = "start a queue consumer"> + <doc> + This method asks the server to start a "consumer", which is a transient request for + messages from a specific queue. Consumers last as long as the channel they were + created on, or until the client cancels them. + </doc> + + <!-- Rule test name: was "amq_basic_01" --> + <rule name = "01"> + <doc> + The server SHOULD support at least 16 consumers per queue, and ideally, impose + no limit except as defined by available resources. + </doc> + <doc type = "scenario"> + Create a queue and create consumers on that queue until the server closes the + connection. Verify that the number of consumers created was at least sixteen + and report the total number. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + <response name = "consume-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01" on-failure = "access-refused"> + <doc> + The client MUST provide a valid access ticket giving "read" access rights to + the realm for the queue. + </doc> + <doc type = "scenario"> + Attempt to create a consumer with an invalid (non-zero) access ticket. + </doc> + </rule> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to consume from. If the queue name is null, + refers to the current queue for the channel, which is the last declared queue. + </doc> + <rule name = "01" on-failure = "not-allowed"> + <doc> + If the queue name is empty the client MUST have previously declared a + queue using this channel. + </doc> + <doc type = "scenario"> + Attempt to create a consumer with an empty queue name and no previously + declared queue on the channel. + </doc> + </rule> + </field> + + <field name = "consumer-tag" domain = "consumer-tag"> + <doc> + Specifies the identifier for the consumer. The consumer tag is local to a + connection, so two clients can use the same consumer tags. If this field is + empty the server will generate a unique tag. + </doc> + <rule name = "01" on-failure = "not-allowed"> + <doc> + The client MUST NOT specify a tag that refers to an existing consumer. + </doc> + <doc type = "scenario"> + Attempt to create two consumers with the same non-empty tag. + </doc> + </rule> + <rule name = "02" on-failure = "not-allowed"> + <doc> + The consumer tag is valid only within the channel from which the + consumer was created. I.e. a client MUST NOT create a consumer in one + channel and then use it in another. + </doc> + <doc type = "scenario"> + Attempt to create a consumer in one channel, then use in another channel, + in which consumers have also been created (to test that the server uses + unique consumer tags). + </doc> + </rule> + </field> + + <field name = "no-local" domain = "no-local" /> + + <field name = "no-ack" domain = "no-ack" /> + + <field name = "exclusive" domain = "bit" label = "request exclusive access"> + <doc> + Request exclusive consumer access, meaning only this consumer can access the + queue. + </doc> + <!-- Rule test name: was "amq_basic_02" --> + <rule name = "01" on-failure = "access-refused"> + <doc> + The client MAY NOT gain exclusive access to a queue that already has + active consumers. + </doc> + <doc type = "scenario"> + Open two connections to a server, and in one connection create a shared + (non-exclusive) queue and then consume from the queue. In the second + connection attempt to consume from the same queue using the exclusive + option. + </doc> + </rule> + </field> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise + a channel or connection exception. + </doc> + </field> + + <!-- RG changed name from filter to arguments on basic.consume: this is inline with qpid0-8 and 0-10 and has no effect on the wire level encoding + <field name = "arguments" domain = "table" label = "arguments for consuming"> --> + <field name = "arguments" domain = "table" label = "arguments for consuming"> + <doc> + A set of filters for the consume. The syntax and semantics + of these filters depends on the providers implementation. + </doc> + </field> + </method> + + <method name = "consume-ok" synchronous = "1" index = "21" label = "confirm a new consumer"> + <doc> + The server provides the client with a consumer tag, which is used by the client + for methods called on the consumer at a later stage. + </doc> + <chassis name = "client" implement = "MUST" /> + <field name = "consumer-tag" domain = "consumer-tag"> + <doc> + Holds the consumer tag specified by the client or provided by the server. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "cancel" synchronous = "1" index = "30" label = "end a queue consumer"> + <doc> + This method 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. The client may receive an arbitrary number of messages in + between sending the cancel method and receiving the cancel-ok reply. + </doc> + + <rule name = "01"> + <doc> + If the queue does not exist the server MUST ignore the cancel method, so + long as the consumer tag is valid for that channel. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + <response name = "cancel-ok" /> + + <field name = "consumer-tag" domain = "consumer-tag" /> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + </method> + + <method name = "cancel-ok" synchronous = "1" index = "31" label = "confirm a cancelled consumer"> + <doc> + This method confirms that the cancellation was completed. + </doc> + <chassis name = "client" implement = "MUST" /> + <field name = "consumer-tag" domain = "consumer-tag" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "publish" content = "1" index = "40" label = "publish a message"> + <doc> + This method 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 when the transaction, if any, is committed. + </doc> + + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "write" access rights + to the access realm for the exchange. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + + <field name = "exchange" domain = "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 a channel exception. + </doc> + + <!-- Rule test name: was "amq_basic_06" --> + <rule name = "01"> + <doc> + The server MUST accept a blank exchange name to mean the default exchange. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + + <!-- Rule test name: was "amq_basic_14" --> + <rule name = "02"> + <doc> + If the exchange was declared as an internal exchange, the server MUST raise + a channel exception with a reply code 403 (access refused). + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + + <!-- Rule test name: was "amq_basic_15" --> + <rule name = "03"> + <doc> + The exchange MAY refuse basic content in which case it MUST raise a channel + exception with reply code 540 (not implemented). + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + + <field name = "routing-key" domain = "shortstr" 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" domain = "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 method. If this flag is zero, the server silently drops the message. + </doc> + <!-- Rule test name: was "amq_basic_07" --> + <rule name = "01"> + <doc> + The server SHOULD implement the mandatory flag. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + + <field name = "immediate" domain = "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 method. If this flag is zero, the server + will queue the message, but with no guarantee that it will ever be consumed. + </doc> + <!-- Rule test name: was "amq_basic_16" --> + <rule name = "01"> + <doc> + The server SHOULD implement the immediate flag. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + </method> + + <method name = "return" content = "1" index = "50" label = "return a failed message"> + <doc> + This method 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> + + <chassis name = "client" implement = "MUST" /> + + <field name = "reply-code" domain = "reply-code" /> + + <field name = "reply-text" domain = "reply-text" /> + + <field name = "exchange" domain = "exchange-name"> + <doc> + Specifies the name of the exchange that the message was originally published to. + </doc> + </field> + + <field name = "routing-key" domain = "shortstr" label = "Message routing key"> + <doc> + Specifies the routing key name specified when the message was published. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "deliver" content = "1" index = "60" + label = "notify the client of a consumer message"> + <doc> + This method delivers a message to the client, via a consumer. In the asynchronous + message delivery model, the client starts a consumer using the Consume method, then + the server responds with Deliver methods as and when messages arrive for that + consumer. + </doc> + + <!-- Rule test name: was "amq_basic_19" --> + <rule name = "01"> + <!-- TODO: Rule split? --> + <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 + unprocessable (possibly causing client applications to abort), and move the + message to a dead letter queue. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer-tag" domain = "consumer-tag" /> + + <field name = "delivery-tag" domain = "delivery-tag" /> + + <field name = "redelivered" domain = "redelivered" /> + + <field name = "exchange" domain = "exchange-name"> + <doc> + Specifies the name of the exchange that the message was originally published to. + </doc> + </field> + + <field name = "routing-key" domain = "shortstr" label = "Message routing key"> + <doc>Specifies the routing key name specified when the message was published.</doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "get" synchronous = "1" index = "70" label = "direct access to a queue"> + <doc> + This method provides a direct access to the messages in a queue using a synchronous + dialogue that is designed for specific types of application where synchronous + functionality is more important than performance. + </doc> + + <response name = "get-ok" /> + <response name = "get-empty" /> + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "read" access rights to + the realm for the queue. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to consume from. If the queue name is null, + refers to the current queue for the channel, which is the last declared queue. + </doc> + <rule name = "01"> + <doc> + If the client did not previously declare a queue, and the queue name in this + method is empty, the server MUST raise a connection exception with reply + code 530 (not allowed). + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + + <field name = "no-ack" domain = "no-ack" /> + </method> + + <method name = "get-ok" synchronous = "1" content = "1" index = "71" + label = "provide client with a message"> + <doc> + This method delivers a message to the client following a get method. A message + delivered by 'get-ok' must be acknowledged unless the no-ack option was set in the + get method. + </doc> + + <chassis name = "client" implement = "MAY" /> + + <field name = "delivery-tag" domain = "delivery-tag" /> + + <field name = "redelivered" domain = "redelivered" /> + + <field name = "exchange" domain = "exchange-name"> + <doc> + Specifies the name of the exchange that the message was originally published to. + If empty, the message was published to the default exchange. + </doc> + </field> + + <field name = "routing-key" domain = "shortstr" label = "Message routing key"> + <doc>Specifies the routing key name specified when the message was published.</doc> + </field> + + <field name = "message-count" domain = "long" label = "number of messages pending"> + <doc> + This field reports the number of messages pending on the queue, excluding the + message being delivered. Note that this figure is indicative, not reliable, and + can change arbitrarily as messages are added to the queue and removed by other + clients. + </doc> + </field> + </method> + + <method name = "get-empty" synchronous = "1" index = "72" + label = "indicate no messages available"> + <doc> + This method tells the client that the queue has no messages available for the + client. + </doc> + + <chassis name = "client" implement = "MAY" /> + + <!-- This field is deprecated pending review --> + <field name = "cluster-id" domain = "shortstr" label = "Cluster id"> + <doc> + For use by cluster applications, should not be used by client applications. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "ack" index = "80" label = "acknowledge one or more messages"> + <doc> + This method acknowledges one or more messages delivered via the Deliver or Get-Ok + methods. The client can ask to confirm a single message or a set of messages up to + and including a specific message. + </doc> + + <chassis name = "server" implement = "MUST" /> + + <field name = "delivery-tag" domain = "delivery-tag" /> + + <field name = "multiple" domain = "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 method. 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 test name: was "amq_basic_20" --> + <rule name = "01"> + <doc> + The server MUST validate that a non-zero delivery-tag refers to an delivered + message, and raise a channel exception if this is not the case. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "reject" index = "90" label = "reject an incoming message"> + <doc> + This method allows a client to reject a message. It can be used to interrupt and + cancel large incoming messages, or return untreatable messages to their original + queue. + </doc> + + <!-- Rule test name: was "amq_basic_21" --> + <rule name = "01"> + <doc> + The server SHOULD be capable of accepting and process the Reject method while + sending message content with a Deliver or Get-Ok method. I.e. the server should + read and process incoming methods while sending output frames. To cancel a + partially-send content, the server sends a content body frame of size 1 (i.e. + with no data except the frame-end octet). + </doc> + </rule> + + <!-- Rule test name: was "amq_basic_22" --> + <rule name = "02"> + <doc> + The server SHOULD interpret this method as meaning that the client is unable to + process the message at this time. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + + <rule name = "03"> + <!-- TODO: Rule split? --> + <doc> + A client MUST NOT use this method as a means of selecting messages to process. A + rejected message MAY be discarded or dead-lettered, not necessarily passed to + another client. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + + <field name = "delivery-tag" domain = "delivery-tag" /> + + <field name = "requeue" domain = "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 test name: was "amq_basic_23" --> + <rule name = "01"> + <!-- TODO: Rule split? --> + <doc> + The server MUST NOT deliver the message to the same client within the + context of the current channel. 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> + <doc type = "scenario"> + TODO. + </doc> + </rule> + </field> + </method> + + <method name = "recover" index = "100" label = "redeliver unacknowledged messages"> + <doc> + This method asks the broker to redeliver all unacknowledged messages on a specified + channel. Zero or more messages may be redelivered. This method is only allowed on + non-transacted channels. + </doc> + + <rule name = "01"> + <doc> + The server MUST set the redelivered flag on all messages that are resent. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + + <rule name = "02"> + <doc> + The server MUST raise a channel exception if this is called on a transacted + channel. + </doc> + <doc type = "scenario"> + TODO. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + + <field name = "requeue" domain = "bit" label = "requeue the message"> + <doc> + If this field is zero, the message will be redelivered to the original + recipient. If this bit is 1, the server will attempt to requeue the message, + potentially then delivering it to an alternative subscriber. + </doc> + </field> + </method> + + + <!-- RG : Added recover-sync and recover-sync-ok to give a synchronous recover without interfering with the correct 0-9 recover method --> + <method name = "recover-sync" index = "102"> + redeliver unacknowledged messages + <doc> + This method asks the broker to redeliver all unacknowledged messages on a + specified channel. Zero or more messages may be redelivered. This method + is only allowed on non-transacted channels. + </doc> + <chassis name = "server" implement = "MUST" /> + + <field name = "requeue" type = "bit"> + requeue the message + <doc> + If this field is zero, the message will be redelivered to the original + recipient. If this bit is 1, the server will attempt to requeue the + message, potentially then delivering it to an alternative subscriber. + </doc> + </field> + <doc name="rule"> + The server MUST set the redelivered flag on all messages that are resent. + </doc> + <doc name="rule"> + The server MUST raise a channel exception if this is called on a + transacted channel. + </doc> + <response name="recover-sync-ok"/> + </method> + <method name="recover-sync-ok" synchronous="1" index="101"> + confirm a successful recover + <doc> + This method confirms to the client that the recover succeeded. + Note that if an recover fails, the server raises a channel exception. + </doc> + <chassis name="client" implement="MUST"/> + </method> + + + </class> + + <!-- == FILE ============================================================= --> + + <class name = "file" handler = "channel" index = "70" label = "work with file content"> + <doc> + The file class provides methods 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 + channel transactions. Note that the file class does not provide message browsing + methods; these are not compatible with the staging model. Applications that need + browsable file transfer should use Basic content and the Basic class. + </doc> + + <doc type = "grammar"> + file = C:QOS S:QOS-OK + / C:CONSUME S:CONSUME-OK + / C:CANCEL S:CANCEL-OK + / 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> + + <chassis name = "server" implement = "MAY" /> + <chassis name = "client" implement = "MAY" /> + + <rule name = "01"> + <doc> + The server MUST make a best-effort to hold file messages on a reliable storage + mechanism. + </doc> + </rule> + + <!-- TODO Rule implement attr inverse? --> + + <!-- TODO: Rule split? --> + + <rule name = "02"> + <doc> + The server MUST NOT discard a file message in case of a queue overflow. The server + MUST use the Channel.Flow method to slow or stop a file message publisher when + necessary. + </doc> + </rule> + + <!-- TODO: Rule split? --> + + <rule name = "03"> + <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 = "04"> + <doc> + The server MUST support both automatic and explicit acknowledgements on file + content. + </doc> + </rule> + + <!-- These are the properties for a File content --> + + <field name = "content-type" domain = "shortstr" label = "MIME content type" /> + <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> + <field name = "headers" domain = "table" label = "message header field table" /> + <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> + <field name = "reply-to" domain = "shortstr" label = "destination to reply to" /> + <field name = "message-id" domain = "shortstr" label = "application message identifier" /> + <field name = "filename" domain = "shortstr" label = "message filename" /> + <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> + <!-- This field is deprecated pending review --> + <field name = "cluster-id" domain = "shortstr" label = "intra-cluster routing identifier" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> + <doc> + This method requests a specific quality of service. The QoS can be specified for the + current channel or for all channels on the connection. The particular properties and + semantics of a qos method always depend on the content class semantics. Though the + qos method could in principle apply to both peers, it is currently meaningful only + for the server. + </doc> + + <chassis name = "server" implement = "MUST" /> + + <response name = "qos-ok" /> + + <field name = "prefetch-size" domain = "long" label = "prefetch 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 down the channel. Prefetching gives a performance + improvement. This field specifies the prefetch window size in octets. May be set + to zero, meaning "no specific limit". Note that other prefetch limits may still + apply. The prefetch-size is ignored if the no-ack option is set. + </doc> + </field> + + <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> + <doc> + Specifies a prefetch 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 prefetch + windows (and those at the channel and connection level) allow it. The + prefetch-count is ignored if the no-ack option is set. + </doc> + + <rule name = "01"> + <!-- TODO: Rule split? --> + <doc> + The server MAY send less data in advance than allowed by the client's + specified prefetch windows but it MUST NOT send more. + </doc> + </rule> + </field> + + <field name = "global" domain = "bit" label = "apply to entire connection"> + <doc> + By default the QoS settings apply to the current channel only. If this field is + set, they are applied to the entire connection. + </doc> + </field> + </method> + + <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> + <doc> + This method 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> + + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "consume" synchronous = "1" index = "20" label = "start a queue consumer"> + <doc> + This method asks the server to start a "consumer", which is a transient request for + messages from a specific queue. Consumers last as long as the channel they were + created on, or until the client cancels them. + </doc> + + <rule name = "01"> + <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> + + <chassis name = "server" implement = "MUST" /> + + <response name = "consume-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "read" access rights to + the realm for the queue. + </doc> + </rule> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to consume from. If the queue name is null, + refers to the current queue for the channel, which is the last declared queue. + </doc> + + <rule name = "01"> + <doc> + If the client did not previously declare a queue, and the queue name in this + method is empty, the server MUST raise a connection exception with reply + code 530 (not allowed). + </doc> + </rule> + </field> + + <field name = "consumer-tag" domain = "consumer-tag"> + <doc> + Specifies the identifier for the consumer. The consumer tag is local to a + connection, so two clients can use the same consumer tags. If this field is + empty the server will generate a unique tag. + </doc> + + <rule name = "01"> + <!-- TODO: Rule split? --> + <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 a + connection exception with reply code 530 (not allowed). + </doc> + </rule> + </field> + + <field name = "no-local" domain = "no-local" /> + + <field name = "no-ack" domain = "no-ack" /> + + <field name = "exclusive" domain = "bit" label = "request exclusive access"> + <doc> + Request exclusive consumer access, meaning only this consumer can access the + queue. + </doc> + + <!-- Rule test name: was "amq_file_00" --> + <rule name = "01"> + <doc> + If the server cannot grant exclusive access to the queue when asked, - + because there are other consumers active - it MUST raise a channel exception + with return code 405 (resource locked). + </doc> + </rule> + </field> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + + <field name = "filter" domain = "table" label = "arguments for consuming"> + <doc> + A set of filters for the consume. The syntax and semantics + of these filters depends on the providers implementation. + </doc> + </field> + </method> + + <method name = "consume-ok" synchronous = "1" index = "21" label = "confirm a new consumer"> + <doc> + This method provides the client with a consumer tag which it MUST use in methods + that work with the consumer. + </doc> + + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer-tag" domain = "consumer-tag"> + <doc>Holds the consumer tag specified by the client or provided by the server.</doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "cancel" synchronous = "1" index = "30" label = "end a queue consumer"> + <doc> + This method 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> + + <response name = "cancel-ok" /> + + <chassis name = "server" implement = "MUST" /> + + <field name = "consumer-tag" domain = "consumer-tag" /> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + </method> + + <method name = "cancel-ok" synchronous = "1" index = "31" label = "confirm a cancelled consumer"> + <doc>This method confirms that the cancellation was completed.</doc> + + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer-tag" domain = "consumer-tag" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "open" synchronous = "1" index = "40" label = "request to start staging"> + <doc> + This method 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> + + <response name = "open-ok" /> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <field name = "identifier" domain = "shortstr" 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" domain = "longlong" 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 = "01"> + <doc> + The sender MUST accurately fill the content-size field. Zero-length content + is permitted. + </doc> + </rule> + </field> + </method> + + <method name = "open-ok" synchronous = "1" index = "41" label = "confirm staging ready"> + <doc> + This method 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> + + <response name = "stage" /> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <field name = "staged-size" domain = "longlong" label = "already staged amount"> + <doc> + The amount of previously-staged content in octets. For a new message this will + be zero. + </doc> + + <rule name = "01"> + <doc> + The sender MUST start sending data from this octet offset in the message, + counting from zero. + </doc> + </rule> + + <rule name = "02"> + <!-- TODO: Rule split? --> + <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 methods. + </doc> + </rule> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "stage" content = "1" index = "50" label = "stage message content"> + <doc> + This method stages the message, sending the message content to the recipient from + the octet offset specified in the Open-Ok method. + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "publish" index = "60" label = "publish a message"> + <doc> + This method 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> + + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "write" access rights + to the access realm for the exchange. + </doc> + </rule> + </field> + + <field name = "exchange" domain = "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 a channel exception. + </doc> + + <rule name = "01"> + <doc> + The server MUST accept a blank exchange name to mean the default exchange. + </doc> + </rule> + + <rule name = "02"> + <doc> + If the exchange was declared as an internal exchange, the server MUST + respond with a reply code 403 (access refused) and raise a channel + exception. + </doc> + </rule> + + <!-- TODO: Rule split? --> + + <rule name = "03"> + <doc> + The exchange MAY refuse file content in which case it MUST respond with a + reply code 540 (not implemented) and raise a channel exception. + </doc> + </rule> + </field> + + <field name = "routing-key" domain = "shortstr" 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" domain = "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 method. If this flag is zero, the server silently drops the message. + </doc> + + <!-- Rule test name: was "amq_file_00" --> + <rule name = "01"> + <doc>The server SHOULD implement the mandatory flag.</doc> + </rule> + </field> + + <field name = "immediate" domain = "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 method. If this flag is zero, the server + will queue the message, but with no guarantee that it will ever be consumed. + </doc> + + <!-- Rule test name: was "amq_file_00" --> + <rule name = "01"> + <doc>The server SHOULD implement the immediate flag.</doc> + </rule> + </field> + + <field name = "identifier" domain = "shortstr" 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 method asynchronously + without waiting for staging to finish. + </doc> + </field> + </method> + + <method name = "return" content = "1" index = "70" label = "return a failed message"> + <doc> + This method 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> + + <chassis name = "client" implement = "MUST" /> + + <field name = "reply-code" domain = "reply-code" /> + + <field name = "reply-text" domain = "reply-text" /> + + <field name = "exchange" domain = "exchange-name"> + <doc> + Specifies the name of the exchange that the message was originally published to. + </doc> + </field> + + <field name = "routing-key" domain = "shortstr" label = "Message routing key"> + <doc>Specifies the routing key name specified when the message was published.</doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "deliver" index = "80" label = "notify the client of a consumer message"> + <doc> + This method 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 + method, then the server responds with Deliver methods as and when messages arrive + for that consumer. + </doc> + + <rule name = "01"> + <!-- TODO: Rule split? --> + <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 + unprocessable (possibly causing client applications to abort), and move the + message to a dead letter queue. + </doc> + </rule> + + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer-tag" domain = "consumer-tag" /> + + <field name = "delivery-tag" domain = "delivery-tag" /> + + <field name = "redelivered" domain = "redelivered" /> + + <field name = "exchange" domain = "exchange-name"> + <doc> + Specifies the name of the exchange that the message was originally published to. + </doc> + </field> + + <field name = "routing-key" domain = "shortstr" label = "Message routing key"> + <doc>Specifies the routing key name specified when the message was published.</doc> + </field> + + <field name = "identifier" domain = "shortstr" 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 method asynchronously + without waiting for staging to finish. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "ack" index = "90" label = "acknowledge one or more messages"> + <doc> + This method acknowledges one or more messages delivered via the Deliver method. The + client can ask to confirm a single message or a set of messages up to and including + a specific message. + </doc> + + <chassis name = "server" implement = "MUST" /> + + <field name = "delivery-tag" domain = "delivery-tag" /> + + <field name = "multiple" domain = "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 method. 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 = "01"> + <doc> + The server MUST validate that a non-zero delivery-tag refers to an delivered + message, and raise a channel exception if this is not the case. + </doc> + </rule> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "reject" index = "100" label = "reject an incoming message"> + <doc> + This method 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 method to interrupt delivery of a + large message. + </doc> + + <rule name = "01"> + <doc> + The server SHOULD interpret this method as meaning that the client is unable to + process the message at this time. + </doc> + </rule> + + <!-- TODO: Rule split? --> + + <rule name = "02"> + <doc> + A client MUST NOT use this method 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> + + <chassis name = "server" implement = "MUST" /> + + <field name = "delivery-tag" domain = "delivery-tag" /> + + <field name = "requeue" domain = "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 = "01"> + <!-- TODO: Rule split? --> + <doc> + The server MUST NOT deliver the message to the same client within the + context of the current channel. 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> + </method> + </class> + + <!-- == STREAM =========================================================== --> + + <class name = "stream" handler = "channel" index = "80" label = "work with streaming content"> + <doc> + The stream class provides methods 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 favour + of high priority messages. + </doc> + + <doc type = "grammar"> + stream = C:QOS S:QOS-OK + / C:CONSUME S:CONSUME-OK + / C:CANCEL S:CANCEL-OK + / C:PUBLISH content + / S:RETURN + / S:DELIVER content + </doc> + + <chassis name = "server" implement = "MAY" /> + <chassis name = "client" implement = "MAY" /> + + <rule name = "01"> + <doc> + The server SHOULD discard stream messages on a priority basis if the queue size + exceeds some configured limit. + </doc> + </rule> + + <rule name = "02"> + <!-- TODO: Rule split? --> + <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 = "03"> + <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 method, the server must + remove it from the queue. + </doc> + </rule> + + <!-- These are the properties for a Stream content --> + + <field name = "content-type" domain = "shortstr" label = "MIME content type" /> + <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> + <field name = "headers" domain = "table" label = "message header field table" /> + <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> + <field name = "timestamp" domain = "timestamp" label = "message timestamp" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "qos" synchronous = "1" index = "10" label = "specify quality of service"> + <doc> + This method requests a specific quality of service. The QoS can be specified for the + current channel or for all channels on the connection. The particular properties and + semantics of a qos method always depend on the content class semantics. Though the + qos method could in principle apply to both peers, it is currently meaningful only + for the server. + </doc> + + <chassis name = "server" implement = "MUST" /> + + <response name = "qos-ok" /> + + <field name = "prefetch-size" domain = "long" label = "prefetch 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 down the channel. Prefetching gives a performance + improvement. This field specifies the prefetch window size in octets. May be set + to zero, meaning "no specific limit". Note that other prefetch limits may still + apply. + </doc> + </field> + + <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> + <doc> + Specifies a prefetch 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 prefetch windows (and those at the channel and connection level) + allow it. + </doc> + </field> + + <field name = "consume-rate" domain = "long" 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 = "01"> + <!-- TODO: Rule split? --> + <doc> + The server MAY ignore the prefetch values and consume rates, depending on + the type of stream and the ability of the server to queue and/or reply it. + The server MAY drop low-priority messages in favour of high-priority + messages. + </doc> + </rule> + </field> + + <field name = "global" domain = "bit" label = "apply to entire connection"> + <doc> + By default the QoS settings apply to the current channel only. If this field is + set, they are applied to the entire connection. + </doc> + </field> + </method> + + <method name = "qos-ok" synchronous = "1" index = "11" label = "confirm the requested qos"> + <doc> + This method 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> + + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "consume" synchronous = "1" index = "20" label = "start a queue consumer"> + <doc> + This method asks the server to start a "consumer", which is a transient request for + messages from a specific queue. Consumers last as long as the channel they were + created on, or until the client cancels them. + </doc> + + <rule name = "01"> + <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 = "02"> + <doc> + Streaming applications SHOULD use different channels 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> + + <chassis name = "server" implement = "MUST" /> + <response name = "consume-ok" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "read" access rights to + the realm for the queue. + </doc> + </rule> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to consume from. If the queue name is null, + refers to the current queue for the channel, which is the last declared queue. + </doc> + + <rule name = "01"> + <doc> + If the client did not previously declare a queue, and the queue name in this + method is empty, the server MUST raise a connection exception with reply + code 530 (not allowed). + </doc> + </rule> + </field> + + <field name = "consumer-tag" domain = "consumer-tag"> + <doc> + Specifies the identifier for the consumer. The consumer tag is local to a + connection, so two clients can use the same consumer tags. If this field is + empty the server will generate a unique tag. + </doc> + + <rule name = "01"> + <!-- TODO: Rule split? --> + <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 a + connection exception with reply code 530 (not allowed). + </doc> + </rule> + </field> + + <field name = "no-local" domain = "no-local" /> + + <field name = "exclusive" domain = "bit" label = "request exclusive access"> + <doc> + Request exclusive consumer access, meaning only this consumer can access the + queue. + </doc> + + + <!-- Rule test name: was "amq_file_00" --> + <rule name = "01"> + <doc> + If the server cannot grant exclusive access to the queue when asked, - + because there are other consumers active - it MUST raise a channel exception + with return code 405 (resource locked). + </doc> + </rule> + </field> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + + <field name = "filter" domain = "table" label = "arguments for consuming"> + <doc> + A set of filters for the consume. The syntax and semantics + of these filters depends on the providers implementation. + </doc> + </field> + </method> + + <method name = "consume-ok" synchronous = "1" index = "21" label = "confirm a new consumer"> + <doc> + This method provides the client with a consumer tag which it may use in methods that + work with the consumer. + </doc> + + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer-tag" domain = "consumer-tag"> + <doc>Holds the consumer tag specified by the client or provided by the server.</doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "cancel" synchronous = "1" index = "30" label = "end a queue consumer"> + <doc> + This method 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> + + <chassis name = "server" implement = "MUST" /> + + <response name = "cancel-ok" /> + + <field name = "consumer-tag" domain = "consumer-tag" /> + + <field name = "nowait" domain = "bit" label = "do not send a reply method"> + <doc> + If set, the server will not respond to the method. The client should not wait + for a reply method. If the server could not complete the method it will raise a + channel or connection exception. + </doc> + </field> + </method> + + <method name = "cancel-ok" synchronous = "1" index = "31" label = "confirm a cancelled consumer"> + <doc>This method confirms that the cancellation was completed.</doc> + + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer-tag" domain = "consumer-tag" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "publish" content = "1" index = "40" label = "publish a message"> + <doc> + This method 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> + + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "write" access rights + to the access realm for the exchange. + </doc> + </rule> + </field> + + <field name = "exchange" domain = "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 a channel exception. + </doc> + + <rule name = "01"> + <doc> + The server MUST accept a blank exchange name to mean the default exchange. + </doc> + </rule> + + <rule name = "02"> + <doc> + If the exchange was declared as an internal exchange, the server MUST + respond with a reply code 403 (access refused) and raise a channel + exception. + </doc> + </rule> + + <rule name = "03"> + <doc> + The exchange MAY refuse stream content in which case it MUST respond with a + reply code 540 (not implemented) and raise a channel exception. + </doc> + </rule> + </field> + + <field name = "routing-key" domain = "shortstr" 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" domain = "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 method. If this flag is zero, the server silently drops the message. + </doc> + + <!-- Rule test name: was "amq_stream_00" --> + <rule name = "01"> + <doc>The server SHOULD implement the mandatory flag.</doc> + </rule> + </field> + + <field name = "immediate" domain = "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 method. If this flag is zero, the server + will queue the message, but with no guarantee that it will ever be consumed. + </doc> + + <!-- Rule test name: was "amq_stream_00" --> + <rule name = "01"> + <doc>The server SHOULD implement the immediate flag.</doc> + </rule> + </field> + </method> + + <method name = "return" content = "1" index = "50" label = "return a failed message"> + <doc> + This method 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> + + <chassis name = "client" implement = "MUST" /> + + <field name = "reply-code" domain = "reply-code" /> + + <field name = "reply-text" domain = "reply-text" /> + + <field name = "exchange" domain = "exchange-name"> + <doc> + Specifies the name of the exchange that the message was originally published to. + </doc> + </field> + + <field name = "routing-key" domain = "shortstr" label = "Message routing key"> + <doc>Specifies the routing key name specified when the message was published.</doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "deliver" content = "1" index = "60" + label = "notify the client of a consumer message"> + <doc> + This method delivers a message to the client, via a consumer. In the asynchronous + message delivery model, the client starts a consumer using the Consume method, then + the server responds with Deliver methods as and when messages arrive for that + consumer. + </doc> + + <chassis name = "client" implement = "MUST" /> + + <field name = "consumer-tag" domain = "consumer-tag" /> + + <field name = "delivery-tag" domain = "delivery-tag" /> + + <field name = "exchange" domain = "exchange-name"> + <doc> + Specifies the name of the exchange that the message was originally published to. + </doc> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue that the message came from. Note that a single + channel can start many consumers on different queues. + </doc> + <assert check = "notnull" /> + </field> + </method> + </class> + + <!-- == TX =============================================================== --> + + <class name = "tx" handler = "channel" index = "90" 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> + + <!-- TODO: Rule split? --> + + <rule name = "01"> + <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> + + <doc type = "grammar"> + tx = C:SELECT S:SELECT-OK + / C:COMMIT S:COMMIT-OK + / C:ROLLBACK S:ROLLBACK-OK + </doc> + + <chassis name = "server" implement = "SHOULD" /> + <chassis name = "client" implement = "MAY" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "select" synchronous = "1" index = "10" label = "select standard transaction mode"> + <doc> + This method sets the channel to use standard transactions. The client must use this + method at least once on a channel before using the Commit or Rollback methods. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "select-ok" /> + </method> + + <method name = "select-ok" synchronous = "1" index = "11" label = "confirm transaction mode"> + <doc> + This method confirms to the client that the channel was successfully set to use + standard transactions. + </doc> + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "commit" synchronous = "1" index = "20" label = "commit the current transaction"> + <doc> + This method commits all messages published and acknowledged in the current + transaction. A new transaction starts immediately after a commit. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "commit-ok" /> + </method> + + <method name = "commit-ok" synchronous = "1" index = "21" label = "confirm a successful commit"> + <doc> + This method confirms to the client that the commit succeeded. Note that if a commit + fails, the server raises a channel exception. + </doc> + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "rollback" synchronous = "1" index = "30" + label = "abandon the current transaction"> + <doc> + This method abandons all messages published and acknowledged in the current + transaction. A new transaction starts immediately after a rollback. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "rollback-ok" /> + </method> + + <method name = "rollback-ok" synchronous = "1" index = "31" label = "confirm successful rollback"> + <doc> + This method confirms to the client that the rollback succeeded. Note that if an + rollback fails, the server raises a channel exception. + </doc> + <chassis name = "client" implement = "MUST" /> + </method> + </class> + + <!-- == DTX ============================================================== --> + + <class name = "dtx" handler = "channel" index = "100" label = "work with distributed transactions"> + <doc> + Distributed transactions provide so-called "2-phase commit". The AMQP distributed + transaction model supports the X-Open XA architecture and other distributed transaction + implementations. The Dtx class assumes that the server has a private communications + channel (not AMQP) to a distributed transaction coordinator. + </doc> + + <doc type = "grammar"> + dtx = C:SELECT S:SELECT-OK + C:START S:START-OK + </doc> + + <chassis name = "server" implement = "MAY" /> + <chassis name = "client" implement = "MAY" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "select" synchronous = "1" index = "10" label = "select standard transaction mode"> + <doc> + This method sets the channel to use distributed transactions. The client must use + this method at least once on a channel before using the Start method. + </doc> + <chassis name = "server" implement = "MUST" /> + <response name = "select-ok" /> + </method> + + <method name = "select-ok" synchronous = "1" index = "11" label = "confirm transaction mode"> + <doc> + This method confirms to the client that the channel was successfully set to use + distributed transactions. + </doc> + <chassis name = "client" implement = "MUST" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "start" synchronous = "1" index = "20" + label = "start a new distributed transaction"> + <doc> + This method starts a new distributed transaction. This must be the first method on a + new channel that uses the distributed transaction mode, before any methods that + publish or consume messages. + </doc> + <chassis name = "server" implement = "MAY" /> + <response name = "start-ok" /> + <field name = "dtx-identifier" domain = "shortstr" label = "transaction identifier"> + <doc> + The distributed transaction key. This identifies the transaction so that the + AMQP server can coordinate with the distributed transaction coordinator. + </doc> + <assert check = "notnull" /> + </field> + </method> + + <method name = "start-ok" synchronous = "1" index = "21" + label = "confirm the start of a new distributed transaction"> + <doc> + This method confirms to the client that the transaction started. Note that if a + start fails, the server raises a channel exception. + </doc> + <chassis name = "client" implement = "MUST" /> + </method> + </class> + + <!-- == TUNNEL =========================================================== --> + + <class name = "tunnel" handler = "tunnel" index = "110" label = "methods for protocol tunnelling"> + <doc> + The tunnel methods are used to send blocks of binary data - which can be serialised AMQP + methods or other protocol frames - between AMQP peers. + </doc> + + <doc type = "grammar"> + tunnel = C:REQUEST + / S:REQUEST + </doc> + + <chassis name = "server" implement = "MAY" /> + <chassis name = "client" implement = "MAY" /> + + <field name = "headers" domain = "table" label = "message header field table" /> + <field name = "proxy-name" domain = "shortstr" label = "identity of tunnelling proxy" /> + <field name = "data-name" domain = "shortstr" label = "name or type of message being tunnelled" /> + <field name = "durable" domain = "octet" label = "message durability indicator" /> + <field name = "broadcast" domain = "octet" label = "message broadcast mode" /> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "request" content = "1" index = "10" label = "sends a tunnelled method"> + <doc> + This method tunnels a block of binary data, which can be an encoded + AMQP method or other data. The binary data is sent as the content for + the Tunnel.Request method. + </doc> + <chassis name = "server" implement = "MUST" /> + <field name = "meta-data" domain = "table" label = "meta data for the tunnelled block"> + <doc> + This field table holds arbitrary meta-data that the sender needs to + pass to the recipient. + </doc> + </field> + </method> + </class> + + <!-- == MESSAGE ============================================================ --> + + <class name = "message" index = "120" handler = "channel" label = "[WORK IN PROGRESS] message transfer"> + <doc> + [WORK IN PROGRESS] The message class provides methods that support an industry-standard messaging model. + </doc> + + <doc type = "grammar"> + message = C:QOS S:OK + / C:CONSUME S:OK + / C:CANCEL S:OK + / C:TRANSFER ( S:OK / S:REJECT ) + / S:TRANSFER ( C:OK / C:REJECT ) + / C:GET ( S:OK / S:EMPTY ) + / C:RECOVER S:OK + / C:OPEN S:OK + / S:OPEN C:OK + / C:APPEND S:OK + / S:APPEND C:OK + / C:CLOSE S:OK + / S:CLOSE C:OK + / C:CHECKPOINT S:OK + / S:CHECKPOINT C:OK + / C:RESUME S:OFFSET + / S:RESUME C:OFFSET + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <rule name = "01"> + <doc> + The server SHOULD respect the persistent property of messages + and SHOULD make a best-effort to hold persistent mess ages 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 = "02"> + <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 = "03"> + <doc> + The server MAY use the Channel.Flow method to slow or stop a + message publisher when necessary. + </doc> + <doc type = "scenario"> + Create a queue overflow situation with non-persistent messages + and verify whether the server responds with Channel.Flow or + not. Repeat with persistent messages. + </doc> + </rule> + + <rule name = "04"> + <doc> + The server MAY overflow non-persistent messages to persistent + storage. + </doc> + </rule> + + <rule name = "05"> + <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 = "06"> + <doc> + The server MUST implement at least 2 priority levels for + messages, where priorities 0-4 and 5-9 are treated as two + distinct levels. + </doc> + <doc type = "scenario"> + Send a number of priority 0 messages to a queue. Send one + priority 9 message. Consume messages from the queue and verify + that the first message received was priority 9. + </doc> + </rule> + + <rule name = "07"> + <doc> + The server MAY implement up to 10 priority levels. + </doc> + <doc type = "scenario"> + Send a number of messages with mixed priorities to a queue, so + that all priority values from 0 to 9 are exercised. A good + scenario would be ten messages in low-to-high priority. + Consume from queue and verify how many priority levels emerge. + </doc> + </rule> + + <rule name = "08"> + <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. Consume and verify that + messages arrive in same order as originally published. + </doc> + </rule> + + <rule name = "09"> + <doc> + The server MUST support automatic acknowledgements on + messages, i.e. consumers with the no-ack field set to FALSE. + </doc> + <doc type = "scenario"> + Create a queue and a consumer using automatic + acknowledgements. Publish a set of messages to the queue. + Consume the messages and verify that all messages are + received. + </doc> + </rule> + + <rule name = "10"> + <doc> + The server MUST support explicit acknowledgements on messages, + i.e. consumers with the no-ack field set to TRUE. + </doc> + <doc type = "scenario"> + Create a queue and a consumer using explicit acknowledgements. + Publish a set of messages to the queue. Consume the messages + but acknowledge only half of them. Disconnect and reconnect, + and consume from the queue. Verify that the remaining messages + are received. + </doc> + </rule> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "transfer" index = "10" label = "[WORK IN PROGRESS] transfer a message"> + <doc> + [WORK IN PROGRESS] This method transfers a message between two peers. When a + client uses this method 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 and distributed to any active consumers when the + transaction, if any, is committed. + + In the asynchronous message delivery model, the client starts + a consumer using the Consume method and passing in a + destination, then the broker responds with transfer methods to + the specified destination as and when messages arrive for that + consumer. + + If synchronous message delivery is required, the client may + issue a get request which on success causes a single message + to be transferred to the specified destination. + + Message acknowledgement is signalled by the return result of + this method. + </doc> + + <rule name = "01"> + <doc> + The recipient MUST NOT return ok before the message has been + processed as defined by the QoS settings. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + <response name = "ok" /> + <response name = "reject" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "write" access rights + to the access realm for the exchange. + </doc> + </rule> + </field> + + <field name = "destination" domain = "destination"> + <doc> + Specifies the destination to which the message is to be + transferred. The destination can be empty, meaning the + default exchange or consumer. If the destination is + specified, and that exchange or consumer does not exist, the + peer must raise a channel exception. + </doc> + + <rule name = "01"> + <doc> + The server MUST accept a blank destination to mean the + default exchange. + </doc> + </rule> + + <rule name = "02"> + <doc> + If the destination refers to an internal exchange, the + server MUST raise a channel exception with a reply code + 403 (access refused). + </doc> + </rule> + + <rule name = "03"> + <doc> + A destination MAY refuse message content in which case it + MUST raise a channel exception with reply code 540 (not + implemented). + </doc> + </rule> + </field> + + <field name = "redelivered" domain = "redelivered" /> + + <field name = "immediate" domain = "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 reject the message. If this + flag is zero, the server will queue the message, but with no + guarantee that it will ever be consumed. + </doc> + <rule name = "01"> + <doc> + The server SHOULD implement the immediate flag. + </doc> + </rule> + </field> + + <field name = "ttl" domain = "duration" label = "time to live"> + <doc> + If this is set to a non zero value 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 = "01"> + <doc> + If a message is transfered between brokers before delivery + to a final consumer the ttl should be decremented before + peer to peer transfer and both timestamp and expiration + should be cleared. + </doc> + </rule> + </field> + + <!-- begin headers --> + <field name = "priority" domain = "octet" label = "message priority, 0 to 9" /> + <field name = "timestamp" domain = "timestamp" label = "message timestamp"> + <doc> + Set on arrival by the broker. + </doc> + </field> + <field name = "delivery-mode" domain = "octet" label = "non-persistent (1) or persistent (2)" /> + <field name = "expiration" domain = "timestamp" 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 method and the current + time. (ttl = expiration - timestamp) + </doc> + </field> + <field name = "exchange" domain = "exchange-name" label = "originating exchange" /> + <field name = "routing-key" domain = "shortstr" label = "message routing key" /> + <field name = "message-id" domain = "shortstr" label = "application message identifier" /> + <field name = "correlation-id" domain = "shortstr" label = "application correlation identifier" /> + <field name = "reply-to" domain = "shortstr" label = "destination to reply to" /> + <field name = "content-type" domain = "shortstr" label = "MIME content type" /> + <field name = "content-encoding" domain = "shortstr" label = "MIME content encoding" /> + <field name = "user-id" domain = "shortstr" label = "creating user id" /> + <field name = "app-id" domain = "shortstr" label = "creating application id" /> + <field name = "transaction-id" domain = "shortstr" label = "distributed transaction id" /> + <field name = "security-token" domain = "security-token" /> + <field name = "application-headers" domain = "table" label = "application specific headers table" /> + <!-- end headers --> + + <field name = "body" domain = "content" label = "message body" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "consume" index = "20" label = "[WORK IN PROGRESS] start a queue consumer"> + <doc> + [WORK IN PROGRESS] This method asks the server to start a "consumer", which is a transient request for + messages from a specific queue. Consumers last as long as the channel they were + created on, or until the client cancels them. + </doc> + + <rule name = "01"> + <doc> + The server SHOULD support at least 16 consumers per queue, and ideally, impose + no limit except as defined by available resources. + </doc> + <doc type = "scenario"> + Create a queue and create consumers on that queue until the server closes the + connection. Verify that the number of consumers created was at least sixteen + and report the total number. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + <response name = "ok" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01" on-failure = "access-refused"> + <doc> + The client MUST provide a valid access ticket giving "read" access rights to + the realm for the queue. + </doc> + <doc type = "scenario"> + Attempt to create a consumer with an invalid (non-zero) access ticket. + </doc> + </rule> + </field> + + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to consume from. If the queue name is null, + refers to the current queue for the channel, which is the last declared queue. + </doc> + <rule name = "01" on-failure = "not-allowed"> + <doc> + If the queue name is empty the client MUST have previously declared a + queue using this channel. + </doc> + <doc type = "scenario"> + Attempt to create a consumer with an empty queue name and no previously + declared queue on the channel. + </doc> + </rule> + </field> + + <field name = "destination" domain = "destination" label = "incoming message destination"> + <doc> + Specifies the destination for the consumer. The destination is local to a + connection, so two clients can use the same destination. + </doc> + <rule name = "01" on-failure = "not-allowed"> + <doc> + The client MUST NOT specify a destination that refers to an existing consumer. + </doc> + <doc type = "scenario"> + Attempt to create two consumers with the same non-empty destination. + </doc> + </rule> + <rule name = "02" on-failure = "not-allowed"> + <doc> + The destination is valid only within the channel from which the + consumer was created. I.e. a client MUST NOT create a consumer in one + channel and then use it in another. + </doc> + <doc type = "scenario"> + Attempt to create a consumer in one channel, then use in another channel, + in which consumers have also been created (to test that the server uses + unique destinations). + </doc> + </rule> + </field> + + <field name = "no-local" domain = "no-local" /> + + <field name = "no-ack" domain = "no-ack" /> + + <field name = "exclusive" domain = "bit" label = "request exclusive access"> + <doc> + Request exclusive consumer access, meaning only this consumer can access the + queue. + </doc> + + <rule name = "01" on-failure = "access-refused"> + <doc> + The client MAY NOT gain exclusive access to a queue that already has + active consumers. + </doc> + <doc type = "scenario"> + Open two connections to a server, and in one connection create a shared + (non-exclusive) queue and then consume from the queue. In the second + connection attempt to consume from the same queue using the exclusive + option. + </doc> + </rule> + </field> + + <field name = "filter" domain = "table" label = "arguments for consuming"> + <doc> + A set of filters for the consume. The syntax and semantics + of these filters depends on the providers implementation. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "cancel" index = "30" label = "[WORK IN PROGRESS] end a queue consumer"> + <doc> + [WORK IN PROGRESS] This method 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. The client may receive an arbitrary number of messages in + between sending the cancel method and receiving the cancel-ok reply. + </doc> + + <rule name = "01"> + <doc> + If the queue does not exist the server MUST ignore the cancel method, so + long as the consumer tag is valid for that channel. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + <response name = "ok" /> + + <field name = "destination" domain = "destination"/> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "get" index = "40" label = "[WORK IN PROGRESS] direct access to a queue"> + <doc> + [WORK IN PROGRESS] This method provides a direct access to the messages in a queue using a synchronous + dialogue that is designed for specific types of application where synchronous + functionality is more important than performance. + </doc> + + <response name = "ok" /> + <response name = "empty" /> + <chassis name = "server" implement = "MUST" /> + + <field name = "ticket" domain = "access-ticket"> + <rule name = "01"> + <doc> + The client MUST provide a valid access ticket giving "read" access rights to + the realm for the queue. + </doc> + </rule> + </field> + <field name = "queue" domain = "queue-name"> + <doc> + Specifies the name of the queue to consume from. If the queue name is null, + refers to the current queue for the channel, which is the last declared queue. + </doc> + <rule name = "01"> + <doc> + If the client did not previously declare a queue, and the queue name in this + method is empty, the server MUST raise a connection exception with reply + code 530 (not allowed). + </doc> + </rule> + </field> + + <field name = "destination" domain = "destination"> + <doc> + On normal completion of the get request (i.e. a response of + ok). A message will be transferred to the supplied destination. + </doc> + </field> + + <field name = "no-ack" domain = "no-ack" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "recover" index = "50" label = "[WORK IN PROGRESS] redeliver unacknowledged messages"> + <doc> + [WORK IN PROGRESS] This method asks the broker to redeliver all unacknowledged + messages on a specified channel. Zero or more messages may be + redelivered. This method is only allowed on non-transacted + channels. + </doc> + + <rule name = "01"> + <doc> + The server MUST set the redelivered flag on all messages + that are resent. + </doc> + </rule> + + <rule name = "02"> + <doc> + The server MUST raise a channel exception if this is called + on a transacted channel. + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + <response name = "ok" /> + + <field name = "requeue" domain = "bit" label = "requeue the message"> + <doc> + If this field is zero, the message will be redelivered to + the original recipient. If this bit is 1, the server will + attempt to requeue the message, potentially then delivering + it to an alternative subscriber. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "open" index = "60" label = "[WORK IN PROGRESS] create a reference to an empty message body"> + <doc> + [WORK IN PROGRESS] This method creates a reference. A references provides a means + to send a message body into a temporary area at the recipient + end and then deliver the message by referring to this + temporary area. This is how the protocol handles large message + transfers. + + The scope of a ref is defined to be between calls to + open (or resume) and close. Between these points it is valid + for a ref to be used from any content data type, and so the + receiver must hold onto its contents. Should the channel be + closed when a ref is still in scope, the receiver may discard + its contents (unless it is checkpointed). A ref that is in + scope is considered open. + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + <response name = "ok" /> + + <field name = "reference" domain = "reference"> + <rule name = "01"> + <doc> + The recipient MUST generate an error if the reference is + currently open (in scope). + </doc> + </rule> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "close" index = "70" label = "[WORK IN PROGRESS] close a reference"> + <doc> + [WORK IN PROGRESS] This method signals the recipient that no more data will be + appended to the reference. + </doc> + + <rule name = "01"> + <doc> + A recipient CANNOT acknowledge a message until its reference + is closed (not in scope). + </doc> + </rule> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + + <response name = "ok" /> + <field name = "reference" domain = "reference" label = "target reference"> + <rule name = "01"> + <doc> + The recipient MUST generate an error if the reference was + not previously open (in scope). + </doc> + </rule> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "append" index = "80" label = "[WORK IN PROGRESS] append to a reference"> + <doc> + [WORK IN PROGRESS] This method appends data to a reference. + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + <response name = "ok" /> + + <field name = "reference" domain = "reference" label = "target reference"> + <rule name = "01"> + <doc> + The recipient MUST generate an error if the reference is + not open (not in scope). + </doc> + </rule> + </field> + <field name = "bytes" domain = "longstr" label = "data to append" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "checkpoint" index = "90" label = "[WORK IN PROGRESS] checkpoint a message body"> + <doc> + [WORK IN PROGRESS] This method provides a means to checkpoint large message + transfer. The sender may ask the recipient to checkpoint the + contents of a reference using the supplied identifier. The + sender may then resume the transfer at a later point. It is at + the discretion of the recipient how much data to save with the + checkpoint, and the sender MUST honour the offset returned by + the resume method. + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + <response name = "ok" /> + + <field name = "reference" domain = "reference" label = "target reference"> + <rule name = "01"> + <doc> + The recipient MUST generate an error if the reference is + not open (not in scope). + </doc> + </rule> + </field> + <field name = "identifier" domain = "shortstr" label = "checkpoint identifier"> + <doc> + This is the checkpoint identifier. This is an arbitrary + string chosen by the sender. For checkpointing to work + correctly the sender must use the same checkpoint identifier + when resuming the message. A good choice for the checkpoint + identifier would be the SHA1 hash of the message properties + data (including the original filename, revised time, etc.). + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "resume" index = "100" label = "[WORK IN PROGRESS] open and resume a checkpointed message"> + <doc> + [WORK IN PROGRESS] This method resumes a reference from the last checkpoint. A + reference is considered to be open (in scope) after a resume + even though it will not have been opened via the open method + during this session. + </doc> + + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + <response name = "offset" /> + + <field name = "reference" domain = "reference" label = "target reference"> + <rule name = "01"> + <doc> + The recipient MUST generate an error if the reference is + currently open (in scope). + </doc> + </rule> + </field> + <field name = "identifier" domain = "shortstr" label = "checkpoint identifier" /> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + + <method name = "qos" index = "110" label = "[WORK IN PROGRESS] specify quality of service"> + <doc> + [WORK IN PROGRESS] This method requests a specific quality of service. The QoS can be specified for the + current channel or for all channels on the connection. The particular properties and + semantics of a qos method always depend on the content class semantics. Though the + qos method could in principle apply to both peers, it is currently meaningful only + for the server. + </doc> + + <chassis name = "server" implement = "MUST" /> + <response name = "ok" /> + + <field name = "prefetch-size" domain = "long" label = "prefetch 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 down the channel. Prefetching gives a performance + improvement. This field specifies the prefetch window size in octets. The server + will send a message in advance if it is equal to or smaller in size than the + available prefetch size (and also falls into other prefetch limits). May be set + to zero, meaning "no specific limit", although other prefetch limits may still + apply. The prefetch-size is ignored if the no-ack option is set. + </doc> + <rule name = "01"> + <doc> + The server MUST ignore this setting when the client is not processing any + messages - i.e. the prefetch size does not limit the transfer of single + messages to a client, only the sending in advance of more messages while + the client still has one or more unacknowledged messages. + </doc> + <doc type = "scenario"> + Define a QoS prefetch-size limit and send a single message that exceeds + that limit. Verify that the message arrives correctly. + </doc> + </rule> + </field> + + <field name = "prefetch-count" domain = "short" label = "prefetch window in messages"> + <doc> + Specifies a prefetch 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 prefetch windows (and those at the channel and connection level) + allow it. The prefetch-count is ignored if the no-ack option is set. + </doc> + <rule name = "01"> + <doc> + The server may send less data in advance than allowed by the client's + specified prefetch windows but it MUST NOT send more. + </doc> + <doc type = "scenario"> + Define a QoS prefetch-size limit and a prefetch-count limit greater than + one. Send multiple messages that exceed the prefetch size. Verify that + no more than one message arrives at once. + </doc> + </rule> + </field> + + <field name = "global" domain = "bit" label = "apply to entire connection"> + <doc> + By default the QoS settings apply to the current channel only. If this field is + set, they are applied to the entire connection. + </doc> + </field> + </method> + + <!-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - --> + <!-- === Responses === --> + + <method name = "ok" index = "500" label = "[WORK IN PROGRESS] normal completion"> + <doc> + [WORK IN PROGRESS] Signals the normal completion of a method. + </doc> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + </method> + + <method name = "empty" index = "510" label = "[WORK IN PROGRESS] empty queue"> + <doc> + [WORK IN PROGRESS] Signals that a queue does not contain any messages. + </doc> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + </method> + + <method name = "reject" index = "520" label = "[WORK IN PROGRESS] reject a message"> + <doc> + [WORK IN PROGRESS] This response rejects a message. A message may be rejected for + a number of reasons. + </doc> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + <field name = "code" domain = "reject-code" /> + <field name = "text" domain = "reject-text" /> + </method> + + <method name = "offset" index = "530" label = "[WORK IN PROGRESS] return an offset"> + <doc> + [WORK IN PROGRESS] Returns the data offset into a reference body. + </doc> + <chassis name = "server" implement = "MUST" /> + <chassis name = "client" implement = "MUST" /> + <field name = "value" domain = "offset" label = "offset into a reference body" /> + </method> + + </class> + +</amqp> diff --git a/qpid/python/qpid_config.py b/qpid/python/qpid/specs_config.py index d740a53dfe..578f141b4e 100644 --- a/qpid/python/qpid_config.py +++ b/qpid/python/qpid/specs_config.py @@ -19,7 +19,7 @@ import os -AMQP_SPEC_DIR=os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), "specs") +AMQP_SPEC_DIR=os.path.join(os.path.dirname(os.path.abspath(__file__)), "specs") amqp_spec = os.path.join(AMQP_SPEC_DIR, "amqp.0-10-qpid-errata.xml") amqp_spec_0_8 = os.path.join(AMQP_SPEC_DIR, "amqp.0-8.xml") amqp_spec_0_9 = os.path.join(AMQP_SPEC_DIR, "amqp.0-9.xml") diff --git a/qpid/python/qpid/tests/codec.py b/qpid/python/qpid/tests/codec.py index 9b51b4713c..8fd0528636 100644 --- a/qpid/python/qpid/tests/codec.py +++ b/qpid/python/qpid/tests/codec.py @@ -20,7 +20,7 @@ import unittest from qpid.codec import Codec -from qpid.spec import load +from qpid.spec08 import load from cStringIO import StringIO from qpid.reference import ReferenceId @@ -53,7 +53,7 @@ __doc__ = """ """ -from qpid_config import amqp_spec_0_8 +from qpid.specs_config import amqp_spec_0_8 SPEC = load(amqp_spec_0_8) # -------------------------------------- diff --git a/qpid/python/setup.py b/qpid/python/setup.py index af01d7646c..445ba704e5 100644..100755 --- a/qpid/python/setup.py +++ b/qpid/python/setup.py @@ -20,8 +20,7 @@ import os, re, sys from distutils.core import setup, Command from distutils.command.build_py import build_py as _build_py -from distutils.command.install import install as _install -from distutils.command.install_lib import install_lib +from distutils.command.install_lib import install_lib as _install_lib from distutils.dep_util import newer from distutils.errors import DistutilsFileError from distutils import log @@ -136,68 +135,39 @@ class build_py(preprocessor, _build_py): else: return None, None -options = [('amqp-spec-dir=', None, "location of the AMQP specifications")] - -class install(_install): - - user_options = _install.user_options + options - - def initialize_options(self): - _install.initialize_options(self) - self.amqp_spec_dir = None - - def get_sub_commands(self): - return ['qpid_config'] + _install.get_sub_commands(self) - -class qpid_config(preprocessor, install_lib): - - user_options = options - - def initialize_options(self): - install_lib.initialize_options(self) - self.prefix = None - self.amqp_spec_dir = None - - def finalize_options(self): - install_lib.finalize_options(self) - self.set_undefined_options('install', - ('prefix', 'prefix'), - ('amqp_spec_dir', 'amqp_spec_dir')) - if self.amqp_spec_dir is None: - self.amqp_spec_dir = "%s/share/amqp" % self.prefix +class install_lib(_install_lib): def get_outputs(self): - return [os.path.join(self.install_dir, "qpid_config.py"), - os.path.join(self.install_dir, "qpid_config.pyc")] + outputs = _install_lib.get_outputs(self) + extra = [] + for of in outputs: + if os.path.basename(of) == "amqp.0-10-qpid-errata.xml": + extra.append("%s.ops.pcl" % of) + return outputs + extra def install(self): - self.mkpath(self.install_dir) - file, _ = self.copy_file("qpid_config.py", self.install_dir) - return [file] - - def configure(self, input): - idx = input.index("AMQP_SPEC_DIR") - end = input.index(os.linesep, idx) - return input[:idx] + \ - ('AMQP_SPEC_DIR="%s"' % self.amqp_spec_dir) + \ - input[end:] - - def actor(self, src, dst): - file = os.path.basename(src) - if file == "qpid_config.py": - return "configuring", self.configure - else: - return None, None + outfiles = _install_lib.install(self) + extra = [] + for of in outfiles: + if os.path.basename(of) == "amqp.0-10-qpid-errata.xml": + tgt = "%s.ops.pcl" % of + if self.force or newer(of, tgt): + log.info("preloading %s to %s" % (of, os.path.basename(tgt))) + if not self.dry_run: + from qpid.ops import load_types + load_types(of) + extra.append(tgt) + return outfiles + extra setup(name="qpid-python", version="0.7", author="Apache Qpid", author_email="dev@qpid.apache.org", packages=["mllib", "qpid", "qpid.tests"], + package_data={"qpid": ["specs/*.dtd", "specs/*.xml"]}, scripts=["qpid-python-test"], url="http://qpid.apache.org/", license="Apache Software License", description="Python client implementation for Apache Qpid", cmdclass={"build_py": build_py, - "install": install, - "qpid_config": qpid_config}) + "install_lib": install_lib}) |