diff options
Diffstat (limited to 'qpid/specs/amqp.0-9.xml')
-rw-r--r-- | qpid/specs/amqp.0-9.xml | 5248 |
1 files changed, 5248 insertions, 0 deletions
diff --git a/qpid/specs/amqp.0-9.xml b/qpid/specs/amqp.0-9.xml new file mode 100644 index 0000000000..73cace7015 --- /dev/null +++ b/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> |