blob: a4f863c911ea94b66fa2a109baebe935e7355788 [file] [log] [blame]
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="amqp.xsl"?>
<!--
Copyright Notice
================
(c) Copyright Bank of America, N.A., Barclays Bank PLC, Cisco Systems, Credit Suisse, Deutsche
Boerse, Envoy Technologies Inc., Goldman Sachs, HCL Technologies Ltd, IIT Software GmbH, iMatix
Corporation, INETCO Systems Limited, Informatica Corporation, JPMorgan Chase & Co., Kaazing
Corporation, N.A, Microsoft Corporation, my-Channels, Novell, Progress Software, Red Hat Inc.,
Software AG, Solace Systems Inc., StormMQ Ltd., Tervela Inc., TWIST Process Innovations Ltd,
VMware, Inc., and WS02 Inc.
2006-2011. All rights reserved.
License
=======
Bank of America, N.A., Barclays Bank PLC, Cisco Systems, Credit Suisse, Deutsche Boerse, Goldman
Sachs, HCL Technologies Ltd, IIT Software GmbH, INETCO Systems Limited, Informatica Corporation,
JPMorgan Chase & Co., Kaazing Corporation, N.A, Microsoft Corporation, my-Channels, Novell,
Progress Software, Red Hat Inc., Software AG, Solace Systems Inc., StormMQ Ltd., Tervela Inc.,
TWIST Process Innovations Ltd, VMware, Inc., and WS02 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 Message Queuing Protocol ("AMQP")
Specification and (ii) the Licensed Claims that are held by the Authors, all for the purpose of
implementing the Advanced Message Queuing 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 Message Queuing Protocol Specification
against any Author. Upon termination, you shall destroy all copies of the Advanced Message Queuing
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 Message Queuing 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
Message Queuing 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 Message Queuing
Protocol Specification that are not required by the Advanced Message Queuing 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 Message Queuing 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 Message Queuing
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 Message Queuing Protocol
Specification. For purposes of this definition, the Advanced Message Queuing 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 Message Queuing 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 Message Queuing Protocol Specification.
The following disclaimers, which you hereby also acknowledge as to any use you may make of the
Advanced Message Queuing Protocol Specification:
THE ADVANCED MESSAGE QUEUING 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 MESSAGE QUEUING PROTOCOL SPECIFICATION ARE SUITABLE FOR ANY PURPOSE; NOR THAT THE
IMPLEMENTATION OF THE ADVANCED MESSAGE QUEUING 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
MESSAGE QUEUING PROTOCOL SPECIFICATION.
The name and trademarks of the Authors may NOT be used in any manner, including advertising or
publicity pertaining to the Advanced Message Queuing Protocol Specification or its contents
without specific, written prior permission. Title to copyright in the Advanced Message Queuing
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 Message Queuing 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.
RED HAT is a registered trademarks of Red Hat, Inc. in the US and other countries.
Other company, product, or service names may be trademarks or service marks of others.
Link to full AMQP specification:
=================================
http://www.amqp.org/confluence/display/AMQP/AMQP+Specification
-->
<!DOCTYPE amqp SYSTEM "amqp.dtd">
<amqp xmlns="http://www.amqp.org/schema/amqp.xsd"
name="transport" label="working version">
<!-- == Section: transport =================================================================== -->
<section name="transport" label="transport overview">
<doc>
<p>
The AMQP Network consists of <term>Nodes</term> connected via <term>Links</term>. Nodes are
named entities responsible for the safe storage and/or delivery of <term>Messages</term>.
Messages can originate from, terminate at, or be relayed by Nodes.
</p>
<p>
A Link is a unidirectional route between two Nodes. Links attach to a Node at
a <term>Terminus</term>. There are two kinds of Terminus: <term>Sources</term>
and <term>Targets</term>. A Terminus is responsible for tracking the state of a particular
stream of incoming or outgoing messages. Sources track outgoing messages and Targets track
incoming messages. Messages may only travel along a Link if they meet the entry criteria at
the Source.
</p>
<p>
As a Message travels through the AMQP network, the responsibility for safe storage and
delivery of the Message is transferred between the Nodes it encounters. The Link Protocol
(defined in <xref name="links"/> ) manages the transfer of responsibility between the Source
and Target.
</p>
<picture>
<![CDATA[
+------------+ +------------+
/ Node A \ / Node B \
+----------------+ +--filter +----------------+
| | / | |
| MSG_3 <MSG_1> | _/ _ | MSG_1 |
| |(_)------------------>(_)| |
| <MSG_2> MSG_4 | | | | MSG_2 |
| | | Link(Src,Tgt) | | |
+----------------+ | | +----------------+
| |
Src Tgt
Key: <MSG_n> = old location of MSG_n
]]>
</picture>
<p>
Nodes exist within a <term>Container</term>, and each Container may hold many Nodes.
Examples of AMQP Nodes are Producers, Consumers, and Queues. Producers and Consumers are the
elements within a client Application that generate and process Messages. Queues are entities
within a Broker that store and forward Messages. Examples of containers are Brokers and
Client Applications.
</p>
<picture>
<![CDATA[
+---------------+ +----------+
| <<Container>> | 1..1 0..n | <<Node>> |
|---------------|<>-------------------->|----------|
| container-id | | name |
+---------------+ +----------+
/_\ /_\
| |
| |
+-----+-----+ +----------+----------+
| | | | |
| | | | |
+--------+ +--------+ +----------+ +----------+ +-------+
| Broker | | Client | | Producer | | Consumer | | Queue |
|--------| |--------| |----------| |----------| |-------|
| | | | | | | | | |
+--------+ +--------+ +----------+ +----------+ +-------+
]]>
</picture>
<p>
The AMQP Transport Specification defines a peer-to-peer protocol for transferring Messages
between Nodes in the AMQP network. This portion of the specification is not concerned with
the internal workings of any sort of Node, and only deals with the mechanics of
unambiguously transferring a Message from one Node to another.
</p>
<p>
Containers communicate via <term>Connections</term>. An AMQP Connection consists of a
full-duplex, reliably ordered sequence of <term>Frames</term>. The precise requirement for a
Connection is that if the n<sup>th</sup> Frame arrives, all Frames prior to n MUST also have
arrived. It is assumed Connections are transient and may fail for a variety of reasons
resulting in the loss of an unknown number of frames, but they are still subject to the
aforementioned ordered reliability criteria. This is similar to the guarantee that TCP or
SCTP provides for byte streams, and the specification defines a framing system used to parse
a byte stream into a sequence of Frames for use in establishing an AMQP Connection (see
<xref name="framing"/>).
</p>
<p>
An AMQP Connection is divided into a negotiated number of independent unidirectional
<term>Channels</term>. Each Frame is marked with the Channel number indicating its parent
Channel, and the Frame sequence for each Channel is multiplexed into a single Frame sequence
for the Connection.
</p>
<p>
An AMQP <term>Session</term> correlates two unidirectional Channels to form a bidirectional,
sequential conversation between two Containers. A single Connection may have multiple
independent Sessions active simultaneously, up to the negotiated Channel limit. Both
Connections and Sessions are modeled by each peer as <term>endpoints</term> that store local
and last known remote state regarding the Connection or Session in question.
</p>
<picture title="Session &amp; Connection Endpoints">
<![CDATA[
Session<------+ +------>Session
(ICH=1, OCH=1) | | (ICH=1, OCH=1)
\|/ \|/
Session<--> Connection <---------> Connection <-->Session
(ICH=2, OCH=3) /|\ /|\ (ICH=3, OCH=2)
| |
Session<------+ +------>Session
(ICH=3, OCH=2) (ICH=2, OCH=3)
Key: ICH -> Input Channel, OCH -> Output Channel
]]>
</picture>
<p>
Sessions provide the context for communication between Sources and Targets. A <term>Link
Endpoint</term> associates a Terminus with a <term>Session Endpoint</term>. Within a
Session, the Link Protocol (defined in <xref name="links"/>) is used to establish Links
between Sources and Targets and to transfer Messages across them. A single Session may be
simultaneously associated with any number of Links.
</p>
<picture><![CDATA[
+-------------+
| Link | Message Transport
+-------------+ (Node to Node)
| name |
| source |
| target |
| timeout |
+-------------+
/|\ 0..n
|
|
|
\|/ 0..1
+------------+
| Session | Frame Transport
+------------+ (Container to Container)
| name |
+------------+
/|\ 0..n
|
|
|
\|/ 1..1
+------------+
| Connection | Frame Transport
+------------+ (Container to Container)
| principal |
+------------+
]]>
</picture>
<p>
A Frame is the unit of work carried on the wire. Connections have a negotiated maximum frame
size allowing byte streams to be easily defragmented into complete frame bodies representing
the independently parsable units formally defined in <xref name="performatives"/>. The
following table lists all frame bodies and defines which endpoints handle them.
</p>
<picture><![CDATA[
Frame Connection Session Link
========================================
open H
begin I H
attach I H
flow I H
transfer I H
disposition I H
detach I H
end I H
close H
----------------------------------------
Key:
H: handled by the endpoint
I: intercepted (endpoint examines
the frame, but delegates
further processing to another
endpoint)
]]>
</picture>
</doc>
</section>
<section name="version-negotiation" title="Version Negotiation"
label="definition of version negotiation steps">
<doc >
<p>
Prior to sending any Frames on a Connection, each peer MUST start by sending a protocol
header that indicates the protocol version used on the Connection. The protocol header
consists of the upper case ASCII letters "AMQP" followed by a protocol id of zero, followed
by three unsigned bytes representing the major, minor, and revision of the protocol version
(currently <xref name="MAJOR"/>, <xref name="MINOR"/>, <xref name="REVISION"/>). In total
this is an 8-octet sequence:
</p>
<picture><![CDATA[
4 OCTETS 1 OCTET 1 OCTET 1 OCTET 1 OCTET
+----------+---------+---------+---------+----------+
| "AMQP" | %d0 | major | minor | revision |
+----------+---------+---------+---------+----------+
]]>
</picture>
<p>
Any data appearing beyond the protocol header MUST match the version indicated by the
protocol header. If the incoming and outgoing protocol headers do not match, both peers MUST
close their outgoing stream and SHOULD read the incoming stream until it is terminated.
</p>
<p>
The AMQP peer which acted in the role of the TCP client (i.e. the peer that opened the
Connection) MUST immediately send its outgoing protocol header on establishment of the TCP
Session. The AMQP peer which acted in the role of the TCP server MAY elect to wait until
receiving the incoming protocol header before sending its own outgoing protocol header.
</p>
<p>
Two AMQP peers agree on a protocol version as follows (where the words "client" and
"server" refer to the roles being played by the peers at the TCP Connection level):
</p>
<ul>
<li>
<p>
When the client opens a new socket Connection to a server, it MUST send a protocol
header with the client's preferred protocol version.
</p>
</li>
<li>
<p>
If the requested protocol version is supported, the server MUST send its own protocol
header with the requested version to the socket, and then proceed according to the
protocol definition.
</p>
</li>
<li>
<p>
If the requested protocol version is <b>not</b> supported, the server MUST send a
protocol header with a <b>supported</b> protocol version and then close the socket.
</p>
</li>
<li>
<p>
When choosing a protocol version to respond with, the server SHOULD choose the highest
supported version that is less than or equal to the requested version. If no such
version exists, the server SHOULD respond with the highest supported version.
</p>
</li>
<li>
<p>
If the server can't parse the protocol header, the server MUST send a valid protocol
header with a supported protocol version and then close the socket.
</p>
</li>
</ul>
<p>
Based on this behavior a client can discover which protocol versions a server supports by
attempting to connect with its highest supported version and reconnecting with a version
less than or equal to the version received back from the server.
</p>
<picture title="Version Negotiation Examples"><![CDATA[
TCP Client TCP Server
======================================================
AMQP%d0.1.0.0 ------------->
<------------- AMQP%d0.1.0.0 (1)
... *proceed*
AMQP%d0.1.1.0 ------------->
<------------- AMQP%d0.1.0.0 (2)
*TCP CLOSE*
HTTP ------------->
<------------- AMQP%d0.1.0.0 (3)
*TCP CLOSE*
------------------------------------------------------
(1) Server accepts Connection for: AMQP, protocol=0,
major=1, minor=0, revision=0
(2) Server rejects Connection for: AMQP, protocol=0,
major=1, minor=1, revision=0, Server responds
that it supports: AMQP, protocol=0, major=1,
minor=0, revision=0
(3) Server rejects Connection for: HTTP. Server
responds it supports: AMQP, protocol=0, major=1,
minor=0, revision=0
]]>
</picture>
<p>
Please note that the above examples use the literal notation defined in RFC 2234 for non
alphanumeric values.
</p>
<p>
The protocol id is not a part of the protocol version and thus the rule above regarding
the highest supported version does not apply. A client might request use of a protocol id
that is unacceptable to a server - for example, it might request a raw AMQP connection
when the server is configured to require a TLS or SASL security layer (See <xref
type="section" name="security-layers"/>). In this case, the server MUST send a protocol
header with an <b>acceptable</b> protocol id (and version) and then close the socket. It MAY
choose any protocol id.
</p>
<picture title="Protocol ID Rejection Example"><![CDATA[
TCP Client TCP Server
======================================================
AMQP%d0.1.0.0 ------------->
<------------- AMQP%d3.1.0.0
*TCP CLOSE*
------------------------------------------------------
Server rejects Connection for: AMQP, protocol=0,
major=1, minor=0, revision=0, Server responds
that it requires: SASL security layer, protocol=3,
major=1, minor=0, revision=0
]]>
</picture>
</doc>
</section>
<section name="framing" label="frame layout and encoding">
<doc>
<p>
Frames are divided into three distinct areas: a fixed width frame header, a variable width
extended header, and a variable width frame body.
</p>
<picture><![CDATA[
required optional optional
+--------------+-----------------+------------+
| frame header | extended header | frame body |
+--------------+-----------------+------------+
8 bytes *variable* *variable*
]]>
</picture>
<dl>
<dt>frame header</dt>
<dd><p>The frame header is a fixed size (8 byte) structure that precedes each frame. The
frame header includes mandatory information required to parse the rest of the frame
including size and type information.</p></dd>
<dt>extended header</dt>
<dd><p>The extended header is a variable width area preceding the frame body. This is an
extension point defined for future expansion. The treatment of this area depends on the
frame type.</p></dd>
<dt>frame body</dt>
<dd><p>The frame body is a variable width sequence of bytes the format of which depends on
the frame type.</p></dd>
</dl>
</doc>
<doc title="Frame Layout">
<p>
The diagram below shows the details of the general frame layout for all frame types.
</p>
<picture><![CDATA[
+0 +1 +2 +3
+-----------------------------------+ -.
0 | SIZE | |
+-----------------------------------+ |---> Frame Header
4 | DOFF | TYPE | <TYPE-SPECIFIC> | | (8 bytes)
+-----------------------------------+ -'
+-----------------------------------+ -.
8 | ... | |
. . |---> Extended Header
. <TYPE-SPECIFIC> . | (DOFF * 4 - 8) bytes
| ... | |
+-----------------------------------+ -'
+-----------------------------------+ -.
4*DOFF | | |
. . |
. . |
. . |
. <TYPE-SPECIFIC> . |---> Frame Body
. . | (SIZE - DOFF * 4) bytes
. . |
. . |
. ________| |
| ... | |
+--------------------------+ -'
]]>
</picture>
<dl>
<dt>SIZE</dt>
<dd><p>Bytes 0-3 of the frame header contain the frame size. This is an unsigned 32-bit
integer that MUST contain the total frame size of the frame header, extended header, and
frame body. The frame is malformed if the size is less than the size of the required
frame header (8 bytes).</p></dd>
<dt>DOFF</dt>
<dd><p>Byte 4 of the frame header is the data offset. This gives the position of the body
within the frame. The value of the data offset is unsigned 8-bit integer specifying a
count of 4 byte words. Due to the mandatory 8 byte frame header, the frame is malformed
if the value is less than 2.</p></dd>
<dt>TYPE</dt>
<dd><p>Byte 5 of the frame header is a type code. The type code indicates the format and
purpose of the frame. The subsequent bytes in the frame header may be interpreted
differently depending on the type of the frame. A type code of 0x00 indicates that the
frame is an AMQP frame. (A type code of 0x01 indicates that the frame is a SASL frame,
see <xref type="section" name="sasl"/>).
</p></dd>
</dl>
</doc>
<doc title="AMQP Frames">
<p>
Bytes 6 and 7 of an AMQP Frame contain the Channel number (see <xref name="transport"/>).
The frame body is defined as a <i>performative</i> followed by an opaque <i>payload</i>. The
performative MUST be one of those defined in <xref name="performatives"/> and is encoded as
a described type in the AMQP type system. The remaining bytes in the frame body form the
payload for that frame. The presence and format of the payload is defined by the semantics
of the given performative.
</p>
<picture><![CDATA[
type: 0x00 - AMQP frame
+0 +1 +2 +3
+-----------------------------------+ -.
0 | SIZE | |
+-----------------------------------+ |---> Frame Header
4 | DOFF | TYPE | CHANNEL | | (8 bytes)
+-----------------------------------+ -'
+-----------------------------------+ -.
8 | ... | |
. . |---> Extended Header
. <IGNORED> . | (DOFF * 4 - 8) bytes
| ... | |
+-----------------------------------+ -'
+-----------------------------------+ -.
4*DOFF | PERFORMATIVE: | |
. Open / Begin / Attach . |
. Flow / Transfer / Disposition . |
. Detach / End / Close . |
|-----------------------------------| |
. . |---> Frame Body
. . | (SIZE - DOFF * 4) bytes
. PAYLOAD . |
. . |
. ________| |
| ... | |
+--------------------------+ -'
]]>
</picture>
<p>
An AMQP frame with no body may be used to generate artificial traffic as needed to
satisfy any negotiated idle time-out interval. See <xref name="doc-idle-time-out"/>.
</p>
</doc>
</section>
<!-- == Section: connections ================================================================= -->
<section name="connections" label="connection life-cycle">
<doc>
<p>
AMQP Connections are divided into a number of unidirectional Channels. A Connection Endpoint
contains two kinds of Channel endpoints: incoming and outgoing. A Connection Endpoint maps
incoming Frames other than <xref name="open"/> and <xref name="close"/> to an incoming
Channel endpoint based on the incoming Channel number, as well as relaying Frames produced
by outgoing Channel endpoints, marking them with the associated outgoing Channel number
before sending them.
</p>
<p>
This requires Connection endpoints to contain two mappings. One from incoming Channel number
to incoming Channel endpoint, and one from outgoing Channel endpoint, to outgoing Channel
number.
</p>
<picture><![CDATA[
+-------OCHE X: 1
|
+-------OCHE Y: 7
|
<=== Frame[CH=1], Frame[CH=7] <===+
===> Frame[CH=0], Frame[CH=1] ===>+
|
+------>0: ICHE A
|
+------>1: ICHE B
OCHE: Outgoing Channel Endpoint
ICHE: Incoming Channel Endpoint
]]>
</picture>
<p>
Channels are unidirectional, and thus at each Connection endpoint the incoming and outgoing
Channels are completely distinct. Channel numbers are scoped relative to direction, thus
there is no causal relation between incoming and outgoing Channels that happen to be
identified by the "same" number. This means that if a bidirectional endpoint is constructed
from an incoming Channel endpoint and an outgoing Channel endpoint, the Channel number used
for incoming Frames is not necessarily the same as the Channel number used for outgoing
Frames.
</p>
<picture><![CDATA[
+-------BIDI/O: 7
|
<=== Frame[CH=1], Frame[CH=7] <===+
===> Frame[CH=0], Frame[CH=1] ===>+
|
+------>1: BIDI/I
BIDI/I: Incoming half of a single bidirectional endpoint
BIDI/O: Outgoing half of a single bidirectional endpoint
]]>
</picture>
<p>
Although not strictly directed at the Connection endpoint, the <xref name="begin"/> and
<xref name="end"/> Frames may be useful for the Connection endpoint to intercept as these
Frames are how Sessions mark the beginning and ending of communication on a given Channel
(see <xref name="sessions"/>).
</p>
</doc>
<doc title="Opening a Connection">
<p>
Each AMQP Connection begins with an exchange of capabilities and limitations, including the
maximum frame size. Prior to any explicit negotiation, the maximum frame size is
<xref name="MIN-MAX-FRAME-SIZE"/> and the maximum channel number is 0. After establishing
or accepting a TCP Connection and sending the protocol header, each peer must send an
<xref type="type" name="open"/> frame before sending any other Frames. The
<xref type="type" name="open"/> frame describes the capabilities and limits of that peer.
The <xref type="type" name="open"/> frame can only be sent on channel 0. After sending the
<xref type="type" name="open"/> frame each peer must read its partner's
<xref type="type" name="open"/> frame and must operate within mutually acceptable
limitations from this point forward.
</p>
<picture><![CDATA[
TCP Client TCP Server
==================================
TCP-CONNECT TCP-ACCEPT
PROTO-HDR PROTO-HDR
OPEN ---+ +--- OPEN
\ /
wait x wait
/ \
proceed <--+ +--> proceed
...
]]>
</picture>
</doc>
<doc title="Pipelined Open">
<p>
For applications that use many short-lived Connections, it may be desirable to pipeline the
Connection negotiation process. A peer may do this by starting to send subsequent frames
before receiving the partner's Connection header or <xref type="type" name="open"/> frame.
This is permitted so long as the pipelined frames are known a priori to conform to the
capabilities and limitations of its partner. For example, this may be accomplished by
keeping the use of the Connection within the capabilities and limits expected of all AMQP
implementations as defined by the specification of the <xref type="type" name="open"/>
frame.
</p>
<picture><![CDATA[
TCP Client TCP Server
=============================================
TCP-CONNECT TCP-ACCEPT
PROTO-HDR PROTO-HDR
OPEN ---+ +--- OPEN
\ /
pipelined frame x pipelined frame
/ \
proceed <--+ +--> proceed
...
---------------------------------------------
]]>
</picture>
<p>
The use of pipelined frames by a peer cannot be distinguished by the peer's partner from
non-pipelined use so long as the pipelined frames conform to the partner's capabilities and
limitations.
</p>
</doc>
<doc title="Closing a Connection">
<p>
Prior to closing a Connection, each peer MUST write a <xref type="type" name="close"/> frame
with a code indicating the reason for closing. This frame MUST be the last thing ever
written onto a Connection. After writing this frame the peer SHOULD continue to read from
the Connection until it receives the partner's <xref type="type" name="close"/> frame (in
order to guard against erroneously or maliciously implemented partners, a peer SHOULD
implement a timeout to give its partner a reasonable time to receive and process the close
before giving up and simply closing the underlying transport mechanism). A <xref type="type"
name="close"/> frame may be received on any channel up to the maximum channel number
negotiated in open. However, implementations SHOULD send it on channel 0, and MUST send it
on channel 0 if pipelined in a single batch with the corresponding <xref name="open"/>.
</p>
<picture><![CDATA[
TCP Client TCP Server
=============================
...
CLOSE ------->
+-- CLOSE
/ TCP-CLOSE
TCP-CLOSE <--+
]]>
</picture>
<p>
Implementations SHOULD NOT expect to be able to reuse open TCP sockets after <xref
type="type" name="close"/> performatives have been exchanged. There is no requirement for an
implementation to read from a socket after a <xref type="type" name="close"/> performative
has been received.
</p>
</doc>
<doc title="Simultaneous Close">
<p>
Normally one peer will initiate the Connection close, and the partner will send its close in
response. However, because both endpoints may simultaneously choose to close the Connection
for independent reasons, it is possible for a simultaneous close to occur. In this case, the
only potentially observable difference from the perspective of each endpoint is the code
indicating the reason for the close.
</p>
<picture><![CDATA[
TCP Client TCP Server
================================
...
CLOSE ---+ +--- CLOSE
\ /
x
/ \
TCP-CLOSE <--+ +--> TCP-CLOSE
]]>
</picture>
</doc>
<doc name="doc-idle-time-out" title="Idle Time-out of a Connection">
<p>
Connections are subject to an idle time-out threshold. The time-out is triggered by a local
peer when no frames are received after a threshold value is exceeded. The idle time-out is
measured in milliseconds, and starts from the time the last frame is received. If the
threshold is exceeded, then a peer should try to gracefully close the connection using a
<xref type="type" name="close"/> frame with an error explaining why. If the remote peer does
not respond gracefully within a threshold to this, then the peer may close the TCP socket.
</p>
<p>
Each peer has its own (independent) idle time-out. At Connection open each peer communicates
the maximum period between activity (frames) on the connection that it desires from its
partner. The <xref type="type" name="open"/> frame carries the idle-time-out field for this
purpose. To avoid spurious time-outs, the value in idle-time-out should be half the peer's
actual timeout threshold.
</p>
<p>
If a peer can not, for any reason support a proposed idle time-out, then it should close
the connection using a <xref type="type" name="close"/> frame with an error explaining why.
There is no requirement for peers to support arbitrarily short or long idle time-outs.
</p>
<p>
The use of idle time-outs is any addition to any network protocol level control.
Implementations should make use of TCP keep-alive wherever possible in order to be good
citizens.
</p>
<p>
If a peer needs to satisfy the need to send traffic to prevent idle time-out, and has
nothing to send, it may send an empty frame, i.e. a frame consisting solely of a frame
header, with no frame body. This frame's channel can be any valid channel up to channel-max,
but is otherwise to be ignored. Implementations SHOULD use channel 0 for empty frames, and
MUST use channel 0 if channel-max has not yet been negotiated (i.e. before an
<xref name="open"/> frame has been received). Apart from this use, empty frames have no
meaning.
</p>
<p>
Empty frames can only be sent after the <xref type="type" name="open"/> frame is sent.
As they are a frame, they should not be sent after the <xref type="type" name="close"/>
frame has been sent.
</p>
<p>
As an alternative to using an empty frame to prevent an idle time-out, if a connection
is in a permissible state, an implementation MAY choose to send a flow frame for a valid
session.
</p>
<p>
If during operation a peer exceeds the remote peer's idle time-out's threshold, e.g.
because it is heavily loaded, it SHOULD gracefully close the connection by using a
<xref type="type" name="close"/> frame with an error explaining why.
</p>
</doc>
<doc title="Connection States">
<dl>
<dt>START</dt>
<dd><p>In this state a Connection exists, but nothing has been sent or received. This is the
state an implementation would be in immediately after performing a socket connect or
socket accept.</p></dd>
<dt>HDR_RCVD</dt>
<dd><p>In this state the Connection header has been received from our peer, but we have not
yet sent anything.</p></dd>
<dt>HDR_SENT</dt>
<dd><p>In this state the Connection header has been sent to our peer, but we have not yet
received anything.</p></dd>
<dt>OPEN_PIPE</dt>
<dd><p>In this state we have sent both the Connection header and the <xref type="type"
name="open"/> frame, but we have not yet received anything.
</p></dd>
<dt>OC_PIPE</dt>
<dd><p>In this state we have sent the Connection header, the <xref type="type" name="open"/>
frame, any pipelined Connection traffic, and the <xref type="type" name="close"/> frame,
but we have not yet received anything.</p></dd>
<dt>OPEN_RCVD</dt>
<dd><p>In this state we have sent and received the Connection header, and received an
<xref type="type" name="open"/> frame from our peer, but have not yet sent an
<xref type="type" name="open"/> frame.</p></dd>
<dt>OPEN_SENT</dt>
<dd><p>In this state we have sent and received the Connection header, and sent an
<xref type="type" name="open"/> frame to our peer, but have not yet received an
<xref type="type" name="open"/> frame.</p></dd>
<dt>CLOSE_PIPE</dt>
<dd><p>In this state we have send and received the Connection header, sent an
<xref type="type" name="open"/> frame, any pipelined Connection traffic, and the
<xref type="type" name="close"/> frame, but we have not yet received an
<xref type="type" name="open"/> frame.</p></dd>
<dt>OPENED</dt>
<dd><p>In this state the Connection header and the <xref type="type" name="open"/> frame
have both been sent and received.</p></dd>
<dt>CLOSE_RCVD</dt>
<dd><p>In this state we have received a <xref type="type" name="close"/> frame indicating
that our partner has initiated a close. This means we will never have to read anything
more from this Connection, however we can continue to write frames onto the Connection.
If desired, an implementation could do a TCP half-close at this point to shutdown the
read side of the Connection.</p></dd>
<dt>CLOSE_SENT</dt>
<dd><p>In this state we have sent a <xref type="type" name="close"/> frame to our partner.
It is illegal to write anything more onto the Connection, however there may still be
incoming frames. If desired, an implementation could do a TCP half-close at this point
to shutdown the write side of the Connection.</p></dd>
<dt>DISCARDING</dt>
<dd><p>The DISCARDING state is a variant of the CLOSE_SENT state where the
<xref name="close"/> is triggered by an error. In this case any incoming frames on
the connection MUST be silently discarded until the peer's <xref name="close"/> frame
is received.</p></dd>
<dt>END</dt>
<dd><p>In this state it is illegal for either endpoint to write anything more onto the
Connection. The Connection may be safely closed and discarded.</p></dd>
</dl>
</doc>
<doc title="Connection State Diagram">
<p>
The graph below depicts a complete state diagram for each endpoint. The boxes represent
states, and the arrows represent state transitions. Each arrow is labeled with the action
that triggers that particular transition.
</p>
<picture><![CDATA[
R:HDR @=======@ S:HDR R:HDR[!=S:HDR]
+--------| START |-----+ +--------------------------------+
| @=======@ | | |
\|/ \|/ | |
@==========@ @==========@ S:OPEN |
+----| HDR_RCVD | | HDR_SENT |------+ |
| @==========@ @==========@ | R:HDR[!=S:HDR] |
| S:HDR | | R:HDR | +-----------------+
| +--------+ +------+ | | |
| \|/ \|/ \|/ | |
| @==========@ +-----------+ S:CLOSE |
| | HDR_EXCH | | OPEN_PIPE |----+ |
| @==========@ +-----------+ | |
| R:OPEN | | S:OPEN | R:HDR | |
| +--------+ +------+ +-------+ | |
| \|/ \|/ \|/ \|/ |
| @===========@ @===========@ S:CLOSE +---------+ |
| | OPEN_RCVD | | OPEN_SENT |-----+ | OC_PIPE |--+
| @===========@ @===========@ | +---------+ |
| S:OPEN | | R:OPEN \|/ | R:HDR |
| | @========@ | +------------+ | |
| +------>| OPENED |<----+ | CLOSE_PIPE |<--+ |
| @========@ +------------+ |
| R:CLOSE | | S:CLOSE | R:OPEN |
| +---------+ +-------+ | |
| \|/ \|/ | |
| @============@ @=============@ | |
| | CLOSE_RCVD | | CLOSE_SENT* |<----+ |
| @============@ @=============@ |
| S:CLOSE | | R:CLOSE |
| | @=====@ | |
| +-------->| END |<-----+ |
| @=====@ |
| /|\ |
| S:HDR[!=R:HDR] | R:HDR[!=S:HDR] |
+----------------------+-----------------------------------------------+
R:<CTRL> = Received <CTRL>
S:<CTRL> = Sent <CTRL>
* Also could be DISCARDING if an error condition
triggered the CLOSE
]]>
</picture>
<picture><![CDATA[
State Legal Sends Legal Receives Legal Connection Actions
=======================================================================
START HDR HDR
HDR_RCVD HDR OPEN
HDR_SENT OPEN HDR
HDR_EXCH OPEN OPEN
OPEN_RCVD OPEN *
OPEN_SENT ** OPEN
OPEN_PIPE ** HDR
CLOSE_PIPE - OPEN TCP Close for Write
OC_PIPE - HDR TCP Close for Write
OPENED * *
CLOSE_RCVD * - TCP Close for Read
CLOSE_SENT - * TCP Close for Write
DISCARDING - * TCP Close for Write
END - - TCP Close
* = any frames
- = no frames
** = any frame known a priori to conform to the
peer's capabilities and limitations
]]>
</picture>
</doc>
</section>
<!-- == Section: sessions ==================================================================== -->
<section name="sessions" label="context for active link communication">
<doc>
<p>
A Session is a bidirectional sequential conversation between two containers that provides a
grouping for related links. Sessions serve as the context for link communication. Any number
of links of any directionality can be <i>attached</i> to a given Session. However, a link
may be attached to at most one Session at a time.
</p>
<picture>
<![CDATA[
Link A-------+ +------>Link A
| |
\|/ (attached) |
Link B<--- Session <--------------> Session <---Link B
Link C------>* (detached) *------>Link C
]]>
</picture>
<p>
Messages transferred on a link are sequentially identified within the Session. A session may
be viewed as multiplexing link traffic, much like a connection multiplexes session traffic.
However, unlike the sessions on a connection, links on a session are not entirely
independent since they share a common delivery sequence scoped to the session. This common
sequence allows endpoints to efficiently refer to sets of deliveries regardless of the
originating link. This is of particular benefit when a single application is receiving
messages along a large number of different links. In this case the session
provides <i>aggregation</i> of otherwise independent links into a single stream that can be
efficiently acknowledged by the receiving application.
</p>
</doc>
<doc title="Establishing a Session">
<p>
Sessions are established by creating a Session Endpoint, assigning it to an unused channel
number, and sending a <xref type="type" name="begin"/> announcing the association of the
Session Endpoint with the outgoing channel. Upon receiving the <xref type="type"
name="begin"/> the partner will check the remote-channel field and find it empty. This
indicates that the begin is referring to remotely initiated Session. The partner will
therefore allocate an unused outgoing channel for the remotely initiated Session and
indicate this by sending its own <xref type="type" name="begin"/> setting the
remote-channel field to the incoming channel of the remotely initiated Session.
</p>
<p>
To make it easier to monitor AMQP sessions, it is recommended that implementations always
assign the lowest available unused channel number.
</p>
<p>
The remote-channel field of a <xref type="type" name="begin"/> frame MUST be empty for a
locally initiated Session, and MUST be set when announcing the endpoint created as a result
of a remotely initiated Session.
</p>
<picture><![CDATA[
Endpoint Endpoint
=====================================================================
[CH3] BEGIN(name=..., --------->
remote-channel=null)
+-- [CH7] BEGIN(name=...,
/ remote-channel=3)
/
<---+
...
---------------------------------------------------------------------
]]>
</picture>
</doc>
<doc title="Ending a Session">
<p>
Sessions end automatically when the Connection is closed or interrupted. Sessions are
explicitly ended when either endpoint chooses to end the Session. When a Session is
explicitly ended, an <xref type="type" name="end"/> frame is sent to announce the
disassociation of the endpoint from its outgoing channel, and to carry error information
when relevant.
</p>
<picture><![CDATA[
Endpoint A Endpoint B
====================================================================
...
[CH3] END(error=...) ---------> (1)
+-- [CH7] END(error=...)
/
/
(2) <---+
...
--------------------------------------------------------------------
(1) At this point the session endpoint is disassociated from
the outgoing channel on A, and the incoming channel on B.
(2) At this point the session endpoint is disassociated from
the outgoing channel on B, and the incoming channel on A.
]]>
</picture>
</doc>
<doc title="Simultaneous End">
<p>
Due to the potentially asynchronous nature of Sessions, it is possible that both peers may
simultaneously decide to end a Session. If this should happen, it will appear to each peer
as though their partner's spontaneously initiated <xref type="type" name="end"/> frame is
actually an answer to the peers initial <xref type="type" name="end"/> frame.
</p>
<picture><![CDATA[
Endpoint A Endpoint B
=================================================================
...
[CH3] END(error=...) --+ +-- [CH7] END(error=...)
(1) \ / (2)
x
/ \
(3) <-+ +-> (4)
...
-----------------------------------------------------------------
(1) At this point no more frames may be sent by A.
(2) At this point no more frames may be sent by B.
(3) At this point Endpoint A is fully ended.
(4) At this point Endpoint B is fully ended.
]]>
</picture>
</doc>
<doc title="Session Errors" >
<p>
When a Session is unable to process input, it MUST indicate this by issuing an END with an
appropriate <xref name="error"/> indicating the cause of the problem. It MUST then proceed
to discard all incoming frames from the remote endpoint until hearing the remote endpoint's
corresponding <xref name="end"/> frame.
</p>
<picture><![CDATA[
Endpoint Endpoint
================================================
FRAME 1 ---------->
FRAME 2 ---------->
FRAME 3 ---+ +--- END(error=...)
\ /
x
/ \
<--+ +--> *discarded*
END ---------->
...
================================================
]]>
</picture>
</doc>
<doc title="Session States">
<dl>
<dt>UNMAPPED</dt>
<dd><p>In the UNMAPPED state, the Session endpoint is not mapped to any incoming or outgoing
channels on the Connection endpoint. In this state an endpoint cannot send or receive
frames.</p></dd>
<dt>BEGIN_SENT</dt>
<dd><p>In the BEGIN_SENT state, the Session endpoint is assigned an outgoing channel number,
but there is no entry in the incoming channel map. In this state the endpoint may send
frames but cannot receive them.</p></dd>
<dt>BEGIN_RCVD</dt>
<dd><p>In the BEGIN_RCVD state, the Session endpoint has an entry in the incoming channel
map, but has not yet been assigned an outgoing channel number. The endpoint may receive
frames, but cannot send them.</p></dd>
<dt>MAPPED</dt>
<dd><p>In the MAPPED state, the Session endpoint has both an outgoing channel number and an
entry in the incoming channel map. The endpoint may both send and receive
frames.</p></dd>
<dt>END_SENT</dt>
<dd><p>In the END_SENT state, the Session endpoint has an entry in the incoming channel map,
but is no longer assigned an outgoing channel number. The endpoint may receive frames,
but cannot send them.</p></dd>
<dt>END_RCVD</dt>
<dd><p>In the END_RCVD state, the Session endpoint is assigned an outgoing channel number,
but there is no entry in the incoming channel map. The endpoint may send frames, but
cannot receive them.</p></dd>
<dt>DISCARDING</dt>
<dd><p>The DISCARDING state is a variant of the END_SENT state where the <xref name="end"/>
is triggered by an error. In this case any incoming frames on the session MUST be
silently discarded until the peer's <xref name="end"/> frame is received.</p></dd>
</dl>
<picture title="State Transitions"><![CDATA[
UNMAPPED<-------------------+
| |
+-------+-------+ |
S:BEGIN | | R:BEGIN |
| | |
\|/ \|/ |
BEGIN_SENT BEGIN_RCVD |
| | |
| | |
R:BEGIN | | S:BEGIN |
+-------+-------+ |
| |
\|/ |
MAPPED |
| |
+-------------+-------------+ |
S:END(error) | S:END | | R:END |
| | | |
\|/ \|/ \|/ |
DISCARDING END_SENT END_RCVD |
| | | |
| | | |
R:END | R:END | | S:END |
+-------------+-------------+ |
| |
| |
+------------------------+
]]>
</picture>
<p>
There is no obligation to retain a Session Endpoint when it is in the UNMAPPED state, i.e.
the UNMAPPED state is equivalent to a NONEXISTENT state.
</p>
</doc>
<doc name="session-flow-control" title="Session Flow Control">
<p>
The Session Endpoint assigns each outgoing <xref name="transfer"/> frame an implicit
<i>transfer-id</i> from a session scoped sequence. Each session endpoint maintains the
following state to manage incoming and outgoing <xref name="transfer"/> frames:
</p>
<dl>
<dt>next-incoming-id</dt>
<dd><p>The <i>next-incoming-id</i> identifies the implicit transfer-id of the next incoming
<xref name="transfer"/> frame.</p></dd>
<dt>incoming-window</dt>
<dd><p>The <i>incoming-window</i> defines the maximum number of incoming
<xref name="transfer"/> frames that the endpoint can currently receive. This identifies
a current maximum incoming transfer-id that can be computed by subtracting one from the
sum of <i>incoming-window</i> and <i>next-incoming-id</i>.</p></dd>
<dt>next-outgoing-id</dt>
<dd><p>The <i>next-outgoing-id</i> is used to assign a unique transfer-id to all
outgoing transfer frames on a given session. The <i>next-outgoing-id</i> may be
initialized to an arbitrary value and is incremented after each successive
<xref name="transfer"/> according to RFC-1982 serial number arithmetic.</p></dd>
<dt>outgoing-window</dt>
<dd><p>The <i>outgoing-window</i> defines the maximum number of outgoing
<xref name="transfer"/> frames that the endpoint can currently send. This identifies a
current maximum outgoing transfer-id that can be computed by subtracting one from the
sum of <i>outgoing-window</i> and <i>next-outgoing-id</i>.</p></dd>
<dt>remote-incoming-window</dt>
<dd><p>The <i>remote-incoming-window</i> reflects the maximum number of outgoing transfers
that can be sent without exceeding the remote endpoint's incoming-window. This value MUST
be decremented after every <xref name="transfer"/> frame is sent, and recomputed when
informed of the remote session endpoint state.</p></dd>
<dt>remote-outgoing-window</dt>
<dd><p>The <i>remote-outgoing-window</i> reflects the maximum number of incoming transfers
that may arrive without exceeding the remote endpoint's outgoing-window. This value MUST
be decremented after every incoming <xref name="transfer"/> frame is received, and
recomputed when informed fo the remote session endpoint state. When this window shrinks,
it is an indication of outstanding transfers. Settling outstanding transfers may cause the
window to grow.</p></dd>
</dl>
<p>
Once initialized, this state is updated by various events that occur in the lifespan of a
session and its associated links:
</p>
<dl>
<dt>sending a transfer</dt>
<dd><p>Upon sending a transfer, the sending endpoint will increment its next-outgoing-id,
decrement its remote-incoming-window, and may (depending on policy) decrement its
outgoing-window.</p></dd>
<dt>receiving a transfer</dt>
<dd><p>Upon receiving a transfer, the receiving endpoint will increment the next-incoming-id
to match the implicit transfer-id of the incoming transfer plus one, as well as
decrementing the remote-outgoing-window, and may (depending on policy) decrement its
incoming-window.</p></dd>
<dt>receiving a flow</dt>
<dd><p>When the endpoint receives a <xref name="flow"/> frame from its peer, it MUST update
the <i>next-incoming-id</i> directly from the <i>next-outgoing-id</i> of the frame, as
well as copy the <i>remote-outgoing-window</i> directly from the <i>outgoing-window</i>
of the frame.</p>
<p>
The <i>remote-incoming-window</i> is computed as follows:
</p>
<p>
<i>next-incoming-id<sub>flow</sub></i> + <i>incoming-window<sub>flow</sub></i>
- <i>next-outgoing-id<sub>endpoint</sub></i>
</p>
<p>
If the <i>next-incoming-id</i> field of the <xref name="flow"/> frame is not set,
then <i>remote-incoming-window</i> is computed as follows:
</p>
<p>
<i>initial-outgoing-id<sub>endpoint</sub></i> + <i>incoming-window<sub>flow</sub></i>
- <i>next-outgoing-id<sub>endpoint</sub></i>
</p>
</dd>
</dl>
</doc>
</section>
<!-- == Section: links ======================================================================= -->
<section name="links" label="link endpoints and the link protocol">
<doc>
<p>
A Link provides a unidirectional transport for Messages between a Source and a Target. The
primary responsibility of a Source or Target (a Terminus) is to maintain a record of the
status of each active delivery attempt until such a time as it is safe to forget. These are
referred to as <term>unsettled</term> deliveries. When a Terminus forgets the state
associated with a delivery-tag, it is considered <term>settled</term>. Each delivery attempt
is assigned a unique <term>delivery-tag</term> at the Source. The status of an active
delivery attempt is known as the <term>Delivery State</term> of the delivery.
</p>
<p>
Link Endpoints interface between a Terminus and a Session Endpoint, and maintain additional
state used for active communication between the local and remote endpoints. Link Endpoints
therefore come in two flavors: <term>Senders</term> and <term>Receivers</term>. When the
sending application submits a Message to the Sender for transport, it also supplies the
delivery-tag used by the Source to track the Delivery State. The Link Endpoint assigns each
Message a unique <term>delivery-id</term> from a Session scoped sequence. These delivery-ids
are used to efficiently reference subsets of the outstanding deliveries on a Session.
</p>
<p>
Termini may exist beyond their associated Link Endpoints, so it is possible for a Session to
terminate and the Termini to remain. A Link is said to be <term>suspended</term> if the
Termini exist, but have no associated Link Endpoints. The process of associating new Link
Endpoints with existing Termini and re-establishing communication is referred to
as <term>resuming</term> a Link.
</p>
<p>
The original Link Endpoint state is not necessary for resumption of a Link. Only the
unsettled Delivery State maintained at the Termini is necessary for link resume, and this
need not be stored directly. The form of delivery-tags is intentionally left open-ended so
that they and their related Delivery State can, if desired, be (re)constructed from
application state, thereby minimizing or eliminating the need to retain additional
protocol-specific state in order to resume a Link.
</p>
</doc>
<doc title="Naming a Link">
<p>
Links are named so that they may be recovered when communication is interrupted. Link names
MUST uniquely identify the link amongst all links of the same direction between the two
participating containers. Link names are only used when attaching a Link, so they may be
arbitrarily long without a significant penalty.
</p>
<p>
A link's name uniquely identifies the link from the container of the source to the
container of the target node, e.g. if the container of the source node is A, and the
container of the target node is B, the link may be globally identified by the (ordered)
tuple <i>(A,B,&lt;name&gt;)</i>.
</p>
<p>
Consequently, a link may only be active in one connection at a time. If an attempt is made
to attach the link subsequently when it is not suspended, then the link can be 'stolen',
i.e. the second attach succeeds and the first attach must then be closed with a link error
of <xref name="link-error" choice="stolen"/>. This behavior ensures that in the event of a
connection failure occurring and being noticed by one party, that re-establishment has the
desired effect.
</p>
</doc>
<doc title="Link Handles">
<p>
Each Link Endpoint is assigned a numeric handle used by the peer as a shorthand to refer to
the Link in all frames that reference the Link (<xref type="type" name="attach"/>,
<xref type="type" name="detach"/>, <xref type="type" name="flow"/>, <xref type="type"
name="transfer"/>, <xref type="type" name="disposition"/>). This handle is assigned by the
initial <xref type="type" name="attach"/> frame and remains in use until the link is
detached. The two Endpoints are not required to use the same handle. This means a peer is
free to independently chose its handle when a Link Endpoint is associated with the Session.
The locally chosen handle is referred to as the <term>output handle</term>. The remotely
chosen handle is referred to as the <term>input handle</term>.
</p>
<p>
At an Endpoint, a Link is considered to be <term>attached</term> when the Link Endpoint
exists and has both input and output handles assigned at an active Session Endpoint. A Link
is considered to be <term>detached</term> when the Link Endpoint exists, but is not assigned
either input or output handles. A Link can be considered <term>half attached</term>
(or <term>half detached</term>) when only one of the input or output handles is assigned.
</p>
<picture><![CDATA[
+-------------------+ +-------------------+
| name: Link_1 | | name: Link_1 |
| handle: i | | handle: j |
|-------------------| |-------------------|
| role: receiver | | role: sender |
| source: A |<---+ +--->| source: A |
| target: B | | | | target: B |
+-------------------+ | | +-------------------+
| |
| +---------+ |
... <---+--->| Session |<---+---> ...
| +---------+ |
| |
+-------------------+ | | +-------------------+
| name: Link_N | | | | name: Link_N |
| handle: k |<---+ +--->| handle: l |
|-------------------| |-------------------|
| role: sender | | role: receiver |
| source: C | | source: C |
| target: D | | target: D |
+-------------------+ +-------------------+
]]>
</picture>
</doc>
<doc title="Establishing or Resuming a Link">
<p>
Links are established and/or resumed by creating a Link Endpoint associated with a local
Terminus, assigning it to an unused handle, and sending an <xref type="type" name="attach"/>
Frame. This frame carries the state of the newly created Link Endpoint, including the local
and remote termini, one being the source and one being the target depending on the
directionality of the Link Endpoint. On receipt of the <xref name="attach"/>, the remote
Session Endpoint creates a corresponding Link Endpoint and informs its application of the
attaching Link. The application attempts to locate the Terminus previously associated with
the Link. This Terminus is associated with the Link Endpoint and may be updated if its
properties do not match those sent by the remote Link Endpoint. If no such Terminus exists,
the application MAY choose to create one using the properties supplied by the remote Link
Endpoint. The Link Endpoint is then mapped to an unused handle, and an <xref type="type"
name="attach"/> Frame is issued carrying the state of the newly created endpoint. Note that
if the application chooses not to create a Terminus, the Session Endpoint will still create
a Link Endpoint and issue an <xref type="type" name="attach"/> indicating that the Link
Endpoint has no associated local terminus. In this case, the Session Endpoint MUST
immediately detach the newly created Link Endpoint.
</p>
<picture title="Establishing a Link"><![CDATA[
Peer Partner
================================================================
*create link endpoint*
ATTACH(name=N, handle=1, ----------> *create link endpoint*
role=sender, +--- ATTACH(name=N, handle=2,
source=A, / role=receiver,
target=B) / source=A,
/ target=B)
<--+
...
----------------------------------------------------------------
]]>
</picture>
<p>
If there is no pre-existing Terminus, and the peer does not wish to create a new one, this
is indicated by setting the local terminus (source or target as appropriate) to null.
</p>
<picture title="Refusing a Link"><![CDATA[
Peer Partner
================================================================
*create link endpoint*
ATTACH(name=N, handle=1, ----------> *create link endpoint* (1)
role=sender, +--- ATTACH(name=N, handle=2,
source=A, / role=receiver,
target=B) / source=A,
/ target=-)
(2) <--+
+--- DETACH(handle=2,
/ closed=True)
/
/
<--+
DETACH(handle=1, ----------->
closed=True)
...
----------------------------------------------------------------
(1) The Link Endpoint is created, but no target is created.
(2) At this point the link is established, but it is to a
nonexistent target.
]]>
</picture>
<p>
If either end of the Link is already associated with a Terminus, the <xref name="attach"/>
frame MUST include its unsettled delivery state.
</p>
<picture title="Resuming a Link"><![CDATA[
Peer Partner
================================================================
*existing source*
ATTACH(name=N, handle=1, ----------> *found existing target*
role=sender, +--- ATTACH(name=N, handle=2, (1)
source=X, / role=receiver,
target=Y, / source=X,
unsettled=...) / target=Y,
(2) <--+ unsettled=...)
...
----------------------------------------------------------------
(1) The target already exists, and its properties
match the peer's expectations.
(2) At this point the Link is reestablished with source=X,
target=Y.
]]>
</picture>
<p>
Note that the expected Terminus properties may not always match the actual Terminus
properties reported by the remote endpoint. In this case, the Link is always considered to
be between the Source as described by the Sender, and the Target as described by the
Receiver. This can happen both when establishing and when resuming a link.
</p>
<p>
When a link is established, an endpoint may not have all the capabilities necessary to
create the terminus exactly matching the expectations of the peer. Should this happen, the
endpoint MAY adjust the properties in order to succeed in creating the terminus. In this
case the endpoint MUST report the actual properties of the terminus as created.
</p>
<p>
When resuming a link, the Source and Target properties may have changed while the link was
suspended. When this happens, the Termini properties communicated in the source and target
fields of the <xref name="attach"/> frames may be in conflict. In this case, the Sender is
considered to hold the authoritative version of the Source properties, the Receiver is
considered to hold the authoritative version of the Target properties. As above, the
resulting Link is constructed to be between the Source as described by the Sender, and the
Target as described by the Receiver. Once the Link is resumed, either peer is free to
continue if the updated properties are acceptable, or if not, <xref type="type"
name="detach"/>.
</p>
<p>
Note that a peer MUST take responsibility for verifying that the remote terminus meets its
requirements. The remote peer SHOULD NOT attempt to pre-empt whether the terminus will meet
the requirements of its partner. This is equally true both for creating and resuming links.
</p>
<picture title="Resuming an altered Link"><![CDATA[
Peer Partner
================================================================
*existing source*
ATTACH(name=N, handle=1, ----------> *found existing target*
role=sender, +--- ATTACH(name=N, handle=2, (1)
source=A, / role=receiver,
target=B, / source=A,
unsettled=...) / target=C,
(2) <--+ unsettled=...)
...
----------------------------------------------------------------
(1) The Terminus already exists, but its state
does not match the Peer's endpoint.
(2) At this point the Link is established with source=A,
target=C.
]]>
</picture>
<p>
It is possible to resume a Link even if one of the Termini has lost nearly all its state.
All that is required is the Link name and direction. This is referred to as
<term>recovering</term> a Link. This is done by creating a new Link Endpoint with an empty
source or target for incoming or outgoing Links respectively. The full Link state is then
constructed from the authoritative source or target supplied by the other endpoint once the
Link is established. If the remote peer has no record of the Link, then no terminus will be
located, and local terminus (source or target as appropriate) field in the
<xref name="attach"/> frame will be null.
</p>
<picture title="Recovering a Link"><![CDATA[
Peer Partner
================================================================
*create link endpoint*
ATTACH(name=N, handle=1, ----------> *found existing target*
role=sender, +--- ATTACH(name=N, handle=2, (1)
source=X / role=receiver,
target=-) / source=X,
(2) <---+ target=Y)
...
----------------------------------------------------------------
(1) The target already exists, and its properties are
authoritative.
(2) At this point the Link is reestablished with source=X,
target=Y.
]]>
</picture>
</doc>
<doc title="Detaching and Reattaching a Link">
<p>
A Session Endpoint can choose to unmap its output handle for a Link. In this case, the
endpoint MUST send a <xref name="detach"/> frame to inform the remote peer that the handle
is no longer attached to the Link Endpoint. Should both endpoints do this, the Link may
return to a fully detached state. Note that in this case the Link Endpoints may still
indirectly communicate via the Session, as there may be active deliveries on the link
referenced via delivery-id.
</p>
<picture><![CDATA[
Peer Partner
=============================================================
*create link endpoint*
ATTACH(name=N, handle=1 ----------> *create link endpoint*
role=sender, +--- ATTACH(name=N, handle=2,
source=A, / role=receiver,
target=B) / source=A,
/ target=B)
<--+
...
*use link* <---------> *use link*
...
DETACH(handle=1) ----------> *detach input handle*
(1) *detach output handle* <---------- DETACH(handle=2)
...
-------------------------------------------------------------
(1) At this point both endpoints are detached.
]]>
</picture>
<p>
When the state of a Link Endpoint changes, this is can be communicated by detaching and then
reattaching with the updated state on the <xref name="attach"/> frame. This can be used to
update the properties of the link endpoints, or to update the properties of the Termini.
</p>
<picture><![CDATA[
Peer Partner
=============================================================
...
DETACH(handle=1) ---+
\
\
\
*modify link endpoint* \
+--> *detach input handle*
ATTACH(name=N, handle=1 ---+ +--- DETACH(handle=2)
role=sender, \ /
source=A', \/
target=B') /\
/ \
*detach input handle* <--+ +--> *reattach input handle*
*modify link endpoint*
+--- ATTACH(name=N, handle=2
/ role=receiver,
/ source=A',
/ target=B')
/
(1) *reattach input handle* <--+
...
*use link* <---------> *use link*
...
-------------------------------------------------------------
(1) At this point the link is updated and attached.
]]>
</picture>
</doc>
<doc title="Link Errors">
<p>
When an error occurs at a Link Endpoint, the endpoint MUST be detached with appropriate
error information supplied in the error field of the <xref name="detach"/> frame. The Link
Endpoint MUST then be destroyed. Should any input (other than a detach) related to the
endpoint either via the input handle or delivery-ids be received, the session MUST be
terminated with an <xref name="session-error" choice="errant-link"/> session-error. Since
the Link Endpoint has been destroyed, the peer cannot reattach, and MUST resume the link in
order to restore communication. In order to disambiguate the resume request from a pipelined
re-attach the resuming <xref name="attach"/> performative MUST contain a non-null value for
its unsettled field. Receipt of a pipelined <xref name="attach"/> MUST result in the session
being terminated with an <xref name="session-error" choice="errant-link"/> session-error.
</p>
</doc>
<doc name="closing-a-link" title="Closing a Link">
<p>
A peer closes a Link by sending the <xref type="type" name="detach"/> frame with the handle
for the specified Link, and the closed flag set to true. The partner will destroy the
corresponding Link endpoint, and reply with its own <xref type="type" name="detach"/> frame
with the closed flag set to true.
</p>
<picture title="Closing a Link"><![CDATA[
Peer Partner
=============================================================
*create link endpoint*
ATTACH(name=N, handle=1 ----------> *create link endpoint*
role=sender, +--- ATTACH(name=N, handle=2,
source=A, / role=receiver,
target=B) / source=A,
/ target=B)
<--+
...
*use link* <---------> *use link*
...
DETACH(handle=1, ----------> *destroy link endpoint*
closed=True)
(1) *destroy link endpoint* <---------- DETACH(handle=2,
closed=True)
-------------------------------------------------------------
(1) At this point both endpoints are destroyed.
]]>
</picture>
<p>
Note that one peer may send a closing detach while its partner is sending a non-closing
detach. In this case, the partner MUST signal that it has closed the link by reattaching and
then sending a closing detach.
</p>
</doc>
<doc name="flow-control" title="Flow Control">
<p>
Once attached, a Link is subject to flow control of Message transfers. Link Endpoints
maintain the following flow control state. This state defines when it is legal to send
transfers on an attached Link, as well as indicating when certain interesting conditions,
such as insufficient messages to consume the currently available <i>link-credit</i>, or
insufficient <i>link-credit</i> to send available messages:
</p>
<dl>
<dt>delivery-count</dt>
<dd><p>The <i>delivery-count</i> is initialized by the Sender when a Link Endpoint is
created, and is incremented whenever a Message is sent (at the Sender) or received (at
the Receiver). Only the Sender may independently modify this field. The Receiver's
value is calculated based on the last known value from the Sender and any subsequent
Messages received on the Link.</p></dd>
<dt>link-credit</dt>
<dd><p>The <i>link-credit</i> variable defines the current maximum legal amount that the
<i>delivery-count</i> may be increased. This identifies a <i>delivery-limit</i> that may
be computed by adding the <i>link-credit</i> to the <i>delivery-count</i>.</p>
<p>Only the Receiver can independently choose a value for this field. The Sender's value
MUST always be maintained in such a way as to match the <i>delivery-limit</i> identified
by the Receiver. This means that the Sender's link-credit variable MUST be set according
to this formula when flow information is given by the receiver:</p>
<p>
<i>link-credit</i><sub>snd</sub> := <i>delivery-count</i><sub>rcv</sub> +
<i>link-credit</i><sub>rcv</sub> - <i>delivery-count</i><sub>snd</sub>.
</p>
<p>
In the event that the receiver does not yet know the <i>delivery-count</i>, i.e.
<i>delivery-count</i><sub>rcv</sub> is unspecified, the Sender MUST assume that
the <i>delivery-count</i><sub>rcv</sub> is the first
<i>delivery-count</i><sub>snd</sub> sent from Sender to Receiver, i.e. the
<i>delivery-count</i><sub>snd</sub> specified in the flow state carried by the initial
<xref name="attach"/> frame from the Sender to the Receiver.
</p>
<p>
Additionally, whenever the Sender increases <i>delivery-count</i>, it MUST decrease
<i>link-credit</i> by the same amount in order to maintain the <i>delivery-limit</i>
identified by the Receiver.
</p>
</dd>
<dt>available</dt>
<dd><p>The <i>available</i> variable is controlled by the Sender, and indicates to the
Receiver, that the Sender could make use of the indicated amount of <i>link-credit</i>.
Only the Sender can independently modify this field. The Receiver's value is calculated
based on the last known value from the Sender and any subsequent incoming Messages
received. The Sender MAY transfer Messages even if the available variable is zero.
Should this happen, the Receiver MUST maintain a floor of zero in it's calculation of
the value of available.</p></dd>
<dt>drain</dt>
<dd><p>The drain flag indicates how the Sender should behave when insufficient messages are
available to consume the current link-credit. If set, the Sender will (after sending all
available messages) advance the delivery-count as much as possible, consuming all
link-credit, and send the flow state to the Receiver. Only the Receiver can
independently modify this field. The Sender's value is always the last known value
indicated by the Receiver.</p></dd>
</dl>
<p>
If the link-credit is less than or equal to zero, i.e. the delivery-count is the same as or
greater than the delivery-limit, it is illegal to send more messages. If the link-credit is
reduced by the Receiver when transfers are in-flight, the Receiver MAY either handle the
excess messages normally or detach the Link with a transfer-limit-exceeded error code.
</p>
<picture><![CDATA[
+----------+ +----------+
| Sender |---------------transfer------------>| Receiver |
+----------+ +----------+
\ / <----------------flow--------------- \ /
+------+ +------+
|
|
|
if link-credit <= 0 then pause
]]>
</picture>
<p>
If the Sender's drain flag is set and there are no available messages, the Sender MUST
advance its delivery-count until link-credit is zero, and send its updated
<xref name="flow"/> state to the Receiver.
</p>
<p>
The delivery-count is an absolute value. While the value itself is conceptually unbounded,
it is encoded as a 32-bit integer that wraps around and compares according to RFC-1982
serial number arithmetic.
</p>
<p>
The initial flow state of a Link Endpoint is determined as follows. The <i>link-credit</i>
and <i>available</i> variables are initialized to zero. The <i>drain</i> flag is initialized
to False. The Sender may choose an arbitrary point to initialize the <i>delivery-count</i>.
This value is communicated in the initial <xref name="attach"/> frame. The Receiver
initializes its <i>delivery-count</i> upon receiving the Sender's <xref name="attach"/>.
</p>
<picture><![CDATA[
flow state
|
| modifies
+------------------+ | +------------------+
| Sender | .----------------------. | Receiver |
+------------------+ attach, transfer, flow +------------------+
| delivery-count |------------------------------->| delivery-count |
| link-credit | | link-credit |
| available |<-------------------------------| available |
| drain | flow | drain |
+------------------+ '-----' +------------------+
|
| modifies
|
flow state
]]>
</picture>
<p>
The flow control semantics defined in this section provide the primitives necessary to
implement a wide variety of flow control strategies. Additionally, by manipulating the
link-credit and drain flag, a Receiver can provide a variety of different higher level
behaviors often useful to applications, including synchronous blocking fetch, synchronous
fetch with a timeout, asynchronous notifications, and stopping/pausing.
</p>
<picture><![CDATA[
+----------+ +----------+
| Receiver |<--------------transfer-------------| Sender |
+----------+ +----------+
\ / -----------------flow--------------> \ /
+------+ +------+
|
|
|
sync-get: flow(link-credit=1, ...) ---->
timed-get: flow(link-credit=1, ...),
*wait*,
flow(drain=True, ...) ---->
async-notify: flow(link-credit=delta, ...) ---->
stop: flow(link-credit=0, ...) ---->
]]>
</picture>
</doc>
<doc title="Synchronous Get">
<p>
A synchronous get of a message from a Link is accomplished by incrementing the link-credit,
sending the updated <xref name="flow"/> state, and waiting indefinitely for a
<xref name="transfer"/> to arrive.
</p>
<picture><![CDATA[
Receiver Sender
=================================================================
...
flow(link-credit=1) ---------->
+---- transfer(...)
*block until transfer arrives* /
<---+
...
-----------------------------------------------------------------
]]>
</picture>
<p>
Synchronous get with a timeout is accomplished by incrementing the link-credit, sending the
updated <xref name="flow"/> state and waiting for the link-credit to be consumed. When the
desired time has elapsed the Receiver then sets the drain flag and sends the newly updated
<xref name="flow"/> state again, while continuing to wait for the link-credit to be
consumed. Even if no messages are available, this condition will be met promptly because of
the drain flag. Once the link-credit is consumed, the Receiver can unambiguously determine
whether a message has arrived or whether the operation has timed out.
</p>
<picture><![CDATA[
Receiver Sender
=================================================================
...
flow(link-credit=1) ---------->
*wait for link-credit <= 0*
flow(drain=True) ---+ +--- transfer(...)
\ /
x
/ \
(1) <--+ +-->
(2) <---------- flow(...)
...
-----------------------------------------------------------------
(1) If a message is available within the timeout, it will
arrive at this point.
(2) If a message is not available within the timeout, the
drain flag will ensure that the Sender promptly advances the
delivery-count until link-credit is consumed.
]]>
</picture>
</doc>
<doc title="Asynchronous Notification">
<p>
Asynchronous notification can be accomplished as follows. The receiver maintains a target
amount of link-credit for that Link. As <xref name="transfer">transfers</xref> arrive on the
Link, the Sender's link-credit decreases as the delivery-count increases. When the Sender's
link-credit falls below a threshold, the <xref name="flow"/> state may be sent to increase
the Sender's link-credit back to the desired target.
</p>
<picture><![CDATA[
Receiver Sender
=====================================================================
...
<---------- transfer(...)
<---------- transfer(...)
flow(link-credit=delta) ---+ +--- transfer(...)
\ /
x
/ \
<--+ +-->
<---------- transfer(...)
<---------- transfer(...)
flow(link-credit=delta) ---+ +--- transfer(...)
\ /
x
/ \
<--+ +-->
...
---------------------------------------------------------------------
The incoming message rate for the Link is limited by the
rate at which the Receiver updates the delivery-limit by
issuing link-credit.
]]>
</picture>
</doc>
<doc title="Stopping a Link">
<p>
Stopping the transfers on a given Link is accomplished by updating the link-credit to be
zero and sending the updated <xref name="flow"/> state. Some transfers may be in-flight at
the time the <xref name="flow"/> state is sent, so incoming transfers may still arrive on
the Link. The echo field of the <xref name="flow"/> frame may be used to request the
Sender's <xref name="flow"/> state be echoed back. This may be used to determine when the
Link has finally quiesced.
</p>
<picture><![CDATA[
Receiver Sender
================================================================
...
<---------- transfer(...)
flow(..., ---+ +--- transfer(...)
link-credit=0, \ /
echo=True) x
/ \
(1) <--+ +-->
(2) <---------- flow(...)
...
----------------------------------------------------------------
(1) In-flight transfers may still arrive until the flow state
is updated at the Sender.
(2) At this point no further transfers will arrive.
]]>
</picture>
</doc>
<doc title="Messages">
<p>
The transport layer assumes as little as possible about Messages and allows alternative
Message representations to be layered above. Message data is carried as the payload in
frames containing the <xref name="transfer"/> performative. Messages can be fragmented
across several <xref name="transfer"/> frames as indicated by the more flag of the <xref
name="transfer"/> performative.
</p>
</doc>
<doc title="Transferring a Message">
<p>
When an application initiates a message transfer, it assigns a delivery-tag used to track
the state of the delivery while the message is in transit. A delivery is considered
<i>unsettled</i> at the sender/receiver from the point at which it was sent/received until
it has been <i>settled</i> by the sending/receiving application. Each delivery MUST be
identified by a delivery-tag chosen by the sending application. The delivery-tag MUST be
unique amongst all deliveries that could be considered unsettled by either end of the Link.
</p>
<p>
Upon initiating a transfer, the application will supply the sending link endpoint (Sender)
with the message data and its associated delivery-tag. The Sender will create an entry in
its unsettled map, and send a transfer frame that includes the delivery-tag, its initial
state, and its associated message data. For brevity on the wire, the delivery-tag is also
associated with a delivery-id assigned by the session. The delivery-id is then used to refer
to the delivery-tag in all subsequent interactions on that session.
</p>
<p>
For simplicity the delivery-id is omitted in the following diagrams and the delivery-tag is
itself used directly. These diagrams also assume that this interaction takes place in the
context of a single established link, and as such omit other details that would be present
on the wire in practice such as the channel number, link handle, fragmentation flags, etc,
focusing only on the essential aspects of message transfer.
</p>
<picture title="Initial Transfer"><![CDATA[
+------------------+
/ Sender \
+----------------------+
| unsettled: | transfer(delivery-tag=DT, settled=False,
| ... | state=S_0, ...)
| DT -> (local: S_0, |----------------------------------------------->
| remote: ?) |
| ... |
+----------------------+
]]>
</picture>
<p>
Upon receiving the transfer, the receiving link endpoint (Receiver) will create an entry in
its own unsettled map and make the transferred message data available to the application to
process.
</p>
<picture title="Initial Receipt"><![CDATA[
+------------------+
/ Receiver \
+----------------------+
transfer(delivery-tag=DT, settled=False, | unsettled: |
state=S_0, ...) | ... |
----------------------------------------------->| DT -> (local: S_1, |
| remote: S_0)|
| ... |
+----------------------+
]]>
</picture>
<p>
Once notified of the received message data, the application processes the message,
indicating the updated delivery state to the link endpoint as desired. Applications may wish
to classify delivery states as <term>terminal</term> or <term>non-terminal</term> depending
on whether an endpoint will ever update the state further once it has been reached. In some
cases (e.g. large messages or transactions), the receiving application may wish to indicate
non-terminal delivery states to the sender. This is done via the <xref name="disposition"/>
frame.
</p>
<picture title="Indication of Non-Terminal State"><![CDATA[
+------------------+
/ Receiver \
+----------------------+
| unsettled: |
| ... |
<-----------------------------------------------| DT -> (local: S_2, |
disp(role=receiver, ..., delivery-tag=DT, | remote: S_0)|
settled=False, state=S_2, ...) | ... |
+----------------------+
]]>
</picture>
<p>
Once the receiving application has finished processing the message, it indicates to the link
endpoint a <i>terminal</i> delivery state that reflects the outcome of the application
processing (successful or otherwise) and thus the outcome which the Receiver wishes to occur
at the Sender. This state is communicated back to the Sender via the disposition frame.
</p>
<picture title="Indication of Presumptive Terminal State"><![CDATA[
+------------------+
/ Receiver \
+----------------------+
| unsettled: |
| ... |
<-----------------------------------------------| DT -> (local: T_0, |
disp(role=receiver, ..., delivery-tag=DT, | remote: S_0)|
settled=False, state=T_0, ...) | ... |
+----------------------+
]]>
</picture>
<p>
Upon receiving the updated delivery state from the Receiver, the Sender will, if it has not
already spontaneously attained a terminal state, update its view the state and communicate
this back to the sending application.
</p>
<picture title="Receipt of Terminal State"><![CDATA[
+------------------+
/ Sender \
+----------------------+
| unsettled: |
| ... |
| DT -> (local: S_0, |<-----------------------------------------------
| remote: T_0)| disp(role=receiver, ..., delivery-tag=DT,
| ... | settled=False, state=T_0, ...)
+----------------------+
]]>
</picture>
<p>
The sending application will then typically perform some action based on this terminal state
and then settle the delivery, causing the Sender to remove the delivery-tag from its
unsettled map. The Sender will then send its final delivery state along with an indication
that the delivery is settled at the Sender. Note that this amounts to the Sender announcing
that it is forever forgetting everything about the delivery-tag in question, and as such it
is only possible to make such an announcement once, since after the Sender forgets, it has
no way of remembering to make the announcement again. Should this frame get lost due to an
interruption in communication, the Receiver will find out that the Sender has settled the
delivery upon link recovery. When the Sender re-attaches the Receiver will examine the
unsettled state of the Sender (i.e. what has <b>not</b> been forgotten) and from this can
derive that the delivery in question has been settled (since its tag will not be in the
unsettled state).
</p>
<picture title="Indication of Settlement"><![CDATA[
+------------------+
/ Sender \
+----------------------+
| unsettled: | disp(role=sender, ..., delivery-tag=DT,
| ... | settled=True, state=T_1, ...)
| - -> - |----------------------------------------------->
| ... |
+----------------------+
]]>
</picture>
<p>
When the Receiver finds out that the Sender has settled the delivery, the Receiver will
update its view of the remote state to indicate this, and then notify the receiving
application.
</p>
<picture title="Receipt of Settlement"><![CDATA[
+------------------+
/ Receiver \
+----------------------+
disp(role=sender, ..., delivery-tag=DT, | unsettled: |
settled=True, state=T_1, ...) | ... |
----------------------------------------------->| DT -> (local: S_2, |
| remote: - ) |
| ... |
+----------------------+
]]>
</picture>
<p>
The application may then perform some final action, e.g. remove the delivery-tag from a set
kept for de-duplication, and then notify the Receiver that the delivery is settled. The
Receiver will then remove the delivery-tag from its unsettled map. Note that because the
Receiver knows that the delivery is already settled at the Sender, it makes no effort to
notify the other endpoint that it is settling the delivery.
</p>
<picture title="Final Settlement"><![CDATA[
+------------------+
/ Receiver \
+----------------------+
| unsettled: |
| ... |
<-----------------------------------------------| - -> - |
| ... |
+----------------------+
]]>
</picture>
<p>
As alluded to above, it is possible for the sending application to transition a delivery to
a terminal state at the Sender spontaneously (i.e. not as a consequence of a disposition
that has been received from the Receiver). In this case the Sender should send a disposition
to the Receiver, but not settle until the Receiver confirms, via a disposition in the
opposite direction, that it has updated the state at its endpoint.
</p>
<p>
This set of exchanges illustrates the basic principals of message transfer. While a delivery
is unsettled the endpoints exchange the current state of the delivery. Eventually both
endpoints reach a terminal state as indicated by the application. This triggers the other
application to take some final action and settle the delivery, and once one endpoint
settles, this usually triggers the application at the other endpoint to settle.
</p>
<p>
This basic pattern can be modified in a variety of ways to achieve different guarantees, for
example if the sending application settles the delivery <i>before</i> sending it, this
results in an <i>at-most-once</i> guarantee. The Sender has indicated up front with his
initial transmission that he has forgotten everything about this delivery and will therefore
make no further attempts to send it. Should this delivery make it to the Receiver, the
Receiver clearly has no obligation to respond with updates of the Receiver's delivery state,
as they would be meaningless and ignored by the Sender.
</p>
<picture title="At-Most-Once"><![CDATA[
+------------------+
/ Sender \
+----------------------+
| unsettled: | transfer(delivery-tag=DT, settled=True,
| ... | state=T_0, ...)
| - -> - |----------------------------------------------->
| ... |
+----------------------+
]]>
</picture>
<p>
Similarly, if we modify the basic scenario such that the receiving application chooses to
settle immediately upon processing the message rather than waiting for the sender to settle
first, we get an <i>at-least-once</i> guarantee. If the disposition frame indicated below is
lost, then upon link recovery the Sender will not see the delivery-tag in the Receiver's
unsettled map and will therefore assume the delivery was lost and resend it, resulting in
duplicate processing of the message at the Receiver.
</p>
<picture title="At-Least-Once"><![CDATA[
+------------------+
/ Receiver \
+----------------------+
| unsettled: |
| ... |
<-----------------------------------------------| - -> - |
disp(role=receiver, ..., delivery-tag=DT, | ... |
settled=True, state=T_0, ...) | |
+----------------------+
]]>
</picture>
<p>
As one might guess, the scenario presented initially where the sending application settles
when the Receiver reaches a terminal state, and the receiving application settles when the
Sender settles, results in an <i>exactly-once</i> guarantee. More generally if the Receiver
settles prior to the Sender, it is possible for duplicate messages to occur, except in the
case where the Sender settles before his initial transmission. Similarly, if the Sender
settles before the Receiver reaches a terminal state, it is possible for messages to be
lost.
</p>
<p>
The Sender and Receiver policy regarding settling may either be pre-configured for the
entire link, thereby allowing for optimized endpoint choices, or may be determined on an
ad-hoc basis for each delivery. An application may also choose to settle at an endpoint
independently of its delivery state, for example the sending application may choose to
settle a delivery due to the message ttl expiring regardless of whether the Receiver has
reached a terminal state.
</p>
</doc>
<doc name="resuming-deliveries" title="Resuming Deliveries">
<p>
When a suspended link having unsettled deliveries is resumed, the <i>unsettled</i> field
from the <xref name="attach"/> frame will carry the delivery-tags and delivery state of all
deliveries considered unsettled by the issuing link endpoint. The set of delivery tags and
delivery states contained in the unsettled maps from both endpoints can be divided into
three categories:
</p>
<dl>
<dt>Deliveries that only the Source considers unsettled</dt>
<dd><p>Deliveries in this category MAY be resumed at the discretion of the sending
application. If the sending application marks the resend attempt as a resumed delivery
then it MUST be ignored by the receiver. (This allows the sender to pipeline resumes
without risk of duplication at the sender).</p></dd>
<dt>Deliveries that only the Target considers unsettled</dt>
<dd><p>Deliveries in this category MUST be ignored by the Sender, and MUST be considered
settled by the Receiver.</p></dd>
<dt>Deliveries that both the Source and Target consider unsettled</dt>
<dd><p>Deliveries in this category MUST be resumed by the Sender.</p></dd>
</dl>
<p>
Note that in the case where an endpoint indicates that the unsettled map is incomplete, the
absence of an entry in the unsettled map is not an indication of settlement. In this case
the two endpoints must reduce the levels of unsettled state as much as they can by the
Sender resuming and/or settling transfers that it observes that the Receiver considers
unsettled. Upon completion of this reduction of state, the two parties must suspend and
re-attempt to resume the link. Only when both sides have complete unsettled maps may new
unsettled state be created by the sending of non-resuming transfers.
</p>
<p>
A delivery is resumed much the same way it is initially transferred with the following
exceptions:
</p>
<ul>
<li><p>The resume flag of the <xref name="transfer"/> frame MUST be set to true when
resuming a delivery.</p></li>
<li><p>The Sender MAY omit message data when the Delivery State of the Receiver indicates
retransmission is unnecessary.</p></li>
</ul>
<p>
Note that unsettled delivery-tags do NOT have any valid delivery-ids associated until they
are resumed, as the delivery-ids from their original link endpoints are meaningless to the
new link endpoints.
</p>
</doc>
<doc title="Transferring Large Messages">
<p>
Each <xref name="transfer"/> frame may carry an arbitrary amount of message data up to the
limit imposed by the maximum frame size. For Messages that are too large to fit within the
maximum frame size, additional data may be transferred in additional <xref name="transfer"/>
frames by setting the more flag on all but the last <xref name="transfer"/> frame. When a
message is split up into multiple <xref name="transfer"/> frames in this manner, messages
being transferred along different links MAY be interleaved. However, messages transferred
along a single link MUST NOT be interleaved.
</p>
<p>
The sender may indicate an aborted attempt to deliver a Message by setting the abort flag on
the last <xref type="type" name="transfer"/>. In this case the receiver MUST discard the
Message data that was transferred prior to the abort.
</p>
<picture title="Outgoing Fragmentation State Diagram"><![CDATA[
+------------+ S:XFR(M=1,A=0)
+------| NOT_SENT |------+
| +------------+ |
| |
| S:XFR(M=0,A=0) |
| | S:XFR(M=1,A=0)
| | +----------+
| | | |
| \|/ \|/ |
| +------------+ |
| +----------------| SENDING |-------+
| | S:XFR(M=0,A=0) +------------+
| | |
| | |
| | | S:XFR(M=0,A=1)
| | |
\|/ \|/ \|/
+------------+ +------------+
| SENT | | ABORTED |
+------------+ +------------+
Key: S:XFR(M=?,A=?) --> Sent TRANSFER(more=?, aborted=?)
]]>
</picture>
<picture title="Incoming Fragmentation State Diagram"><![CDATA[
+------------+ R:XFR(M=1,A=0)
+------| NOT_RCVD |------+
| +------------+ |
| |
| R:XFR(M=0,A=0) |
| | R:XFR(M=1,A=0)
| | +----------+
| | | |
| \|/ \|/ |
| +------------+ |
| +----------------| RECEIVING |-------+
| | R:XFR(M=0,A=0) +------------+
| | |
| | |
| | | R:XFR(M=0,A=1)
| | |
\|/ \|/ \|/
+------------+ +------------+
| RECEIVED | | ABORTED |
+------------+ +------------+
Key: R:XFR(M=?,A=?) --> Received TRANSFER(more=?, aborted=?)
]]>
</picture>
</doc>
</section>
<section name="performatives" label="composite types that appear as frame bodies">
<!-- - Frame: open - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="open" source="list" provides="frame"
label="negotiate Connection parameters">
<doc>
<p>
The first frame sent on a connection in either direction MUST contain an Open body. (Note
that the Connection header which is sent first on the Connection is *not* a frame.) The
fields indicate the capabilities and limitations of the sending peer.
</p>
</doc>
<descriptor name="amqp:open:list" code="0x00000000:0x00000010"/>
<field name="container-id" type="string" mandatory="true"
label="the id of the source container"/>
<field name="hostname" type="string" label="the name of the target host">
<doc>
<p>
The dns name of the host (either fully qualified or relative) to which the sending peer
is connecting. It is not mandatory to provide the hostname. If no hostname is provided
the receiving peer should select a default based on its own configuration. This field
can be used by AMQP proxies to determine the correct back-end service to connect
the client to.
</p>
<p>
This field may already have been specified by the <xref name="sasl-init"/> frame, if a
SASL layer is used, or, the server name indication extension as described in
RFC-4366, if a TLS layer is used, in which case this field SHOULD be null or contain
the same value. It is undefined what a different value to those already specific means.
</p>
</doc>
</field>
<field name="max-frame-size" type="uint" default="4294967295"
label="proposed maximum frame size">
<doc>
<p>
The largest frame size that the sending peer is able to accept on this Connection. If
this field is not set it means that the peer does not impose any specific limit. A peer
MUST NOT send frames larger than its partner can handle. A peer that receives an
oversized frame MUST close the Connection with the framing-error error-code.
</p>
<p>
Both peers MUST accept frames of up to <xref name="MIN-MAX-FRAME-SIZE"/> octets
large.
</p>
</doc>
</field>
<field name="channel-max" type="ushort" default="65535"
label="the maximum channel number that may be used on the Connection">
<doc>
<p>
The channel-max value is the highest channel number that may be used on the Connection.
This value plus one is the maximum number of Sessions that can be simultaneously active
on the Connection. A peer MUST not use channel numbers outside the range that its
partner can handle. A peer that receives a channel number outside the supported range
MUST close the Connection with the framing-error error-code.
</p>
</doc>
</field>
<field name="idle-time-out" type="milliseconds" label="idle time-out">
<doc>
<p>
The idle time-out required by the sender. A value of zero is the same as if it was
not set (null). If the receiver is unable or unwilling to support the idle time-out
then it should close the connection with an error explaining why (eg, because it is
too small).
</p>
<p>
If the value is not set, then the sender does not have an idle time-out. However,
senders doing this should be aware that implementations MAY choose to use an
internal default to efficiently manage a peer's resources.
</p>
</doc>
</field>
<field name="outgoing-locales" type="ietf-language-tag" multiple="true"
label="locales available for outgoing text">
<doc>
<p>
A list of the locales that the peer supports for sending informational text. This
includes Connection, Session and Link error descriptions. A peer MUST support at least
the <i>en-US</i> locale (see <xref name="ietf-language-tag"/>). Since this value is
always supported, it need not be supplied in the outgoing-locales. A null value or an
empty list implies that only <i>en-US</i> is supported.
</p>
</doc>
</field>
<field name="incoming-locales" type="ietf-language-tag" multiple="true"
label="desired locales for incoming text in decreasing level of preference">
<doc>
<p>
A list of locales that the sending peer permits for incoming informational text. This
list is ordered in decreasing level of preference. The receiving partner will chose the
first (most preferred) incoming locale from those which it supports. If none of the
requested locales are supported, <i>en-US</i> will be chosen. Note that <i>en-US</i>
need not be supplied in this list as it is always the fallback. A peer may determine
which of the permitted incoming locales is chosen by examining the partner's supported
locales as specified in the outgoing-locales field. A null value or an empty list
implies that only <i>en-US</i> is supported.
</p>
</doc>
</field>
<field name="offered-capabilities" type="symbol" multiple="true"
label="the extension capabilities the sender supports">
<doc>
<p>
If the receiver of the offered-capabilities requires an extension capability which is
not present in the offered-capability list then it MUST close the connection.
</p>
<p>
A list of commonly defined connection capabilities and their meanings can be found here:
<xref type="extern"
name="http://www.amqp.org/specification/1.0/connection-capabilities"/>.
</p>
</doc>
</field>
<field name="desired-capabilities" type="symbol" multiple="true"
label="the extension capabilities the sender may use if the receiver supports them">
<doc>
<p>
The desired-capability list defines which extension capabilities the sender MAY use if
the receiver offers them (i.e. they are in the offered-capabilities list received by the
sender of the desired-capabilities). If the receiver of the desired-capabilities offers
extension capabilities which are not present in the desired-capability list it received,
then it can be sure those (undesired) capabilities will not be used on the
Connection.
</p>
</doc>
</field>
<field name="properties" type="fields" label="connection properties">
<doc>
<p>
The properties map contains a set of fields intended to indicate information about the
connection and its container.
</p>
<p>
A list of commonly defined connection properties and their meanings can be found here:
<xref type="extern" name="http://www.amqp.org/specification/1.0/connection-properties"/>
</p>
</doc>
</field>
</type>
<!-- - Frame: begin - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="begin" source="list" provides="frame"
label="begin a Session on a channel">
<doc>
<p>
Indicate that a Session has begun on the channel.
</p>
</doc>
<descriptor name="amqp:begin:list" code="0x00000000:0x00000011"/>
<field name="remote-channel" type="ushort" label="the remote channel for this Session">
<doc>
<p>
If a Session is locally initiated, the remote-channel MUST NOT be set. When an endpoint
responds to a remotely initiated Session, the remote-channel MUST be set to the channel
on which the remote Session sent the begin.
</p>
</doc>
</field>
<field name="next-outgoing-id" type="transfer-number" mandatory="true"
label="the transfer-id of the first transfer id the sender will send">
<doc>
<p>See <xref type="doc" name="session-flow-control"/>.</p>
</doc>
</field>
<field name="incoming-window" type="uint" mandatory="true"
label="the initial incoming-window of the sender">
<doc>
<p>See <xref name="session-flow-control"/>.</p>
</doc>
</field>
<field name="outgoing-window" type="uint" mandatory="true"
label="the initial outgoing-window of the sender">
<doc>
<p>See <xref name="session-flow-control"/>.</p>
</doc>
</field>
<field name="handle-max" type="handle" default="4294967295"
label="the maximum handle value that may be used on the Session">
<doc>
<p>
The handle-max value is the highest handle value that may be used on the Session.
A peer MUST NOT attempt to attach a Link using a handle value outside the range that its
partner can handle. A peer that receives a handle outside the supported range MUST close
the Connection with the framing-error error-code.
</p>
</doc>
</field>
<field name="offered-capabilities" type="symbol" multiple="true"
label="the extension capabilities the sender supports">
<doc>
<p>
A list of commonly defined session capabilities and their meanings can be found here:
<xref type="extern" name="http://www.amqp.org/specification/1.0/session-capabilities"/>.
</p>
</doc>
</field>
<field name="desired-capabilities" type="symbol" multiple="true"
label="the extension capabilities the sender may use if the receiver supports them"/>
<field name="properties" type="fields" label="session properties">
<doc>
<p>
The properties map contains a set of fields intended to indicate information about the
session and its container.
</p>
<p>
A list of commonly defined session properties and their meanings can be found here:
<xref type="extern" name="http://www.amqp.org/specification/1.0/session-properties"/>.
</p>
</doc>
</field>
</type>
<!-- - Frame: attach - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="attach" source="list" provides="frame"
label="attach a Link to a Session">
<doc>
<p>
The <xref type="type" name="attach"/> frame indicates that a Link Endpoint has been
attached to the Session. The opening flag is used to indicate that the Link Endpoint is
newly created.
</p>
</doc>
<descriptor name="amqp:attach:list" code="0x00000000:0x00000012"/>
<field name="name" type="string" mandatory="true" label="the name of the link">
<doc>
<p>
This name uniquely identifies the link from the container of the source to the container
of the target node, e.g. if the container of the source node is A, and the container of
the target node is B, the link may be globally identified by the (ordered) tuple
<i>(A,B,&lt;name&gt;)</i>.
</p>
</doc>
</field>
<field name="handle" type="handle" mandatory="true">
<doc>
<p>
The handle MUST NOT be used for other open Links. An attempt to attach using a handle
which is already associated with a Link MUST be responded to with an immediate
<xref name="close"/> carrying a Handle-in-use <xref name="session-error"/>.
</p>
<p>
To make it easier to monitor AMQP link attach frames, it is recommended that
implementations always assign the lowest available handle to this field.
</p>
</doc>
</field>
<field name="role" type="role" mandatory="true" label="role of the link endpoint"/>
<field name="snd-settle-mode" type="sender-settle-mode" default="mixed"
label="settlement mode for the Sender">
<doc>
<p>
Determines the settlement policy for deliveries sent at the Sender. When set at the
Receiver this indicates the desired value for the settlement mode at the Sender. When
set at the Sender this indicates the actual settlement mode in use.
</p>
</doc>
</field>
<field name="rcv-settle-mode" type="receiver-settle-mode" default="first"
label="the settlement mode of the Receiver">
<doc>
<p>
Determines the settlement policy for unsettled deliveries received at the Receiver. When
set at the Sender this indicates the desired value for the settlement mode at the
Receiver. When set at the Receiver this indicates the actual settlement mode in use.
</p>
</doc>
</field>
<field name="source" type="*" requires="source" label="the source for Messages">
<doc>
<p>
If no source is specified on an outgoing Link, then there is no source currently
attached to the Link. A Link with no source will never produce outgoing Messages.
</p>
</doc>
</field>
<field name="target" type="*" requires="target" label="the target for Messages">
<doc>
<p>
If no target is specified on an incoming Link, then there is no target currently
attached to the Link. A Link with no target will never permit incoming Messages.
</p>
</doc>
</field>
<field name="unsettled" type="map" label="unsettled delivery state">
<doc>
<p>
This is used to indicate any unsettled delivery states when a suspended link is resumed.
The map is keyed by delivery-tag with values indicating the delivery state. The local
and remote delivery states for a given delivery-tag MUST be compared to resolve any
in-doubt deliveries. If necessary, deliveries MAY be resent, or resumed based on the
outcome of this comparison. See <xref name="resuming-deliveries"/>.
</p>
<p>
If the local unsettled map is too large to be encoded within a frame of the agreed
maximum frame size then the session may be ended with the frame-size-too-small error
(see <xref name="amqp-error"/>). The endpoint SHOULD make use of the ability to send an
incomplete unsettled map (see below) to avoid sending an error.
</p>
<p>
The unsettled map MUST NOT contain null valued keys.
</p>
<p>
When reattaching (as opposed to resuming), the unsettled map MUST be null.
</p>
</doc>
</field>
<field name="incomplete-unsettled" type="boolean" default="false">
<doc>
<p>
If set to true this field indicates that the unsettled map provided is not complete.
When the map is incomplete the recipient of the map cannot take the absence of a
delivery tag from the map as evidence of settlement. On receipt of an incomplete
unsettled map a sending endpoint MUST NOT send any new deliveries (i.e. deliveries where
resume is not set to true) to its partner (and a receiving endpoint which sent an
incomplete unsettled map MUST detach with an error on receiving a transfer which does
not have the resume flag set to true).
</p>
</doc>
</field>
<field name="initial-delivery-count" type="sequence-no">
<doc>
<p>
This MUST NOT be null if role is sender, and it is ignored if the role is receiver. See
<xref name="flow-control"/>.
</p>
</doc>
</field>
<field name="max-message-size" type="ulong"
label="the maximum message size supported by the link endpoint">
<doc>
<p>
This field indicates the maximum message size supported by the link endpoint. Any
attempt to deliver a message larger than this results in a message-size-exceeded
<xref name="link-error"/>. If this field is zero or unset, there is no maximum size
imposed by the link endpoint.
</p>
</doc>
</field>
<field name="offered-capabilities" type="symbol" multiple="true"
label="the extension capabilities the sender supports">
<doc>
<p>
A list of commonly defined session capabilities and their meanings can be found here:
<xref type="extern" name="http://www.amqp.org/specification/1.0/link-capabilities"/>.
</p>
</doc>
</field>
<field name="desired-capabilities" type="symbol" multiple="true"
label="the extension capabilities the sender may use if the receiver supports them"/>
<field name="properties" type="fields" label="link properties">
<doc>
<p>
The properties map contains a set of fields intended to indicate information about the
link and its container.
</p>
<p>
A list of commonly defined link properties and their meanings can be found here:
<xref type="extern" name="http://www.amqp.org/specification/1.0/link-properties"/>
</p>
</doc>
</field>
</type>
<!-- - Frame: flow - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="flow" source="list" provides="frame" label="update link state">
<doc>
<p>Updates the flow state for the specified Link.</p>
</doc>
<descriptor name="amqp:flow:list" code="0x00000000:0x00000013"/>
<field name="next-incoming-id" type="transfer-number">
<doc>
<p>
Identifies the expected transfer-id of the next incoming <xref name="transfer"/> frame.
This value is not set if and only if the sender has not yet received the
<xref name="begin"/> frame for the session. See
<xref type="doc" name="session-flow-control"/> for more details.
</p>
</doc>
</field>
<field name="incoming-window" type="uint" mandatory="true">
<doc>
<p>
Defines the maximum number of incoming <xref name="transfer"/> frames that the endpoint
can currently receive. See <xref type="doc" name="session-flow-control"/> for more
details.
</p>
</doc>
</field>
<field name="next-outgoing-id" type="transfer-number" mandatory="true">
<doc>
<p>
The transfer-id that will be assigned to the next outgoing <xref name="transfer"/>
frame. See <xref type="doc" name="session-flow-control"/> for more details.
</p>
</doc>
</field>
<field name="outgoing-window" type="uint" mandatory="true">
<doc>
<p>
Defines the maximum number of outgoing <xref name="transfer"/> frames that the endpoint
could potentially currently send, if it was not constrained by restrictions imposed by
its peer's incoming-window. See <xref type="doc" name="session-flow-control"/> for more
details.
</p>
</doc>
</field>
<field name="handle" type="handle">
<doc>
<p>
If set, indicates that the flow frame carries flow state information for the local Link
Endpoint associated with the given handle. If not set, the flow frame is carrying only
information pertaining to the Session Endpoint.
</p>
<p>
If set to a handle that is not currently associated with an attached Link, the
recipient MUST respond by ending the session with an <xref choice="unattached-handle"
name="session-error"/> session error.
</p>
</doc>
</field>
<field name="delivery-count" type="sequence-no" label="the endpoint's delivery-count">
<doc>
<p>
When the handle field is not set, this field MUST NOT be set.
</p>
<p>
When the handle identifies that the flow state is being sent from the Sender Link
Endpoint to Receiver Link Endpoint this field MUST be set to the current delivery-count
of the Link Endpoint.
</p>
<p>
When the flow state is being sent from the Receiver Endpoint to the Sender Endpoint this
field MUST be set to the last known value of the corresponding Sending Endpoint. In the
event that the Receiving Link Endpoint has not yet seen the initial
<xref name="attach"/> frame from the Sender this field MUST NOT be set.
</p>
<p>
See <xref type="doc" name="flow-control"/> for more details.
</p>
</doc>
</field>
<field name="link-credit" type="uint"
label="the current maximum number of Messages that can be received">
<doc>
<p>
The current maximum number of Messages that can be handled at the Receiver
Endpoint of the Link. Only the receiver endpoint can independently set this value. The
sender endpoint sets this to the last known value seen from the receiver. See
<xref type="doc" name="flow-control"/> for more details.
</p>
<p>
When the handle field is not set, this field MUST NOT be set.
</p>
</doc>
</field>
<field name="available" type="uint" label="the number of available Messages">
<doc>
<p>
The number of Messages awaiting credit at the link sender endpoint. Only the
sender can independently set this value. The receiver sets this to the last known value
seen from the sender. See <xref type="doc" name="flow-control"/> for more details.
</p>
<p>
When the handle field is not set, this field MUST NOT be set.
</p>
</doc>
</field>
<field name="drain" type="boolean" default="false" label="indicates drain mode">
<doc>
<p>
When flow state is sent from the sender to the receiver, this field contains the actual
drain mode of the sender. When flow state is sent from the receiver to the sender, this
field contains the desired drain mode of the receiver. See <xref type="doc"
name="flow-control"/> for more details.
</p>
<p>
When the handle field is not set, this field MUST NOT be set.
</p>
</doc>
</field>
<field name="echo" type="boolean" default="false"
label="request link state from other endpoint"/>
<field name="properties" type="fields" label="link state properties">
<doc>
<p>
A list of commonly defined link state properties and their meanings can be found here:
<xref type="extern" name="http://www.amqp.org/specification/1.0/link-state-properties"/>
</p>
</doc>
</field>
</type>
<!-- - Frame: transfer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="transfer" source="list" provides="frame"
label="transfer a Message">
<doc>
<p>
The transfer frame is used to send Messages across a Link. Messages may be carried by a
single transfer up to the maximum negotiated frame size for the Connection. Larger
Messages may be split across several transfer frames.
</p>
</doc>
<descriptor name="amqp:transfer:list" code="0x00000000:0x00000014"/>
<field name="handle" type="handle" mandatory="true">
<doc>
<p>Specifies the Link on which the Message is transferred.</p>
</doc>
</field>
<field name="delivery-id" type="delivery-number" label="alias for delivery-tag">
<doc>
<p>
The delivery-id MUST be supplied on the first transfer of a multi-transfer delivery. On
continuation transfers the delivery-id MAY be omitted. It is an error if the delivery-id
on a continuation transfer differs from the delivery-id on the first transfer of a
delivery.
</p>
</doc>
</field>
<field name="delivery-tag" type="delivery-tag">
<doc>
<p>
Uniquely identifies the delivery attempt for a given Message on this Link. This field
MUST be specified for the first transfer of a multi transfer message and may only be
omitted for continuation transfers.
</p>
</doc>
</field>
<field name="message-format" type="message-format" label="indicates the message format">
<doc>
<p>
This field MUST be specified for the first transfer of a multi transfer message and may
only be omitted for continuation transfers.
</p>
</doc>
</field>
<field name="settled" type="boolean">
<doc>
<p>
If not set on the first (or only) transfer for a delivery, then the settled flag MUST
be interpreted as being false. For subsequent transfers if the settled flag is left
unset then it MUST be interpreted as true if and only if the value of the settled flag
on any of the preceding transfers was true; if no preceding transfer was sent with
settled being true then the value when unset MUST be taken as false.
</p>
<p>
If the negotiated value for snd-settle-mode at attachment is <xref
name="sender-settle-mode" choice="settled"/>, then this field MUST be true on at least
one transfer frame for a delivery (i.e. the delivery must be settled at the Sender at
the point the delivery has been completely transferred).
</p>
<p>
If the negotiated value for snd-settle-mode at attachment is <xref
name="sender-settle-mode" choice="unsettled"/>, then this field MUST be false (or
unset) on every transfer frame for a delivery (unless the delivery is aborted).
</p>
</doc>
</field>
<field name="more" type="boolean" default="false"
label="indicates that the Message has more content">
<doc>
<p>
Note that if both the more and aborted fields are set to true, the aborted flag takes
precedence. That is a receiver should ignore the value of the more field if the
transfer is marked as aborted. A sender SHOULD NOT set the more flag to true if it
also sets the aborted flag to true.
</p>
</doc>
</field>
<field name="rcv-settle-mode" type="receiver-settle-mode">
<doc>
<p>
If <xref name="receiver-settle-mode" choice="first"/>, this indicates that the
Receiver MUST settle the delivery once it has arrived without waiting for the Sender to
settle first.
</p>
<p>
If <xref name="receiver-settle-mode" choice="second"/>, this indicates that the
Receiver MUST NOT settle until sending its disposition to the Sender and receiving a
settled disposition from the sender.
</p>
<p>
If not set, this value is defaulted to the value negotiated on link attach.
</p>
<p>
If the negotiated link value is <xref name="receiver-settle-mode" choice="first"/>,
then it is illegal to set this field to <xref name="receiver-settle-mode"
choice="second"/>.
</p>
<p>
If the message is being sent settled by the Sender, the value of this field is ignored.
</p>
<p>
The (implicit or explicit) value of this field does not form part of the transfer state,
and is not retained if a link is suspended and subsequently resumed.
</p>
</doc>
</field>
<field name="state" type="*" requires="delivery-state"
label="the state of the delivery at the sender">
<doc>
<p>
When set this informs the receiver of the state of the delivery at the sender. This is
particularly useful when transfers of unsettled deliveries are resumed after a resuming
a link. Setting the state on the transfer can be thought of as being equivalent to
sending a disposition immediately before the <xref name="transfer"/> performative, i.e.
it is the state of the delivery (not the transfer) that existed at the point the frame
was sent.
</p>
<p>
Note that if the <xref name="transfer"/> performative (or an earlier <xref
name="disposition"/> performative referring to the delivery) indicates that the delivery
has attained a terminal state, then no future <xref name="transfer"/> or <xref
name="disposition"/> sent by the sender can alter that terminal state.
</p>
</doc>
</field>
<field name="resume" type="boolean" default="false" label="indicates a resumed delivery">
<doc>
<p>
If true, the resume flag indicates that the transfer is being used to reassociate an
unsettled delivery from a dissociated link endpoint. See
<xref name="resuming-deliveries"/> for more details.
</p>
<p>
The receiver MUST ignore resumed deliveries that are not in its local unsettled map. The
sender MUST NOT send resumed transfers for deliveries not in its local unsettled map.
</p>
<p>
If a resumed delivery spans more than one transfer performative, then the resume flag
MUST be set to true on the first transfer of the resumed delivery. For subsequent
transfers for the same delivery the resume flag may be set to true, or may be omitted.
</p>
<p>
In the case where the exchange of unsettled maps makes clear that all message data has
been successfully transferred to the receiver, and that only the final state (and
potentially settlement) at the sender needs to be conveyed, then a resumed delivery may
carry no payload and instead act solely as a vehicle for carrying the terminal state of
the delivery at the sender.
</p>
</doc>
</field>
<field name="aborted" type="boolean" default="false"
label="indicates that the Message is aborted">
<doc>
<p>
Aborted Messages should be discarded by the recipient (any payload within the frame
carrying the performative MUST be ignored). An aborted Message is implicitly settled.
</p>
</doc>
</field>
<field name="batchable" type="boolean" default="false" label="batchable hint">
<doc>
<p>
If true, then the issuer is hinting that there is no need for the peer to urgently
communicate updated delivery state. This hint may be used to artificially increase the
amount of batching an implementation uses when communicating delivery states, and
thereby save bandwidth.
</p>
<p>
If the message being delivered is too large to fit within a single frame, then the
setting of batchable to true on any of the <xref name="transfer"/> performatives for the
delivery is equivalent to setting batchable to true for all the <xref name="transfer"/>
performatives for the delivery.
</p>
<p>
The batchable value does not form part of the transfer state, and is not retained if
a link is suspended and subsequently resumed.
</p>
</doc>
</field>
</type>
<!-- - Frame: disposition - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="disposition" source="list" provides="frame"
label="inform remote peer of delivery state changes">
<doc>
<p>
The disposition frame is used to inform the remote peer of local changes in the state of
deliveries. The disposition frame may reference deliveries from many different links
associated with a session, although all links MUST have the directionality indicated by
the specified <i>role</i>.
</p>
<p>
Note that it is possible for a disposition sent from sender to receiver to refer to a
delivery which has not yet completed (i.e. a delivery which is spread over multiple
frames and not all frames have yet been sent). The use of such interleaving is
discouraged in favor of carrying the modified state on the next <xref name="transfer"/>
performative for the delivery.
</p>
<p>
The disposition performative may refer to deliveries on links that are no longer attached.
As long as the links have not been closed or detached with an error then the deliveries
are still "live" and the updated state MUST be applied.
</p>
</doc>
<descriptor name="amqp:disposition:list" code="0x00000000:0x00000015"/>
<field name="role" type="role" mandatory="true" label="directionality of disposition">
<doc>
<p>
The role identifies whether the disposition frame contains information
about <i>sending</i> link endpoints or <i>receiving</i> link endpoints.
</p>
</doc>
</field>
<field name="first" type="delivery-number" mandatory="true" label="lower bound of deliveries">
<doc>
<p>
Identifies the lower bound of delivery-ids for the deliveries in this set.
</p>
</doc>
</field>
<field name="last" type="delivery-number" label="upper bound of deliveries">
<doc>
<p>
Identifies the upper bound of delivery-ids for the deliveries in this set. If not set,
this is taken to be the same as <i>first</i>.
</p>
</doc>
</field>
<field name="settled" type="boolean" default="false" label="indicates deliveries are settled">
<doc>
<p>
If true, indicates that the referenced deliveries are considered settled by the issuing
endpoint.
</p>
</doc>
</field>
<field name="state" type="*" requires="delivery-state" label="indicates state of deliveries">
<doc>
<p>
Communicates the state of all the deliveries referenced by this disposition.
</p>
</doc>
</field>
<field name="batchable" type="boolean" default="false" label="batchable hint">
<doc>
<p>
If true, then the issuer is hinting that there is no need for the peer to urgently
communicate the impact of the updated delivery states. This hint may be used to
artificially increase the amount of batching an implementation uses when communicating
delivery states, and thereby save bandwidth.
</p>
</doc>
</field>
</type>
<!-- - Frame: detach - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="detach" source="list" provides="frame"
label="detach the Link Endpoint from the Session" >
<doc>
<p>
Detach the Link Endpoint from the Session. This un-maps the handle and makes it available
for use by other Links.
</p>
</doc>
<descriptor name="amqp:detach:list" code="0x00000000:0x00000016"/>
<field name="handle" type="handle" mandatory="true"
label="the local handle of the link to be detached"/>
<field name="closed" type="boolean" default="false"
label="if true then the sender has closed the link">
<doc>
<p>See <xref name="closing-a-link"/>.</p>
</doc>
</field>
<field name="error" type="error" label="error causing the detach">
<doc>
<p>
If set, this field indicates that the Link is being detached due to an error condition.
The value of the field should contain details on the cause of the error.
</p>
</doc>
</field>
</type>
<!-- - Frame: end - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="end" source="list" provides="frame" label="end the Session">
<doc>
<p>Indicates that the Session has ended.</p>
</doc>
<descriptor name="amqp:end:list" code="0x00000000:0x00000017"/>
<field name="error" type="error" label="error causing the end">
<doc>
<p>
If set, this field indicates that the Session is being ended due to an error condition.
The value of the field should contain details on the cause of the error.
</p>
</doc>
</field>
</type>
<!-- - Frame: close - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -->
<type class="composite" name="close" source="list" provides="frame"
label="signal a Connection close">
<doc>
<p>
Sending a close signals that the sender will not be sending any more frames (or bytes of
any other kind) on the Connection. Orderly shutdown requires that this frame MUST be
written by the sender. It is illegal to send any more frames (or bytes of any other kind)
after sending a close frame.
</p>
</doc>
<descriptor name="amqp:close:list" code="0x00000000:0x00000018"/>
<field name="error" type="error" label="error causing the close">
<doc>
<p>
If set, this field indicates that the Connection is being closed due to an error
condition. The value of the field should contain details on the cause of the error.
</p>
</doc>
</field>
</type>
</section>
<section name="definitions" label="supporting definitions">
<type class="restricted" name="role" source="boolean" label="link endpoint role">
<choice name="sender" value="false" />
<choice name="receiver" value="true" />
</type>
<type class="restricted" name="sender-settle-mode" source="ubyte"
label="settlement policy for a Sender">
<choice name="unsettled" value="0">
<doc>
<p>
The Sender will send all deliveries initially unsettled to the Receiver.
</p>
</doc>
</choice>
<choice name="settled" value="1">
<doc>
<p>
The Sender will send all deliveries settled to the Receiver.
</p>
</doc>
</choice>
<choice name="mixed" value="2">
<doc>
<p>
The Sender may send a mixture of settled and unsettled deliveries to the Receiver.
</p>
</doc>
</choice>
</type>
<type class="restricted" name="receiver-settle-mode" source="ubyte"
label="settlement policy for a Receiver">
<choice name="first" value="0">
<doc>
<p>
The Receiver will spontaneously settle all incoming transfers.
</p>
</doc>
</choice>
<choice name="second" value="1">
<doc>
<p>
The Receiver will only settle after sending the <xref name="disposition"/> to the Sender
and receiving a <xref name="disposition"/> indicating settlement of the delivery from
the sender.
</p>
</doc>
</choice>
</type>
<type class="restricted" name="handle" source="uint" label="the handle of a Link">
<doc>
<p>
An alias established by the <xref type="type" name="attach"/> frame and subsequently used
by endpoints as a shorthand to refer to the Link in all outgoing frames. The two endpoints
may potentially use different handles to refer to the same Link. Link handles may be
reused once a Link is closed for both send and receive.
</p>
</doc>
</type>
<type class="restricted" name="seconds" source="uint" label="a duration measured in seconds"/>
<type class="restricted" name="milliseconds" source="uint"
label="a duration measured in milliseconds"/>
<type class="restricted" name="delivery-tag" source="binary">
<doc>
<p>
A delivery-tag may be up to 32 octets of binary data.
</p>
</doc>
</type>
<type class="restricted" name="delivery-number" source="sequence-no"/>
<type class="restricted" name="transfer-number" source="sequence-no"/>
<type class="restricted" name="sequence-no" source="uint" label="32-bit RFC-1982 serial number">
<doc>
<p>
A sequence-no encodes a serial number as defined in RFC-1982. The arithmetic, and
operators for these numbers are defined by RFC-1982.
</p>
</doc>
</type>
<type class="restricted" name="message-format" source="uint" label="32-bit message format code">
<doc>
<p>
The upper three octets of a message format code identify a particular message format. The
lowest octet indicates the version of said message format. Any given version of a format
is forwards compatible with all higher versions.
</p>
<picture><![CDATA[
3 octets 1 octet
+----------------+---------+
| message format | version |
+----------------+---------+
| |
msb lsb
]]>
</picture>
</doc>
</type>
<type class="restricted" name="ietf-language-tag" source="symbol"
label="an IETF language tag as defined by BCP 47">
<doc>
<p>
IETF language tags are abbreviated language codes as defined in the IETF Best Current
Practice <xref type="extern" name="http://www.rfc-editor.org/rfc/bcp/bcp47.txt">BCP-47
</xref> (incorporating <xref type="extern"
name="http://www.rfc-editor.org/rfc/rfc5646.txt">RFC-5646</xref>). A list of registered
subtags is maintained in the <xref type="extern"
name="http://www.iana.org/assignments/language-subtag-registry">IANA Language Subtag
Registry</xref>.
</p>
<p>
All AMQP implementations should understand at the least the IETF language tag
<i>en-US</i> (note that this uses a hyphen separator, not an underscore).
</p>
</doc>
</type>
<type class="restricted" name="fields" source="map" label="a mapping from field name to value">
<doc>
<p>
The <i>fields</i> type is a map where the keys are restricted to be of type <xref
name="symbol"/> (this excludes the possibility of a null key). There is no further
restriction implied by the <i>fields</i> type on the allowed values for the entries or the
set of allowed keys.
</p>
</doc>
</type>
<type class="composite" name="error" source="list" label="details of an error">
<descriptor name="amqp:error:list" code="0x00000000:0x0000001d"/>
<field name="condition" type="symbol" requires="error-condition" mandatory="true"
label="error condition">
<doc>
<p>A symbolic value indicating the error condition.</p>
</doc>
</field>
<field name="description" type="string" label="descriptive text about the error condition">
<doc>
<p>
This text supplies any supplementary details not indicated by the condition field. This
text can be logged as an aid to resolving issues.
</p>
</doc>
</field>
<field name="info" type="fields" label="map carrying information about the error condition"/>
</type>
<type class="restricted" name="amqp-error" source="symbol" provides="error-condition"
label="shared error conditions">
<choice name="internal-error" value="amqp:internal-error">
<doc>
<p>
An internal error occurred. Operator intervention may be required to resume normal
operation.
</p>
</doc>
</choice>
<choice name="not-found" value="amqp:not-found">
<doc>
<p>A peer attempted to work with a remote entity that does not exist.</p>
</doc>
</choice>
<choice name="unauthorized-access" value="amqp:unauthorized-access">
<doc>
<p>
A peer attempted to work with a remote entity to which it has no access due to security
settings.
</p>
</doc>
</choice>
<choice name="decode-error" value="amqp:decode-error">
<doc>
<p>Data could not be decoded.</p>
</doc>
</choice>
<choice name="resource-limit-exceeded" value="amqp:resource-limit-exceeded">
<doc>
<p>A peer exceeded its resource allocation.</p>
</doc>
</choice>
<choice name="not-allowed" value="amqp:not-allowed">
<doc>
<p>
The peer tried to use a frame in a manner that is inconsistent with the semantics
defined in the specification.
</p>
</doc>
</choice>
<choice name="invalid-field" value="amqp:invalid-field">
<doc>
<p>
An invalid field was passed in a frame body, and the operation could not proceed.
</p>
</doc>
</choice>
<choice name="not-implemented" value="amqp:not-implemented">
<doc>
<p>The peer tried to use functionality that is not implemented in its partner.</p>
</doc>
</choice>
<choice name="resource-locked" value="amqp:resource-locked">
<doc>
<p>
The client attempted to work with a server entity to which it has no access because
another client is working with it.
</p>
</doc>
</choice>
<choice name="precondition-failed" value="amqp:precondition-failed">
<doc>
<p>
The client made a request that was not allowed because some precondition failed.
</p>
</doc>
</choice>
<choice name="resource-deleted" value="amqp:resource-deleted">
<doc>
<p>A server entity the client is working with has been deleted.</p>
</doc>
</choice>
<choice name="illegal-state" value="amqp:illegal-state">
<doc>
<p>
The peer sent a frame that is not permitted in the current state of the Session.
</p>
</doc>
</choice>
<choice name="frame-size-too-small" value="amqp:frame-size-too-small">
<doc>
<p>
The peer cannot send a frame because the smallest encoding of the performative with the
currently valid values would be too large to fit within a frame of the agreed maximum
frame size. When transferring a message the message data can be sent in multiple <xref
name="transfer"/> frames thereby avoiding this error. Similarly when attaching a link
with a large unsettled map the endpoint may make use of the incomplete-unsettled flag to
avoid the need for overly large frames.
</p>
</doc>
</choice>
</type>
<type class="restricted" name="connection-error" source="symbol" provides="error-condition"
label="symbols used to indicate connection error conditions">
<choice name="connection-forced" value="amqp:connection:forced">
<doc>
<p>
An operator intervened to close the Connection for some reason. The client may retry at
some later date.
</p>
</doc>
</choice>
<choice name="framing-error" value="amqp:connection:framing-error">
<doc>
<p>A valid frame header cannot be formed from the incoming byte stream.</p>
</doc>
</choice>
<choice name="redirect" value="amqp:connection:redirect">
<doc>
<p>
The container is no longer available on the current connection. The peer should
attempt reconnection to the container using the details provided in the info map.
</p>
<dl>
<dt>hostname</dt>
<dd>
<p>
the hostname of the container. This is the value that should be supplied in the
<i>hostname</i> field of the <xref name="open"/> frame, and suring the SASL and
TLS negotiation (if used).
</p>
</dd>
<dt>network-host</dt>
<dd>
<p>
the DNS hostname or IP address of the machine hosting the container.
</p>
</dd>
<dt>port</dt>
<dd>
<p>
the port number on the machine hosting the container.
</p>
</dd>
</dl>
</doc>
</choice>
</type>
<type class="restricted" name="session-error" source="symbol" provides="error-condition"
label="symbols used to indicate session error conditions">
<choice name="window-violation" value="amqp:session:window-violation">
<doc>
<p>
The peer violated incoming window for the session.
</p>
</doc>
</choice>
<choice name="errant-link" value="amqp:session:errant-link">
<doc>
<p>
Input was received for a link that was detached with an error.
</p>
</doc>
</choice>
<choice name="handle-in-use" value="amqp:session:handle-in-use">
<doc>
<p>
An attach was received using a handle that is already in use for an attached Link.
</p>
</doc>
</choice>
<choice name="unattached-handle" value="amqp:session:unattached-handle">
<doc>
<p>
A frame (other than attach) was received referencing a handle which is not currently
in use of an attached Link.
</p>
</doc>
</choice>
</type>
<type class="restricted" name="link-error" source="symbol" provides="error-condition"
label="symbols used to indicate link error conditions">
<choice name="detach-forced" value="amqp:link:detach-forced">
<doc>
<p>
An operator intervened to detach for some reason.
</p>
</doc>
</choice>
<choice name="transfer-limit-exceeded" value="amqp:link:transfer-limit-exceeded">
<doc>
<p>The peer sent more Message transfers than currently allowed on the link.</p>
</doc>
</choice>
<choice name="message-size-exceeded" value="amqp:link:message-size-exceeded">
<doc>
<p>The peer sent a larger message than is supported on the link.</p>
</doc>
</choice>
<choice name="redirect" value="amqp:link:redirect">
<doc>
<p>The address provided cannot be resolved to a terminus at the current container.
The info map may contain the following information to allow the client to locate
the attach to the terminus.
</p>
<dl>
<dt>hostname</dt>
<dd>
<p>
the hostname of the container hosting the terminus. This is the value that should
be supplied in the <i>hostname</i> field of the <xref name="open"/> frame, and
during SASL and TLS negotiation (if used).
</p>
</dd>
<dt>network-host</dt>
<dd>
<p>
the DNS hostname or IP address of the machine hosting the container.
</p>
</dd>
<dt>port</dt>
<dd>
<p>
the port number on the machine hosting the container.
</p>
</dd>
<dt>address</dt>
<dd>
<p>
the address of the terminus at the container.
</p>
</dd>
</dl>
</doc>
</choice>
<choice name="stolen" value="amqp:link:stolen">
<doc>
<p>
The link has been attached elsewhere, causing the existing attachment to be forcibly
closed.
</p>
</doc>
</choice>
</type>
<definition name="PORT" value="5672" label="the IANA assigned port number for AMQP">
<doc>
<p>
The standard AMQP port number that has been assigned by IANA for TCP, UDP, and SCTP.
</p>
</doc>
<doc>
<p>
There are currently no UDP or SCTP mappings defined for AMQP. The port number is reserved
for future transport mappings to these protocols.
</p>
</doc>
</definition>
<definition name="SECURE-PORT" value="5671" label="the IANA assigned port number
for secure AMQP (amqps)">
<doc>
<p>
The standard AMQP port number that has been assigned by IANA for secure TCP using TLS.
</p>
</doc>
<doc>
<p>
Implementations listening on this port should NOT expect a protocol handshake before TLS
is negotiated.
</p>
</doc>
</definition>
<definition name="MAJOR" value="1" label="major protocol version" />
<definition name="MINOR" value="0" label="minor protocol version" />
<definition name="REVISION" value="0" label="protocol revision" />
<definition name="MIN-MAX-FRAME-SIZE" value="512"
label="the lower bound for the agreed maximum frame size (in bytes)">
<doc>
<p>
During the initial Connection negotiation, the two peers must agree upon a maximum frame
size. This constant defines the minimum value to which the maximum frame size can be set.
By defining this value, the peers can guarantee that they can send frames of up to this
size until they have agreed a definitive maximum frame size for that
Connection.
</p>
</doc>
</definition>
</section>
</amqp>