libcoap 4.3.5-develop-146e0bb
Loading...
Searching...
No Matches
coap_query_into_optlist(3)
coap_pdu_options

SYNOPSIS

#include <coap3/coap.h>

coap_optlist_t *coap_new_optlist(uint16_t number, size_t length, const uint8_t *data);

int coap_insert_optlist(coap_optlist_t **optlist_chain, coap_optlist_t *optlist);

void coap_delete_optlist(coap_optlist_t *optlist_chain);

int coap_sort_optlist(coap_optlist_t **optlist_chain);

unsigned int coap_encode_var_safe(uint8_t *buffer, size_t size, unsigned int value);

unsigned int coap_encode_var_safe8(uint8_t *buffer, size_t size, uint64_t value);

int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t **optlist_chain);

size_t coap_add_option(coap_pdu_t *pdu, uint16_t number, size_t length, const uint8_t *data);

int coap_path_into_optlist(const uint8_t *path, size_t length, coap_option_num_t optnum, coap_optlist_t **optlist_chain);

int coap_split_path(const uint8_t *path, size_t length, uint8_t *buffer, size_t *buflen);

int coap_query_into_optlist(const uint8_t *path, size_t length, coap_option_num_t optnum, coap_optlist_t **optlist_chain);

int coap_split_query(const uint8_t *query, size_t length, uint8_t *buffer, size_t *buflen);

For specific (D)TLS library support, link with -lcoap-3-notls, -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls, -lcoap-3-wolfssl or -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default (D)TLS library support.

DESCRIPTION

The CoAP PDU is of the form

--header--|--optional token--|--optional options--|--optional payload--

The terminology used is taken mainly from "RFC7252 1.2. Terminology".

The PDU must be built in the correct order, from left to right. In particular, the options need to be added in the correct numerical option order as they are stored in the PDU using relative numeric offsets from the previous option number.

There are option list functions available where options can be added to a chained list of options and then the chain list is sorted and then be added to the PDU.

Typically for clients, when creating a request, the PDU needs to be created before filling it with the appropriate information.

Typically with a server, the response PDU, with the optional token already added in, will already be created before the response handler is called, and the response PDU will need to be updated as appropriate starting with the optional options. Note that updating the response pdu’s code variable will cause the response pdu to get transmitted. If code does not get updated, and the PDU is of type CONFIRMABLE, then the response PDU is transmitted as an empty ACK packet. The response pdu is always freed off by the underlying library.

For handling situations where the data to be transmitted does not fit into a single packet, see coap_block(3).

For further information on setting up the PDU (other than the options) see coap_pdu_setup(3).

PDU OPTIONS FUNCTIONS

The following is the current list of options with their numeric value

/*
 * The C, U, and N flags indicate the properties
 * Critical, Unsafe, and NoCacheKey, respectively.
 * If U is set, then N has no meaning as per
 * https://rfc-editor.org/rfc/rfc7252#section-5.10
 * and is set to a -.
 * Separately, R is for the options that can be repeated
 *
 * The least significant byte of the option is set as followed
 * as per https://rfc-editor.org/rfc/rfc7252#section-5.4.6
 *
 *   0   1   2   3   4   5   6   7
 * --+---+---+---+---+---+---+---+
 *           | NoCacheKey| U | C |
 * --+---+---+---+---+---+---+---+
 *
 * https://rfc-editor.org/rfc/rfc8613#section-4 goes on to define E, I and U
 * properties Encrypted and Integrity Protected, Integrity Protected Only and
 * Unprotected respectively.  Integrity Protected Only is not currently used.
 *
 * An Option is tagged with CUNREIU with any of the letters replaced with _ if
 * not set, or - for N if U is set (see above) for aiding understanding of the
 * Option.
 */

COAP_OPTION_IF_MATCH        1 /* C__RE__, opaque,    0-8 B, RFC7252 */
COAP_OPTION_URI_HOST        3 /* CU-___U, String,  1-255 B, RFC7252 */
COAP_OPTION_ETAG            4 /* ___RE__, opaque,    1-8 B, RFC7252 */
COAP_OPTION_IF_NONE_MATCH   5 /* C___E__, empty,       0 B, RFC7252 */
COAP_OPTION_OBSERVE         6 /* _U-_E_U, empty/uint,  0 B/0-3 B, RFC7641 */
COAP_OPTION_URI_PORT        7 /* CU-___U, uint,      0-2 B, RFC7252 */
COAP_OPTION_LOCATION_PATH   8 /* ___RE__, String,  0-255 B, RFC7252 */
COAP_OPTION_OSCORE          9 /* C_____U, *,       0-255 B, RFC8613 */
COAP_OPTION_URI_PATH       11 /* CU-RE__, String,  0-255 B, RFC7252 */
COAP_OPTION_CONTENT_FORMAT 12 /* ____E__, uint,      0-2 B, RFC7252 */
/* COAP_OPTION_MAXAGE default 60 seconds if not set */
COAP_OPTION_MAXAGE         14 /* _U-_E_U, uint,      0-4 B, RFC7252 */
COAP_OPTION_URI_QUERY      15 /* CU-RE__, String,  1-255 B, RFC7252 */
COAP_OPTION_HOP_LIMIT      16 /* ______U, uint,        1 B, RFC8768 */
COAP_OPTION_ACCEPT         17 /* C___E__, uint,      0-2 B, RFC7252 */
COAP_OPTION_Q_BLOCK1       19 /* CU__E_U, uint,      0-3 B, RFC8177 */
COAP_OPTION_LOCATION_QUERY 20 /* ___RE__, String,  0-255 B, RFC7252 */
COAP_OPTION_BLOCK2         23 /* CU-_E_U, uint,      0-3 B, RFC7959 */
COAP_OPTION_BLOCK1         27 /* CU-_E_U, uint,      0-3 B, RFC7959 */
COAP_OPTION_SIZE2          28 /* __N_E_U, uint,      0-4 B, RFC7959 */
COAP_OPTION_Q_BLOCK2       31 /* CU_RE_U, uint,      0-3 B, RFC9177 */
COAP_OPTION_PROXY_URI      35 /* CU-___U, String, 1-1034 B, RFC7252 */
COAP_OPTION_PROXY_SCHEME   39 /* CU-___U, String,  1-255 B, RFC7252 */
COAP_OPTION_SIZE1          60 /* __N_E_U, uint,      0-4 B, RFC7252 */
COAP_OPTION_ECHO          252 /* _N__E_U, opaque,   0-40 B, RFC9175 */
COAP_OPTION_NORESPONSE    258 /* _U-_E_U, uint,      0-1 B, RFC7967 */
COAP_OPTION_RTAG          292 /* ___RE_U, opaque,    0-8 B, RFC9175 */

See FURTHER INFORMATION as to how to get the latest list.

Function: coap_new_optlist()

The coap_new_optlist() function returns a newly created optlist entry of type coap_optlist_t*. The number specifies which CoAP option is to be used, and is one of the COAP_OPTION_* definitions. The length is the length of the data of the option, and data points to the content of the option.

NOTE: Where possible, the option data needs to be stripped of leading zeros (big endian) to reduce the amount of data needed in the PDU, as well as in some cases the maximum data size of an option can be exceeded if not stripped and hence be illegal. This is done by using coap_encode_var_safe() or coap_encode_var_safe8().

Function: coap_insert_optlist()

The coap_insert_optlist() function adds the optlist entry onto the end of the optlist_chain. The initial optlist_chain entry needs to be set to NULL before this function is first called. The coap_delete_optlist() function has to be called to free off all the optlist_chain entries.

Function: coap_delete_optlist()

The coap_delete_optlist() function deletes and frees off all the optlist entries in the optlist_chain.

Function: coap_sort_optlist()

The coap_sort_optlist() function sorts the optlist chain pointed to by oplist_chain into ascending option number order (RFC 7252 ordering for delta encoding). The chain is reordered in place. Use this when the list was built with coap_insert_optlist() and you need it ordered before use (for example, before adding options to a PDU manually or for inspection). Returns 1 if sorted successfully, 0 if oplist_chain is NULL or the chain is empty.

NOTE: coap_add_optlist_pdu() sorts internally, so calling coap_sort_optlist() is not required when using that function.

Function: coap_add_optlist_pdu()

The coap_add_optlist_pdu() function sorts all of the entries in optlist_chain into ascending option numeric order and adds all the entries to the pdu. This function does not free off the entries in optlist_chain. This function must be called after adding any token and before adding in the payload data.

Function: coap_add_option()

The coap_add_option() function adds in the specified option of type number with data of length length to the PDU pdu. It is important that options are added to the pdu with number either being the same or greater than the previous option number that was added.

NOTE: Where possible, the option data needs to be stripped of leading zeros (big endian) to reduce the amount of data needed in the PDU, as well as in some cases the maximum data size of an option can be exceeded if not stripped and hence be illegal. This is done by using coap_encode_var_safe() or coap_encode_var_safe8().

Function: coap_encode_var_safe()

The coap_encode_var_safe() function encodes value into buffer which has a size of size in bytes. Normally, the buffer size should be at least the sizeof(int) bytes unless you definitely know less space is required.

Function: coap_encode_var_safe8()

The coap_encode_var_safe8() function encodes 8 byte value into buffer which has a size of size in bytes. Normally, the buffer size should be at least 8 bytes unless you definitely know less space is required.

Function: coap_path_into_optlist()

The coap_path_into_optlist() function splits up path of length length into / separated segments and then appends the optnum option for each segment to optlist_chain. optlist_chain can contain previous optlist entries or the parent has to be initialized to NULL. Any segment that is just "." is not appended. Any segment that is just ".." causes the previous segment (if just added by coap_path_into_optlist()) to be removed from optlist_chain. Any %<hex><hex> definitions are replaced by the actual byte. optnum should be one of COAP_OPTION_URI_PATH or COAP_OPTION_LOCATION_PATH.

Function: coap_split_path()

The coap_split_path() function splits up path of length length into / separated segments and places the result in buffer which has a size of buflen with a dummy option separating each path segment. buflen needs to be preset with the size of buffer before the function call, and then buflen is updated with the actual size of buffer used. buflen needs to be at least length with an extra 2 bytes per segment to handle long segments. Any segment that is just "." is not appended. Any segment that is just ".." causes the previous segment (if any) to be removed from buffer. Any %<hex><hex> definitions are replaced by the actual byte. The return value indicates the number of components that individual COAP_OPTION_URI_PATH (or COAP_OPTION_LOCATION_PATH) options need to be created for.

Note: For simplicity, use coap_path_into_optlist() instead.

Function: coap_query_into_optlist()

The coap_query_into_optlist() function splits up query of length length into & separated segments and then appends the optnum option for each segment to optlist_chain. optlist_chain can contain previous optlist entries or the parent has to be initialized to NULL. optnum should be one of COAP_OPTION_URI_QUERY or COAP_OPTION_LOCATION_QUERY.

Function: coap_split_query()

The coap_split_query() function splits up query of length length into & separated segments and places the result in buffer which has a size of buflen with a dummy option separating each query segment. buflen needs to be preset with the size of buffer before the function call, and then buflen is updated with the actual size of buffer used. buflen needs to be at least length with an extra 2 bytes per segment to handle long segments. The return value indicates the number of components that individual COAP_OPTION_URI_QUERY (or COAP_OPTION_LOCATION_QUERY) options need to be created for.

Note: For simplicity, use coap_query_into_optlist() instead.

PDU OPTIONS - LIBCOAP HANDLING

Most of the options are under the control of the applications, but the following are primarily used internally by libcoap.

COAP_OPTION_BLOCK1 and COAP_OPTION_BLOCK2

These Block options are used when a large body needs to be split up into multiple payloads. Following the introduction of coap_context_set_block_mode(3), libcoap can internally handle the setting of these options (see coap_block(3)). Applications can continue to include these options to set hint block size values.

It is recommended that coap_context_set_block_mode(context, COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY) is used to reduce the programming requirements for block handling within the applications.

COAP_OPTION_ECHO

This option can be set by the server application to indicate that the state of the client’s freshness is confirmed. The libcoap client logic will detect the use of the Echo option by the server and reflect back the Echo value in the next request without involving the client application. The opaque option Echo may be seen by the client application.

COAP_OPTION_ETAG

This option is normally set by the server libcoap logic when sending back multiple payloads so that the (libcoap logic) client can re-assemble the correct body.

COAP_OPTION_HOP_LIMIT

When using proxy logic, the value of the Hop-Limit option is decremented by one for each proxy hop. If the count decrements to zero, then a 5.08 (Hop Limit Reached) error code is returned to the sender. The initial count is 16, unless the client application sets its own limit using the Hop-Limit option.

COAP_OPTION_RTAG

This option is set by the libcoap client logic when transmitting multiple bodies with multiple payloads so that the (libcoap logic) server can differentiate and re-assemble the correct body.

COAP_OPTION_SIZE1 and COAP_OPTION_SIZE2

These options are added by the libcoap logic to provide a size (Size1 by libcoap client logic, Size2 by libcoap server logic) indication to the recipient of the size of the large body that is to be transferred. See coap_block(3).

COAP_OPTION_OSCORE

This option is used during OSCORE enabled communications. It should not be set by any application, but is used internally. See coap_oscore(3) for further information on how to set up OSCORE.

RETURN VALUES

coap_new_optlist() returns a newly created optlist or NULL if there is a malloc failure.

coap_insert_optlist(), coap_sort_optlist() and coap_add_optlist_pdu() return 0 on failure, 1 on success.

coap_encode_var_safe() returns either the length of bytes encoded (which can be 0 when encoding 0) or 0 on failure.

coap_encode_var_safe8() returns either the length of bytes encoded (which can be 0 when encoding 0) or 0 on failure.

coap_add_option() returns the size of option added, or 0 on failure.

coap_path_into_optlist() and coap_query_into_optlist() return 1 on success or 0 on failure.

coap_split_path() and coap_split_query() return the number of components found.

EXAMPLES

Setup PDU and Transmit

#include <coap3/coap.h>

#include <string.h>

static int
build_send_pdu(coap_context_t *context, coap_session_t *session,
               uint8_t msgtype, uint8_t request_code, const char *path,
               const char *query, unsigned char *data, size_t length,
               int observe) {
  coap_pdu_t *pdu;
  uint8_t buf[8];
  size_t buflen;
  coap_optlist_t *optlist_chain = NULL;
  /* Remove (void) definition if variable is used */
  (void)context;

  /* Create the pdu with the appropriate options */
  pdu = coap_pdu_init(msgtype, request_code, coap_new_message_id(session),
                      coap_session_max_pdu_size(session));
  if (!pdu)
    return 0;

  /*
   * Create unique token for this request for handling unsolicited /
   * delayed responses
   */
  coap_session_new_token(session, &buflen, buf);
  if (!coap_add_token(pdu, buflen, buf)) {
    coap_log_debug("cannot add token to request\n");
    goto error;
  }

  if (path) {
    /* Add in the Uri-Path options */
    if (!coap_path_into_optlist((const uint8_t *)path, strlen(path),
                                COAP_OPTION_URI_PATH, &optlist_chain))
      goto error;
  }

  if (query) {
    /* Add in the Uri-Query options */
    if (!coap_query_into_optlist((const uint8_t *)query, strlen(query),
                                 COAP_OPTION_URI_QUERY, &optlist_chain))
      goto error;
  }

  if (request_code == COAP_REQUEST_GET && observe) {
    /* Indicate that we want to observe this resource */
    if (!coap_insert_optlist(&optlist_chain,
                             coap_new_optlist(COAP_OPTION_OBSERVE,
                                              coap_encode_var_safe(buf, sizeof(buf),
                                                  COAP_OBSERVE_ESTABLISH), buf)
                            ))
      goto error;
  }

  /* ... Other code / options etc. ... */

  /* Add in all the options (after internal sorting) to the pdu */
  if (!coap_add_optlist_pdu(pdu, &optlist_chain))
    goto error;

  if (data && length) {
    /* Add in the specified data */
    if (!coap_add_data(pdu, length, data))
      goto error;
  }

  if (coap_send(session, pdu) == COAP_INVALID_MID)
    goto error;
  return 1;

error:

  if (pdu)
    coap_delete_pdu(pdu);
  return 0;

}

BUGS

Please raise an issue on GitHub at https://github.com/obgm/libcoap/issues to report any bugs.

Please raise a Pull Request at https://github.com/obgm/libcoap/pulls for any fixes.

AUTHORS

The libcoap project <libcoap-developers@lists.sourceforge.net>

coap_query_into_optlist(3)