The properties of the Q-Block1 and Q-Block2 options are shown in
Table 1. The formatting of this table follows the one used in Table 4 of
Section 5.10 of
RFC 7252. The C, U, N, and R columns indicate the properties Critical, UnSafe, NoCacheKey, and Repeatable, which are defined in
Section 5.4 of
RFC 7252. Only the Critical and UnSafe columns are marked for the Q-Block1 option. The Critical, UnSafe, and Repeatable columns are marked for the Q-Block2 option. As these options are UnSafe, NoCacheKey has no meaning and so is marked with a dash.
No. |
C |
U |
N |
R |
Name |
Format |
Length |
Default |
19 |
x |
x |
- |
|
Q-Block1 |
uint |
0-3 |
(none) |
31 |
x |
x |
- |
x |
Q-Block2 |
uint |
0-3 |
(none) |
Table 1: CoAP Q-Block1 and Q-Block2 Option Properties
The Q-Block1 and Q-Block2 options can be present in both the request and response messages. The Q-Block1 option pertains to the request payload, and the Q-Block2 option pertains to the response payload. When the Content-Format option is present together with the Q-Block1 or Q-Block2 option, the option applies to the body, not to the payload (i.e., it must be the same for all payloads of the same body).
The Q-Block1 option is useful with the payload-bearing (e.g., POST, PUT, FETCH, PATCH, and iPATCH) requests and their responses.
The Q-Block2 option is useful, for example, with GET, POST, PUT, FETCH, PATCH, and iPATCH requests and their payload-bearing responses (response codes 2.01, 2.02, 2.04, and 2.05) (
Section 5.5 of
RFC 7252).
A CoAP endpoint (or proxy)
MUST support either both or neither of the Q-Block1 and Q-Block2 options.
If the Q-Block1 option is present in a request or the Q-Block2 option is returned in a response, this indicates a block-wise transfer and describes how this specific block-wise payload forms part of the entire body being transferred. If it is present in the opposite direction, it provides additional control on how that payload will be formed or was processed.
To indicate support for Q-Block2 responses, the CoAP client
MUST include the Q-Block2 option in a GET or similar request (e.g., FETCH), the Q-Block2 option in a PUT or similar request (e.g., POST), or the Q-Block1 option in a PUT or similar request so that the server knows that the client supports this Q-Block functionality should it need to send back a body that spans multiple payloads. Otherwise, the server would use the Block2 option (if supported) to send back a message body that is too large to fit into a single IP packet [
RFC 7959].
How a client decides whether it needs to include a Q-Block1 or Q-Block2 option can be driven by a local configuration parameter, triggered by an application (e.g., DOTS), etc. Such considerations are out of the scope of this document.
Implementation of the Q-Block1 and Q-Block2 options is intended to be optional. However, when a Q-Block1 or Q-Block2 option is present in a CoAP message, it
MUST be processed (or the message rejected). Therefore, the Q-Block1 and Q-Block2 options are identified as critical options.
With CoAP over UDP, the way a request message is rejected for critical options depends on the message type. A Confirmable message with an unrecognized critical option is rejected with a 4.02 (Bad Option) response (
Section 5.4.1 of
RFC 7252). A Non-confirmable message with an unrecognized critical option is either rejected with a Reset message or just silently ignored (Sections
5.4.1 and
4.3 of [
RFC 7252]). To reliably get a rejection message, it is therefore
REQUIRED that clients use a Confirmable message for determining support for the Q-Block1 and Q-Block2 options. This Confirmable message can be sent under the base CoAP congestion control setup specified in
Section 4.7 of
RFC 7252 (that is, NSTART does not need to be increased (
Section 7.1)).
The Q-Block1 and Q-Block2 options are unsafe to forward. That is, a CoAP proxy that does not understand the Q-Block1 (or Q-Block2) option must reject the request or response that uses either option (see
Section 5.7.1 of
RFC 7252).
The Q-Block2 option is repeatable when requesting retransmission of missing blocks but not otherwise. Except for that case, any request carrying multiple Q-Block1 (or Q-Block2) options
MUST be handled following the procedure specified in
Section 5.4.5 of
RFC 7252.
The Q-Block1 and Q-Block2 options, like the Block1 and Block2 options, are of both class E and class U for OSCORE processing (
Table 2). The Q-Block1 (or Q-Block2) option
MAY be an Inner or Outer option (
Section 4.1 of
RFC 8613). The Inner and Outer values are therefore independent of each other. The Inner option is encrypted and integrity protected between clients and servers and provides message body identification in case of end-to-end fragmentation of requests. The Outer option is visible to proxies and labels message bodies in case of hop-by-hop fragmentation of requests.
Number |
Name |
E |
U |
19 |
Q-Block1 |
x |
x |
31 |
Q-Block2 |
x |
x |
Table 2: OSCORE Protection of the Q-Block1 and Q-Block2 Options
Note that, if the Q-Block1 or Q-Block2 options are included in a packet as Inner options, the Block1 or Block2 options
MUST NOT be included as Inner options. Similarly, there
MUST NOT be a mix of Q-Block and Block options for the Outer options. Messages that do not adhere to this behavior
MUST be rejected with a 4.02 (Bad Option). The Q-Block and Block options can be mixed across Inner and Outer options, as these are handled independently of each other. For clarity, if OSCORE is not being used, there
MUST NOT be a mix of Q-Block and Block options in the same packet.
The structure of the Q-Block1 and Q-Block2 options follows the structure defined in
Section 2.2 of
RFC 7959.
There is no default value for the Q-Block1 and Q-Block2 options. The absence of one of these options is equivalent to an option value of 0 with respect to the value of block number (NUM) and more bit (M) that could be given in the option, i.e., it indicates that the current block is the first and only block of the transfer (block number is set to 0; M is unset). However, in contrast to the explicit value 0, which would indicate a size of the block (SZX) of 0, and thus a size value of 16 bytes, there is no specific size implied by the absence of the option -- the size is left unspecified. (As for any uint, the explicit value 0 is efficiently indicated by a zero-length option; therefore, this is semantically different from the absence of the option.)
The Q-Block1 option is used when the client wants to send a large amount of data to the server using the POST, PUT, FETCH, PATCH, or iPATCH methods where the data and headers do not fit into a single packet.
When the Q-Block1 option is used, the client
MUST include a Request-Tag option [
RFC 9175]. The Request-Tag value
MUST be the same for all of the requests for the body of data that is being transferred. The Request-Tag is opaque, but the client
MUST ensure that it is unique for every different body of transmitted data.
Implementation Note: It is suggested that the client treats the Request-Tag as an unsigned integer of 8 bytes in length. An implementation may want to consider limiting this to 4 bytes to reduce packet overhead size. The initial Request-Tag value should be randomly generated and then subsequently incremented by the client whenever a new body of data is being transmitted between peers.
Section 4.6 discusses the use of the Size1 option.
For Confirmable transmission, the server continues to acknowledge each packet, but a response is not required (whether separate or piggybacked) until successful receipt of the body by the server. For Non-confirmable transmission, no response is required until either the successful receipt of the body by the server or a timer expires with some of the payloads having not yet arrived. In the latter case, a "retransmit missing payloads" response is needed. For reliable transports (e.g., [
RFC 8323]), a response is not required until successful receipt of the body by the server.
Each individual message that carries a block of the body is treated as a new request (
Section 6).
The client
MUST send the payloads in order of increasing block number, starting from zero, until the body is complete (subject to any congestion control (
Section 7)). In addition, any missing payloads requested by the server must be separately transmitted with increasing block numbers.
The following response codes are used:
-
2.01 (Created)
-
This response code indicates successful receipt of the entire body and that the resource was created. The token to use MUST be one of the tokens that were received in a request for this block-wise exchange. However, it is desirable to provide the one used in the last received request, since that will aid any troubleshooting. The client should then release all of the tokens used for this body. Note that the last received payload might not be the one with the highest block number.
-
2.02 (Deleted)
-
This response code indicates successful receipt of the entire body and that the resource was deleted when using POST (Section 5.8.2 of RFC 7252). The token to use MUST be one of the tokens that were received in a request for this block-wise exchange. However, it is desirable to provide the one used in the last received request. The client should then release all of the tokens used for this body.
-
2.04 (Changed)
-
This response code indicates successful receipt of the entire body and that the resource was updated. The token to use MUST be one of the tokens that were received in a request for this block-wise exchange. However, it is desirable to provide the one used in the last received request. The client should then release all of the tokens used for this body.
-
2.05 (Content)
-
This response code indicates successful receipt of the entire FETCH request body (Section 2 of RFC 8132) and that the appropriate representation of the resource is being returned. The token to use MUST be one of the tokens that were received in a request for this block-wise exchange. However, it is desirable to provide the one used in the last received request.
If the FETCH request includes the Observe option, then the server MUST use the same token as used for the 2.05 (Content) response for returning any triggered Observe responses so that the client can match them up.
The client should then release all of the tokens used for this body apart from the one used for tracking an observed resource.
-
2.31 (Continue)
-
This response code can be used to indicate that all of the blocks up to and including the Q-Block1 option block NUM (all having the M bit set) have been successfully received. The token to use MUST be one of the tokens that were received in a request for this latest MAX_PAYLOADS_SET block-wise exchange. However, it is desirable to provide the one used in the last received request.
The client should then release all of the tokens used for this MAX_PAYLOADS_SET.
A response using this response code MUST NOT be generated for every received Q-Block1 option request. It SHOULD only be generated when all the payload requests are Non-confirmable and a MAX_PAYLOADS_SET has been received by the server. More details about the motivations for this optimization are discussed in Section 7.2.
This response code SHOULD NOT be generated for CON, as this may cause duplicated payloads to unnecessarily be sent.
-
4.00 (Bad Request)
-
This response code MUST be returned if the request does not include a Request-Tag option or a Size1 option but does include a Q-Block1 option.
-
4.02 (Bad Option)
-
This response code MUST be returned for a Confirmable request if the server does not support the Q-Block options. Note that a Reset message may be sent in case of a Non-confirmable request.
-
4.08 (Request Entity Incomplete)
-
As a reminder, this response code returned without content type "application/missing-blocks+cbor-seq" (Section 12.3) is handled as in Section 2.9.2 of RFC 7959.
This response code returned with content type "application/missing-blocks+cbor-seq" indicates that some of the payloads are missing and need to be resent. The client then retransmits the individual missing payloads using the same Request-Tag, Size1, and Q-Block1 options to specify the same NUM, SZX, and M bit values as those sent initially in the original (but not received) packets.
The Request-Tag value to use is determined by taking the token in the 4.08 (Request Entity Incomplete) response, locating the matching client request, and then using its Request-Tag.
The token to use in the 4.08 (Request Entity Incomplete) response MUST be one of the tokens that were received in a request for this block-wise body exchange. However, it is desirable to provide the one used in the last received request. See Section 5 for further information.
If the server has not received all the blocks of a body, but one or more NON payloads have been received, it SHOULD wait for NON_RECEIVE_TIMEOUT (Section 7.2) before sending a 4.08 (Request Entity Incomplete) response.
-
4.13 (Request Entity Too Large)
-
This response code can be returned under conditions similar to those discussed in Section 2.9.3 of RFC 7959.
This response code can be returned if there is insufficient space to create a response PDU with a block size of 16 bytes (SZX = 0) to send back all the response options as appropriate. In this case, the Size1 option is not included in the response.
Further considerations related to the transmission timings of the 4.08 (Request Entity Incomplete) and 2.31 (Continue) response codes are discussed in
Section 7.2.
If a server receives payloads with different Request-Tags for the same resource, it should continue to process all the bodies, as it has no way of determining which is the latest version or which body, if any, the client is terminating the transmission for.
If the client elects to stop the transmission of a complete body, then absent any local policy, the client
MUST "forget" all tracked tokens associated with the body's Request-Tag so that a Reset message is generated for the invalid token in the 4.08 (Request Entity Incomplete) response. On receipt of the Reset message, the server
SHOULD delete the partial body.
If the server receives a duplicate block with the same Request-Tag, it
MUST ignore the payload of the packet but
MUST still respond as if the block was received for the first time.
A server
SHOULD maintain a partial body (missing payloads) for NON_PARTIAL_TIMEOUT (
Section 7.2).
In a request for any block number, an unset M bit indicates the request is just for that block. If the M bit is set, this has different meanings based on the NUM value:
-
NUM is zero:
-
This is a request for the entire body.
-
'NUM modulo MAX_PAYLOADS' is zero, while NUM is not zero:
-
This is used to confirm that the current MAX_PAYLOADS_SET (the latest block having block number NUM-1) has been successfully received and that, upon receipt of this request, the server can continue to send the next MAX_PAYLOADS_SET (the first block having block number NUM). This is the 'Continue' Q-Block-2 and conceptually has the same usage (i.e., continue sending the next set of data) as the use of 2.31 (Continue) for Q-Block1.
-
Any other value of NUM:
-
This is a request for that block and for all of the remaining blocks in the current MAX_PAYLOADS_SET.
If the request includes multiple Q-Block2 options and these options overlap (e.g., combination of M being set (this and later blocks) and unset (this individual block)), resulting in an individual block being requested multiple times, the server
MUST only send back one instance of that block. This behavior is meant to prevent amplification attacks.
The payloads sent back from the server as a response
MUST all have the same ETag (
Section 5.10.6 of
RFC 7252) for the same body. The server
MUST NOT use the same ETag value for different representations of a resource.
The ETag is opaque, but the server
MUST ensure that it is unique for every different body of transmitted data.
Implementation Note: It is suggested that the server treats the ETag as an unsigned integer of 8 bytes in length. An implementation may want to consider limiting this to 4 bytes to reduce packet overhead size. The initial ETag value should be randomly generated and then subsequently incremented by the server whenever a new body of data is being transmitted between peers.
Section 4.6 discusses the use of the Size2 option.
The client may elect to request any detected missing blocks or just ignore the partial body. This decision is implementation specific.
For NON payloads, the client
SHOULD wait for NON_RECEIVE_TIMEOUT (
Section 7.2) after the last received payload before requesting retransmission of any missing blocks. Retransmission is requested by issuing a GET, POST, PUT, FETCH, PATCH, or iPATCH request that contains one or more Q-Block2 options that define the missing block(s). Generally, the M bit on the Q-Block2 option(s)
SHOULD be unset, although the M bit
MAY be set to request this and later blocks from this MAX_PAYLOADS_SET; see
Section 10.2.4 for an example of this in operation. Further considerations related to the transmission timing for missing requests are discussed in
Section 7.2.
The missing block numbers requested by the client
MUST have an increasing block number in each additional Q-Block2 option with no duplicates. The server
SHOULD respond with a 4.00 (Bad Request) to requests not adhering to this behavior. Note that the ordering constraint is meant to force the client to check for duplicates and remove them. This also helps with troubleshooting.
If the client receives a duplicate block with the same ETag, it
MUST silently ignore the payload.
A client
SHOULD maintain a partial body (missing payloads) for NON_PARTIAL_TIMEOUT (
Section 7.2) or as defined by the Max-Age option (or its default of 60 seconds (
Section 5.6.1 of
RFC 7252)), whichever is less. On release of the partial body, the client should then release all of the tokens used for this body apart from the token that is used to track a resource that is being observed.
The ETag option should not be used in the request for missing blocks, as the server could respond with a 2.03 (Valid) response with no payload. It can be used in the request if the client wants to check the freshness of the locally cached body response.
The server
SHOULD maintain a cached copy of the body when using the Q-Block2 option to facilitate retransmission of any missing payloads.
If the server detects partway through a body transfer that the resource data has changed and the server is not maintaining a cached copy of the old data, then the transmission is terminated. Any subsequent missing block requests
MUST be responded to using the latest ETag and Size2 option values with the updated data.
If the server responds during a body update with a different ETag option value (as the resource representation has changed), then the client should treat the partial body with the old ETag as no longer being fresh. The client may then request all of the new data by specifying Q-Block2 with block number '0' and the M bit set.
If the server transmits a new body of data (e.g., a triggered Observe notification) with a new ETag to the same client as an additional response, the client should remove any partially received body held for a previous ETag for that resource, as it is unlikely the missing blocks can be retrieved.
If there is insufficient space to create a response PDU with a block size of 16 bytes (SZX = 0) to send back all the response options as appropriate, a 4.13 (Request Entity Too Large) is returned without the Size1 option.
For Confirmable traffic, the server typically acknowledges the initial request using an Acknowledgment (ACK) with a piggybacked payload and then sends the subsequent payloads of the MAX_PAYLOADS_SET as CON responses. These CON responses are individually ACKed by the client. The server will detect failure to send a packet and
SHOULD terminate the body transfer, but the client can issue, after a MAX_TRANSMIT_SPAN delay, a separate GET, POST, PUT, FETCH, PATCH, or iPATCH for any missing blocks as needed.
For a request that uses Q-Block1, the Observe value [
RFC 7641]
MUST be the same for all the payloads of the same body. This includes any missing payloads that are retransmitted.
For a response that uses Q-Block2, the Observe value
MUST be the same for all the payloads of the same body. This is different from Block2 usage where the Observe value is only present in the first block (
Section 3.4 of
RFC 7959). This includes payloads transmitted following receipt of the 'Continue' Q-Block2 option (
Section 4.4) by the server. If a missing payload is requested by a client, then both the request and response
MUST NOT include the Observe option.
Section 4 of
RFC 7959 defines two CoAP options: Size1 for indicating the size of the representation transferred in requests and Size2 for indicating the size of the representation transferred in responses.
For the Q-Block1 and Q-Block2 options, the Size1 or Size2 option values
MUST exactly represent the size of the data on the body so that any missing data can easily be determined.
The Size1 option
MUST be used with the Q-Block1 option when used in a request and
MUST be present in all payloads of the request, preserving the same value. The Size2 option
MUST be used with the Q-Block2 option when used in a response and
MUST be present in all payloads of the response, preserving the same value.
The behavior is similar to the one defined in
Section 3.3 of
RFC 7959 with Q-Block1 substituted for Block1 and Q-Block2 substituted for Block2.
Servers
MUST ignore multicast requests that contain the Q-Block2 option. As a reminder, the Block2 option can be used as stated in
Section 2.8 of
RFC 7959.