4. Message Transmission
CoAP messages are exchanged asynchronously between CoAP endpoints. They are used to transport CoAP requests and responses, the semantics of which are defined in Section 5.
As CoAP is bound to unreliable transports such as UDP, CoAP messages may arrive out of order, appear duplicated, or go missing without notice. For this reason, CoAP implements a lightweight reliability mechanism, without trying to re-create the full feature set of a transport like TCP. It has the following features:
-
Simple stop-and-wait retransmission reliability with exponential back-off for Confirmable messages.
-
Duplicate detection for both Confirmable and Non-confirmable messages.
4.1. Messages and Endpoints
A CoAP endpoint is the source or destination of a CoAP message. The specific definition of an endpoint depends on the transport being used for CoAP. For the transports defined in this specification, the endpoint is identified depending on the security mode used (see Section 9): With no security, the endpoint is solely identified by an IP address and a UDP port number. With other security modes, the endpoint is identified as defined by the security mode.
There are different types of messages. The type of a message is specified by the Type field in the CoAP Header.
Orthogonal to the message type, a message may carry a request, a response, or be Empty. This is signaled by the Request/Response Code field in the CoAP Header and is relevant to the request/response model. Possible values for this field are maintained in the CoAP Code Registries (Section 12.1).
An Empty message has the Code field set to 0.00. The Token Length field MUST be set to 0 and bytes of data MUST NOT be present after the Message ID field. If there are any bytes, they MUST be processed as a message format error.
4.2. Messages Transmitted Reliably
The reliable transmission of a message is initiated by marking the message as Confirmable in the CoAP header. A Confirmable message always carries either a request or response, unless it is used only to elicit a Reset message, in which case it is Empty. A recipient MUST either (a) acknowledge a Confirmable message with an Acknowledgement message or (b) reject the message if the recipient lacks context to process the message properly, including the case where the message is Empty, uses a code with a reserved class (1, 6, or 7), or has a message format error. Rejecting a Confirmable message is effected by sending a matching Reset message and otherwise ignoring it. The Acknowledgement message MUST echo the Message ID of the Confirmable message and MUST carry a response or be Empty (see Section 5.2.1 and Section 5.2.2). The Reset message MUST echo the Message ID of the Confirmable message and MUST be Empty. Rejecting an Acknowledgement or Reset message (including the cases where an Acknowledgement carries a request or a code with a reserved class, or a Reset message is not Empty) is effected by silently ignoring it. More generally, recipients of Acknowledgements and Reset messages MUST NOT respond with either Acknowledgements or Reset messages.
The sender retransmits the Confirmable message at exponentially increasing intervals, until it receives an acknowledgement (or Reset message) or runs out of attempts.
Retransmission is controlled by two things that a CoAP endpoint MUST keep track of for each Confirmable message it sends while waiting for an acknowledgement (or reset): a timeout and a retransmission counter. For a new Confirmable message, the initial timeout is set to a random duration (often not an integer number of seconds) between ACK_TIMEOUT and (ACK_TIMEOUT * ACK_RANDOM_FACTOR) (see Section 4.8), and the retransmission counter is set to 0. When the timeout is triggered and the retransmission counter is less than MAX_RETRANSMIT, the message is retransmitted, the retransmission counter is incremented, and the timeout is doubled. If the retransmission counter reaches MAX_RETRANSMIT on a timeout, or if the endpoint receives a Reset message, then the attempt to transmit the message is canceled and the application process informed of failure. On the other hand, if the endpoint receives an acknowledgement in time, transmission is considered successful.
There are no guarantees on the accuracy of the clock for implementing the above binary exponential back-off algorithm. In particular, an endpoint may be shut down for an extended period of time, during which it may miss a retransmission opportunity or timeout. Upon restarting, it should continue retransmitting according to the back-off mechanism. If this is problematic for any reason, the endpoint should cancel the transmission attempt when going to sleep and retransmit when waking up. In any case, the minimum interval between any two retransmissions is ACK_TIMEOUT, and the entire sequence of (re)transmissions MUST stay within MAX_TRANSMIT_SPAN (see Section 4.8.2), even if this means the sender may miss a transmission opportunity.
A CoAP endpoint that sent a Confirmable message MAY give up in attempting to obtain an ACK even before the MAX_RETRANSMIT counter value is reached. For example, the application has canceled the request because it no longer needs a response, or there is some other indication that the CON message did arrive. In particular, a CoAP request message may have elicited a separate response, in which case the requester will know the only the ACK was lost and it would serve no purpose to retransmit the request. However, a responder MUST NOT in turn rely on this cross-layer behavior from a requester, i.e., it MUST retain state to create the ACK for the request, if needed, even if a Confirmable response was already acknowledged by the requester.
Another reason for giving up retransmission can be the receipt of ICMP errors. If retrying to reach a destination that is found unreachable by ICMP, implementations SHOULD NOT retry the transmission of a Confirmable message before an exponentially increasing wait time. The wait time SHOULD be chosen similarly to the retransmission timeouts, except that it SHOULD NOT be randomized.
4.3. Messages Transmitted without Reliability
Some messages do not require an acknowledgement. This is particularly true for messages that are repeated regularly for application requirements, such as repeated readings from a sensor, where eventual success is sufficient.
As a more lightweight alternative, a message may be transmitted less reliably by marking the message as Non-confirmable. A Non-confirmable message always carries either a request or a response and MUST NOT be Empty. A recipient does not acknowledge a Non-confirmable message. If the recipient lacks context to process the message properly (including the case where the message is Empty, uses a code with a reserved class (1, 6, or 7), or has a message format error), it MUST reject the message. Rejecting a Non-confirmable message MAY involve sending a matching Reset message, and apart from the Reset message the rejected message MUST be silently ignored.
At the CoAP level, there is no way for the sender to detect if a Non-confirmable message was received or not. A sender MAY choose to transmit multiple copies of a Non-confirmable message within MAX_TRANSMIT_SPAN (subject to the constraints in Section 4.7, in particular if no response is received then subject to the PROBING_RATE constraint), or the network may duplicate the message in transmission. To enable the recipient to act only once on the message, Non-confirmable messages specify a Message ID as well. (This Message ID is drawn from the same number space as the Message IDs for Confirmable messages.)
Summarizing Section 4.2 and Section 4.3, the four message types can be used as in Table 1. The column titles in this table are the message types. "R" denotes a request, "r" a response. "A" denotes that the message is used to carry an acknowledgement, "E" that it is Empty. Combinations marked "-" are not used in normal operation, except that CON can be used with Empty to elicit a Reset message, i.e., for a "CoAP ping".
+----------+-----+-----+-----+-----+
| | CON | NON | ACK | RST |
+----------+-----+-----+-----+-----+
| Request | R | R | - | - |
| Response | r | r | r | - |
| Empty | * | - | A/E | E |
+----------+-----+-----+-----+-----+
Table 1: Message Type Usage
4.4. Message Correlation
An Acknowledgement or Reset message is related to a Confirmable message or Non-confirmable message by means of a Message ID along with additional address information of the corresponding endpoint. The Message ID is a 16-bit unsigned integer that is generated by the sender of a Confirmable or Non-confirmable message and included in the CoAP header. The recipient MUST echo the Message ID in the Acknowledgement or Reset message.
The same Message ID MUST NOT be reused (with the same endpoint) within the EXCHANGE_LIFETIME (Section 4.8.2).
Implementation Note: Several implementation strategies can be employed for generating Message IDs. In the simplest case, a CoAP endpoint generates Message IDs by keeping a single Message ID variable, which is changed each time a new Confirmable or Non-confirmable message is sent, regardless of the destination address or port. Endpoints dealing with large numbers of transactions could keep multiple Message ID variables, for example per prefix or destination address. (Note that some receiving endpoints may not be able distinguish unicast and multicast packets addressed to it, so endpoints generating Message IDs need to make sure these don't overlap.) It is strongly recommended that the initial value of the variable (e.g., on startup) be randomized, in order to make successful off-path attacks on the protocol less likely.
For an Acknowledgement or Reset message to match a Confirmable or Non-confirmable message, the Message ID and source endpoint of the Acknowledgement or Reset message MUST match the Message ID and destination endpoint of the Confirmable or Non-confirmable message.
4.5. Message Deduplication
A recipient might receive the same Confirmable message (as indicated by Message ID and source endpoint) multiple times within the EXCHANGE_LIFETIME (Section 4.8.2), for example, when its Acknowledgement was lost or did not reach the original sender before the first timeout. The recipient SHOULD acknowledge each duplicate copy of a Confirmable message using the same Acknowledgement or Reset message but SHOULD process any request or response in the message only once. An exception to this is the case where the request carried in the Confirmable message is idempotent (see Section 5.1) or can be handled in an idempotent fashion. Examples of relaxed message deduplication:
-
A server might relax the requirement that it answers all retransmissions of an idempotent request with the same response (Section 4.2), so that it does not have to maintain state for the Message ID. For example, an implementation might want to process duplicate transmissions of a GET, PUT, or DELETE request as separate requests if the effort incurred from duplicate processing is less expensive than keeping track of previous responses would be.
-
A constrained server may even want to relax this requirement for some non-idempotent requests if the application semantics make this trade-off favorable. For example, if the result of a POST request is just the creation of some short-lived state at the server, it may be less expensive to incur this effort multiple times for a request than to keep track of whether a previous transmission of the same request was already acted upon.
A recipient might receive the same Non-confirmable message (as indicated by Message ID and source endpoint) multiple times within NON_LIFETIME (Section 4.8.2). As a general rule (that may be relaxed based on the specific semantics of a message), the recipient SHOULD silently ignore any duplicated Non-confirmable message and SHOULD process any request or response in the message only once.
4.6. Message Size
While it is beneficial to keep CoAP messages small enough to fit into a single link-layer packet (see Section 1), this is a matter of implementation quality. The CoAP specification itself only provides an upper bound for message size. Messages larger than an IP packet would cause undesirable packet fragmentation. A CoAP message, appropriately encapsulated, SHOULD fit within a single IP packet (i.e., avoid IP fragmentation) and (by fitting into one UDP payload) obviously needs to fit within a single IP datagram. If the Path MTU is not known for a destination, an IP MTU of 1280 bytes SHOULD be assumed; if nothing is known about the size of the headers, good upper bounds are 1152 bytes for the message size and 1024 bytes for the payload size.
Implementation Note: CoAP's message size parameters work well with today's predominant IP maximum transmission unit (MTU) of 1500 bytes. However, with IPv4, it is hard to absolutely ensure there is no IP fragmentation. If support for IPv4 on unusual networks is a consideration, implementations may want to limit themselves to more conservative IPv4 datagram sizes such as 576 bytes; per [RFC0791], the absolute minimum for the IP MTU of IPv4 is as low as 68 bytes, which would leave only 40 bytes for a UDP payload minus security overhead. Implementations extremely focused on this set of problems might also set the IPv4 DF bit and perform some form of path MTU discovery [RFC4821]; however, this is generally unnecessary in realistic use cases for CoAP. What may be more important in many constrained networks is the potential for adaptation layer fragmentation (e.g., the 6LoWPAN L2 packet size is limited to 127 bytes including various overheads); this may motivate implementations to be conservative in their packet sizes and to move to block-wise transfer [BLOCK] when approaching three-digit message sizes.
Message size is also of great importance to implementations on constrained nodes. Many implementations will need to allocate a buffer for incoming messages. An implementation may be too constrained to allow for the above upper bound. If an implementation is too constrained to allow for a message size that does not employ DTLS security, it can apply the following implementation strategy: An implementation receiving a datagram into a buffer that is too small will typically have the choice of either discarding the datagram entirely or retaining the partial datagram for further processing. The receiving implementation is therefore typically able to determine the tail part of the datagram that was discarded and to retrieve the initial part. Therefore, at least the CoAP header and the options (if not all of the payload) are likely to fit within the buffer. A server can therefore fully interpret a request and return a 4.13 (Request Entity Too Large; see Section 5.9.2.9) response code if the payload was truncated. A client sending an idempotent request and receiving a response that is larger than would fit in its buffer can repeat the request with an appropriate value for the Block Option [BLOCK].
4.7. Congestion Control
The basic congestion control mechanism provided by CoAP is the exponential back-off mechanism in Section 4.2.
In order not to cause congestion, clients (including proxies) MUST strictly limit the number of simultaneous outstanding interactions to a given server (including proxies) to NSTART. An outstanding interaction is either a CON for which an ACK has not yet been received and is still expected (message layer) or a request for which neither a response nor an acknowledgement message has yet been received and is still expected (which may both occur at the same time, counting as one outstanding interaction). The default value of NSTART for this specification is 1.
Further optimizations and considerations for CoAP congestion control are expected in the future, for example, with automatic initialization of the CoAP transmission parameters defined in Section 4.8, which may allow values for NSTART greater than 1.
After EXCHANGE_LIFETIME, a client stops expecting responses to a Confirmable request for which no acknowledgement message was received. The specific algorithm by which a client stops "expecting" a response to an acknowledged Confirmable request or a Non-confirmable request is not defined. Unless modified by further congestion control optimizations, it MUST be chosen in such a way that an endpoint does not exceed an average data rate of PROBING_RATE when sending to another endpoint that does not respond.
Note: CoAP places the onus of congestion control mainly on the clients. However, clients may malfunction or actually be attackers, e.g., to perform amplification attacks (Section 11.3). To limit the damage (to the network and to its own energy resources), a server SHOULD implement some rate limiting for its response transmissions based on reasonable assumptions about application requirements. This is most helpful if the rate limiting is per endpoint (client) and not global. Rate limiting may be difficult to perform on a constrained node; such nodes may simply resort to using a less aggressive value for NSTART (which also helps with both congestion and energy conservation). Servers that are building up state for the clients may want to strictly limit the number of clients they accept.
4.8. Transmission Parameters
Message transmission is controlled by the following parameters:
+-------------------+---------------+
| name | default value |
+-------------------+---------------+
| ACK_TIMEOUT | 2 seconds |
| ACK_RANDOM_FACTOR | 1.5 |
| MAX_RETRANSMIT | 4 |
| NSTART | 1 |
| DEFAULT_LEISURE | 5 seconds |
| PROBING_RATE | 1 byte/second |
+-------------------+---------------+
Table 2: CoAP Protocol Parameters
4.8.1. Changing the Parameters
The values for ACK_TIMEOUT, ACK_RANDOM_FACTOR, MAX_RETRANSMIT, NSTART, DEFAULT_LEISURE (Section 8.2), and PROBING_RATE can be configured to values specific to an application environment (including dynamically adjusted values); however, the method for configuration is out of the scope of this document. It is recommended that an application environment use consistent values for these parameters; the specific effects of operating with inconsistent values in an application environment are outside the scope of this specification.
The transmission parameters have been chosen to be safe for use on the general Internet, where there is a danger of causing congestion. If a configuration desires to use different values, the onus is on the configuration to ensure that congestion is not caused. In particular, decreasing ACK_TIMEOUT below 1 second will violate the guidelines of [RFC5405]. ([RTO-CONSIDER] provides some additional background.) CoAP was designed to enable implementations that do not maintain round-trip-time (RTT) measurements. However, where it is desired to decrease ACK_TIMEOUT significantly or to increase NSTART, this can only be done safely when maintaining such measurements. A configuration MUST NOT decrease ACK_TIMEOUT or increase NSTART without using mechanisms that ensure congestion control safety, which can be defined in the configuration or in a future standards document.
ACK_RANDOM_FACTOR MUST NOT be decreased below 1.0, and it SHOULD have a value that is sufficiently different from 1.0 to provide some protection from synchronization effects.
MAX_RETRANSMIT can be freely adjusted, although a value that is too small will reduce the probability that a Confirmable message is actually received, while values larger than given here will require further adjustments to the time values (see Section 4.8.2).
If the choice of transmission parameters leads to an increase in derived time values (see Section 4.8.2), the configuration mechanism MUST ensure that the adjusted values are also available to all endpoints that are to communicate using these adjusted values.
4.8.2. Time Values Derived from Transmission Parameters
The combination of ACK_TIMEOUT, ACK_RANDOM_FACTOR, and MAX_RETRANSMIT influences the timing of retransmissions, which in turn influences how long certain information items need to be kept by an implementation. To be able to unambiguously reference these derived time values, we give them names as follows:
MAX_TRANSMIT_SPAN: The maximum time from the first transmission of a Confirmable message to its last retransmission. For the default transmission parameters, the value is (2+4+8+16)*1.5 = 45 seconds, or more generally:
ACK_TIMEOUT * ((2 ** MAX_RETRANSMIT) - 1) * ACK_RANDOM_FACTOR
MAX_TRANSMIT_WAIT: The maximum time from the first transmission of a Confirmable message to the time when the sender gives up on receiving an acknowledgement or reset. For the default transmission parameters, the value is (2+4+8+16+32)*1.5 = 93 seconds, or more generally:
ACK_TIMEOUT * ((2 ** (MAX_RETRANSMIT + 1)) - 1) * ACK_RANDOM_FACTOR
In addition, some assumptions need to be made about the characteristics of the network and nodes.
MAX_LATENCY: The maximum time a datagram is expected to take from the start of its transmission to the completion of its reception. This constant is related to the MSL (Maximum Segment Lifetime) of [RFC0793], which is "arbitrarily defined to be 2 minutes" ([RFC0793] glossary, page 81). Note that this is not necessarily smaller than MAX_TRANSMIT_WAIT, as MAX_LATENCY is not intended to describe a situation in which the protocol works well, but the worst-case situation against which the protocol has to guard. We, also arbitrarily, define MAX_LATENCY to be 100 seconds. Apart from being reasonably realistic for most configurations and close to the historic choice for TCP, this value also allows Message ID lifetime timers to be represented in 8 bits (when measured in seconds). In these calculations, there is no assumption that the direction of the transmission is irrelevant (i.e., that the network is symmetric); the value simply needs to be the worst case of the sum of the one-way latencies in both directions. If that asymmetry is not the case, the following calculations are only slightly more complex.
PROCESSING_DELAY: The time a node takes to turn around a Confirmable message into an acknowledgement. We assume that the node will attempt to send an ACK before the sender times out, so as a conservative assumption we set it equal to ACK_TIMEOUT.
MAX_RTT: Maximum round-trip time, or:
(2 * MAX_LATENCY) + PROCESSING_DELAY
From these values, we can derive the following values that are relevant to the protocol operation:
EXCHANGE_LIFETIME: The time from starting to send a Confirmable message to the time when an acknowledgement is no longer expected, i.e., message-layer information about the message exchange can be purged. EXCHANGE_LIFETIME includes a MAX_TRANSMIT_SPAN, a MAX_LATENCY forward, the PROCESSING_DELAY, and a MAX_LATENCY for the way back. Note that if a configuration is chosen where the last wait period (ACK_TIMEOUT * (2 ** MAX_RETRANSMIT), or the difference between MAX_TRANSMIT_SPAN and MAX_TRANSMIT_WAIT) is smaller than MAX_LATENCY, MAX_TRANSMIT_WAIT does not need to be considered -- this is a likely choice, as MAX_LATENCY is a worst-case value unlikely to be met in the real world. In this case, EXCHANGE_LIFETIME simplifies to:
MAX_TRANSMIT_SPAN + (2 * MAX_LATENCY) + PROCESSING_DELAY
or 247 seconds with the default transmission parameters.
NON_LIFETIME: The time from sending a Non-confirmable message to the time its Message ID can be safely reused. If multiple transmission of a NON message is not used, the value for this parameter is simply MAX_LATENCY, or 100 seconds. However, a CoAP sender might send a NON message multiple times, in particular for multicast applications. While the specification does not limit the period of reuse, a receiver needs to be able to reliably detect duplicates at a time scale on the order of MAX_TRANSMIT_SPAN. For this purpose, it is safer to use:
MAX_TRANSMIT_SPAN + MAX_LATENCY
or 145 seconds with the default transmission parameters; however, an implementation that just wants to use a single timeout value for retiring Message IDs can safely use the larger value for EXCHANGE_LIFETIME.
Table 3 lists the derived parameters introduced in this subsection with their default values.
+-------------------+---------------+
| name | default value |
+-------------------+---------------+
| MAX_TRANSMIT_SPAN | 45 s |
| MAX_TRANSMIT_WAIT | 93 s |
| MAX_LATENCY | 100 s |
| PROCESSING_DELAY | 2 s |
| MAX_RTT | 202 s |
| EXCHANGE_LIFETIME | 247 s |
| NON_LIFETIME | 145 s |
+-------------------+---------------+
Table 3: Derived Protocol Parameters