Skip to content

Commit

Permalink
RFC9175: Add in support for the Echo and Request-Tag options
Browse files Browse the repository at this point in the history
A unique Request-Tag is added to any PUT/POST/FETCH request that contains
a large body.  The server is then able to differentiate between concurrent
sending of large data using the same session.

If a server responds with a 4.01 and includes an Echo option, then the libcoap
client retransmits the request adding in the received Echo option with the same
value.

If the server responds normally with an Echo option, then the next request
from the libcoap client (internally added by libcoap) will contain that Echo
option.

It is the responsibility of the server application to add in the Echo
option if required and validate the next request unless the Echo is triggered
by OSCORE (RFC8613 Appendix B.1.2).
  • Loading branch information
mrdeep1 committed Jun 17, 2022
1 parent 20f15a1 commit 44df810
Show file tree
Hide file tree
Showing 15 changed files with 265 additions and 92 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@ The following RFCs are supported

* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option

* RFC9175: CoAP: Echo, Request-Tag, and Token Processing

There is (D)TLS support for the following libraries

* OpenSSL (Minimum version 1.1.0) [PKI, PSK and PKCS11]
Expand Down
2 changes: 2 additions & 0 deletions doc/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ The following RFCs are supported

* RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option

* RFC9175: CoAP: Echo, Request-Tag, and Token Processing

There is (D)TLS support for the following libraries

* OpenSSL (Minimum version 1.1.0) [PKI, PSK and PKCS11]
Expand Down
19 changes: 10 additions & 9 deletions include/coap3/block.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* block.h -- block transfer
*
* Copyright (C) 2010-2012,2014-2015 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2022 Jon Shallow <supjps-libcoap@jpshallow.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*
Expand All @@ -24,7 +25,7 @@
/**
* @ingroup application_api
* @defgroup block Block Transfer
* API for handling PDUs using CoAP BLOCK options (RFC7959)
* API for handling PDUs using CoAP Block options (RFC7959)
* @{
*/

Expand Down Expand Up @@ -239,7 +240,7 @@ coap_block_build_body(coap_binary_t *body_data, size_t length,
/**
* Adds the appropriate part of @p data to the @p response pdu. If blocks are
* required, then the appropriate block will be added to the PDU and sent.
* Adds a ETAG option that is the hash of the entire data if the data is to be
* Adds a ETag option that is the hash of the entire data if the data is to be
* split into blocks
* Used by a request handler.
*
Expand Down Expand Up @@ -287,15 +288,15 @@ typedef void (*coap_release_large_data_t)(coap_session_t *session,
* Used for a client request.
*
* If the data spans multiple PDUs, then the data will get transmitted using
* BLOCK1 option with the addition of the SIZE1 option.
* Block1 option with the addition of the Size1 and Request-Tag options.
* The underlying library will handle the transmission of the individual blocks.
* Once the body of data has been transmitted (or a failure occurred), then
* @p release_func (if not NULL) will get called so the application can
* de-allocate the @p data based on @p app_data. It is the responsibility of
* the application not to change the contents of @p data until the data
* transfer has completed.
*
* There is no need for the application to include the BLOCK1 option in the
* There is no need for the application to include the Block1 option in the
* @p pdu.
*
* coap_add_data_large_request() (or the alternative coap_add_data_large_*()
Expand Down Expand Up @@ -332,21 +333,21 @@ int coap_add_data_large_request(coap_session_t *session,
*
* If all the data can be transmitted in a single PDU, this is functionally
* the same as coap_add_data() except @p release_func (if not NULL) will get
* invoked after data transmission. The MEDIA_TYPE, MAXAGE and ETAG options may
* be added in as appropriate.
* invoked after data transmission. The Content-Format, Max-Age and ETag
* options may be added in as appropriate.
*
* Used by a server request handler to create the response.
*
* If the data spans multiple PDUs, then the data will get transmitted using
* BLOCK2 (response) option with the addition of the SIZE2 and ETAG
* Block2 (response) option with the addition of the Size2 and ETag
* options. The underlying library will handle the transmission of the
* individual blocks. Once the body of data has been transmitted (or a
* failure occurred), then @p release_func (if not NULL) will get called so the
* application can de-allocate the @p data based on @p app_data. It is the
* responsibility of the application not to change the contents of @p data
* until the data transfer has completed.
*
* There is no need for the application to include the BLOCK2 option in the
* There is no need for the application to include the Block2 option in the
* @p pdu.
*
* coap_add_data_large_response() (or the alternative coap_add_data_large_*()
Expand All @@ -361,7 +362,7 @@ int coap_add_data_large_request(coap_session_t *session,
* @param request The requesting pdu.
* @param response The response pdu.
* @param query The query taken from the (original) requesting pdu.
* @param media_type The format of the data.
* @param media_type The content format of the data.
* @param maxage The maxmimum life of the data. If @c -1, then there
* is no maxage.
* @param etag ETag to use if not 0.
Expand Down
7 changes: 4 additions & 3 deletions include/coap3/coap_block_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
* coap_block_internal.h -- Structures, Enums & Functions that are not
* exposed to application programming
*
* Copyright (C) 2010-2021 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2021 Jon Shallow <supjps-libcoap@jpshallow.com>
* Copyright (C) 2010-2022 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2021-2022 Jon Shallow <supjps-libcoap@jpshallow.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*
Expand Down Expand Up @@ -191,7 +191,8 @@ int coap_handle_request_put_block(coap_context_t *context,
#endif /* COAP_SERVER_SUPPORT */

#if COAP_CLIENT_SUPPORT
int coap_handle_response_send_block(coap_session_t *session, coap_pdu_t *rcvd);
int coap_handle_response_send_block(coap_session_t *session, coap_pdu_t *sent,
coap_pdu_t *rcvd);

int coap_handle_response_get_block(coap_context_t *context,
coap_session_t *session,
Expand Down
6 changes: 3 additions & 3 deletions include/coap3/coap_cache.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/* coap_cache.h -- Caching of CoAP requests
*
* Copyright (C) 2020 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2020-2022 Olaf Bergmann <bergmann@tzi.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*
Expand Down Expand Up @@ -50,7 +50,7 @@ typedef enum coap_cache_record_pdu_t {
* for an explanation of CoAP cache keys.
*
* Specific CoAP options can be removed from the cache-key. Examples of
* this are the BLOCK1 and BLOCK2 options - which make no real sense including
* this are the Block1 and Block2 options - which make no real sense including
* them in a client or server environment, but should be included in a proxy
* caching environment where things are cached on a per block basis.
* This is done globally by calling the coap_cache_ignore_options()
Expand Down Expand Up @@ -78,7 +78,7 @@ coap_cache_key_t *coap_cache_derive_key(const coap_session_t *session,
* for an explanation of CoAP cache keys.
*
* Specific CoAP options can be removed from the cache-key. Examples of
* this are the BLOCK1 and BLOCK2 options - which make no real sense including
* this are the Block1 and Block2 options - which make no real sense including
* them in a client or server environment, but should be included in a proxy
* caching environment where things are cached on a per block basis.
* This is done individually by specifying @p cache_ignore_count and
Expand Down
3 changes: 2 additions & 1 deletion include/coap3/coap_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* coap_event.h -- libcoap Event API
*
* Copyright (C) 2016 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2021-2022 Jon Shallow <supjps-libcoap@jpshallow.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*
Expand Down Expand Up @@ -54,7 +55,7 @@ typedef enum coap_event_t {
COAP_EVENT_SESSION_FAILED = 0x2003,

/**
* (Q-)BLOCK receive errors
* (Q-)Block receive errors
*/
COAP_EVENT_PARTIAL_BLOCK = 0x3001,

Expand Down
4 changes: 3 additions & 1 deletion include/coap3/coap_session_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* coap_session_internal.h -- Structures, Enums & Functions that are not
* exposed to application programming
*
* Copyright (C) 2010-2019 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2010-2022 Olaf Bergmann <bergmann@tzi.org>
*
* SPDX-License-Identifier: BSD-2-Clause
*
Expand Down Expand Up @@ -145,7 +145,9 @@ struct coap_session_t {
uint8_t doing_first; /**< Set if doing client's first request */
uint8_t proxy_session; /**< Set if this is an ongoing proxy session */
uint8_t delay_recursive; /**< Set if in coap_client_delay_first() */
uint32_t tx_rtag; /**< Next Request-Tag number to use */
uint64_t tx_token; /**< Next token number to use */
coap_bin_const_t *echo; /**< Echo value to send with next request */
};

#if COAP_SERVER_SUPPORT
Expand Down
3 changes: 3 additions & 0 deletions include/coap3/pdu.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
* pdu.h -- CoAP message structure
*
* Copyright (C) 2010-2014 Olaf Bergmann <bergmann@tzi.org>
* Copyright (C) 2021-2022 Jon Shallow <supjps-libcoap@jpshallow.com>
*
* SPDX-License-Identifier: BSD-2-Clause
*
Expand Down Expand Up @@ -130,7 +131,9 @@ typedef enum coap_request_t {
#define COAP_OPTION_PROXY_URI 35 /* CU-___U, String, 1-1034 B, RFC7252 */
#define COAP_OPTION_PROXY_SCHEME 39 /* CU-___U, String, 1-255 B, RFC7252 */
#define COAP_OPTION_SIZE1 60 /* __N_E_U, uint, 0-4 B, RFC7252 */
#define COAP_OPTION_ECHO 252 /* _N__E_U, opaque, 0-40 B, RFC9175 */
#define COAP_OPTION_NORESPONSE 258 /* _U-_E_U, uint, 0-1 B, RFC7967 */
#define COAP_OPTION_RTAG 292 /* ___RE_U, opaque, 0-8 B, RFC9175 */

#define COAP_MAX_OPT 65535 /**< the highest option number we know */

Expand Down
2 changes: 2 additions & 0 deletions man/coap.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ See

"RFC8768: Constrained Application Protocol (CoAP) Hop-Limit Option"

"RFC9175: CoAP: Echo, Request-Tag, and Token Processing"

for further information.

BUGS
Expand Down
18 changes: 9 additions & 9 deletions man/coap_block.txt.in
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ In RAM constrained environments, option 2 may be the preferred method.
This man page focuses on getting libcoap to do all the work, not how to do it
all in the application.

However, if the client supplies a BLOCK1 or BLOCK2 Option in the PDU where the
However, if the client supplies a Block1 or Block2 Option in the PDU where the
block number is not 0, this is assumed to be a random access request and any
other blocks will not be requested by libcoap even if instructed otherwise.

Expand Down Expand Up @@ -167,7 +167,7 @@ If COAP_BLOCK_USE_LIBCOAP is set, then any PDUs presented to the application
handlers will get the tokens set back to the initiating token so that requests
can be matched with responses even if different tokens had to be used for the
series of packet interchanges. Furthermore, if COAP_BLOCK_SINGLE_BODY is set,
then the PDU that presents the entire body will have any BLOCKx option removed.
then the PDU that presents the entire body will have any BlockX option removed.

*NOTE:* COAP_BLOCK_USE_LIBCOAP must be set if libcoap is to do all the
block tracking and requesting, otherwise the application will have to do all
Expand All @@ -180,7 +180,7 @@ but supports the transmission of data that has a body size that is potentially
larger than can be fitted into a single client request PDU. The specified
payload _data_ of length _length_ is associated with the _session_ with the
first block of data added to the PDU _pdu_ along with the appropriate CoAP
options such as BLOCK1, and SIZE1 if the data does not fit in
options such as Block1, Size1 and Request-Tag if the data does not fit in
a single PDU.

When the block receipt has been acknowledged by the peer, the library
Expand Down Expand Up @@ -216,15 +216,15 @@ NULL, the callback function is called once the final block of _data_ has been
transmitted. The user-defined parameter _app_ptr_ is the same value that was
passed to *coap_add_data_large_response*().

It also adds in the appropriate CoAP options such as BLOCK2, SIZE2 and ETAG to
It also adds in the appropriate CoAP options such as Block2, Size2 and ETag to
handle block-wise transfer if the data does not fit in a single PDU.

_resource_, _query_, _session_, _request_, and _response_ are the same
parameters as in the called resource handler that invokes
*coap_add_data_large_response*(). If _etag_ is 0, then a unique ETag value will
be generated, else is the ETag value to use.
The _media_type_ is for the format of the _data_ and _maxage_ defines the
lifetime of the response. If _maxage_ is set to -1, then the MAXAGE option
lifetime of the response. If _maxage_ is set to -1, then the Max-Age option
does not get included (which indicates the default value of 60 seconds
according to RFC 7252).

Expand Down Expand Up @@ -444,10 +444,10 @@ const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
* Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in
* Define how long this response is valid for (secs) - 1 - to add in.
*
* OBSERVE Option added internally if needed within the function
* BLOCK2 Option added internally if output too large
* SIZE2 Option added internally
* ETAG Option added internally
* Observe Option added internally if needed within the function
* Block2 Option added internally if output too large
* Size2 Option added internally
* ETag Option added internally
*/
coap_add_data_large_response(resource, session, request, response,
query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0,
Expand Down
Loading

0 comments on commit 44df810

Please sign in to comment.