libcoap 4.3.5-develop-146e0bb
Loading...
Searching...
No Matches
coap_session_init_token(3)
coap_pdu_setup

SYNOPSIS

#include <coap3/coap.h>

coap_pdu_t *coap_new_pdu(coap_pdu_type_t type, coap_pdu_code_t code, coap_session_t *session);

coap_pdu_t *coap_pdu_init(coap_pdu_type_t type, coap_pdu_code_t code, coap_mid_t message_id, size_t max_size);

uint16_t coap_new_message_id(coap_session_t *session);

void coap_session_init_token(coap_session_t *session, size_t length, const uint8_t *token);

void coap_session_new_token(coap_session_t *session, size_t *length, uint8_t *token);

int coap_add_token(coap_pdu_t *pdu, size_t length, const uint8_t *data);

int coap_add_data(coap_pdu_t *pdu, size_t length, const uint8_t *data);

void coap_add_data_blocked_response(const coap_pdu_t *request, coap_pdu_t *response, uint16_t media_type, int maxage, size_t length, const uint8_t *data);

void coap_pdu_set_mid(coap_pdu_t *pdu, coap_mid_t mid);

void coap_pdu_set_code(coap_pdu_t *pdu, coap_pdu_code_t code);

void coap_pdu_set_type(coap_pdu_t *pdu, coap_pdu_type_t type);

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).

See coap_pdu_options(3) for handling the PDU options.

PDU CREATE AND HEADER FUNCTIONS

Function: coap_new_pdu()

The coap_new_pdu() function returns a newly created PDU of type coap_pdu_t.

The type is one of the following

COAP_MESSAGE_CON Set the _PDU_ to be of type confirmable.
COAP_MESSAGE_NON Set the _PDU_ to be of type non-confirmable.
COAP_MESSAGE_ACK Set the _PDU_ to be of type acknowledge (for internal use).
COAP_MESSAGE_RST Set the _PDU_ to be of type reset.

The code is one of the following

COAP_EMPTY_CODE                               0.00
COAP_REQUEST_CODE_GET                         0.01
COAP_REQUEST_CODE_POST                        0.02
COAP_REQUEST_CODE_PUT                         0.03
COAP_REQUEST_CODE_DELETE                      0.04
COAP_REQUEST_CODE_FETCH                       0.05
COAP_REQUEST_CODE_PATCH                       0.06
COAP_REQUEST_CODE_IPATCH                      0.07
COAP_RESPONSE_CODE_OK                         2.00
COAP_RESPONSE_CODE_CREATED                    2.01
COAP_RESPONSE_CODE_DELETED                    2.02
COAP_RESPONSE_CODE_VALID                      2.03
COAP_RESPONSE_CODE_CHANGED                    2.04
COAP_RESPONSE_CODE_CONTENT                    2.05
COAP_RESPONSE_CODE_CONTINUE                   2.31
COAP_RESPONSE_CODE_BAD_REQUEST                4.00
COAP_RESPONSE_CODE_UNAUTHORIZED               4.01
COAP_RESPONSE_CODE_BAD_OPTION                 4.02
COAP_RESPONSE_CODE_FORBIDDEN                  4.03
COAP_RESPONSE_CODE_NOT_FOUND                  4.04
COAP_RESPONSE_CODE_NOT_ALLOWED                4.05
COAP_RESPONSE_CODE_NOT_ACCEPTABLE             4.06
COAP_RESPONSE_CODE_INCOMPLETE                 4.08
COAP_RESPONSE_CODE_CONFLICT                   4.09
COAP_RESPONSE_CODE_PRECONDITION_FAILED        4.12
COAP_RESPONSE_CODE_REQUEST_TOO_LARGE          4.13
COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT 4.15
COAP_RESPONSE_CODE_UNPROCESSABLE              4.22
COAP_RESPONSE_CODE_TOO_MANY_REQUESTS          4.29
COAP_RESPONSE_CODE_INTERNAL_ERROR             5.00
COAP_RESPONSE_CODE_NOT_IMPLEMENTED            5.01
COAP_RESPONSE_CODE_BAD_GATEWAY                5.02
COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE        5.03
COAP_RESPONSE_CODE_GATEWAY_TIMEOUT            5.04
COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED     5.05
COAP_RESPONSE_CODE_HOP_LIMIT_REACHED          5.08
COAP_SIGNALING_CODE_CSM                       7.01
COAP_SIGNALING_CODE_PING                      7.02
COAP_SIGNALING_CODE_PONG                      7.03
COAP_SIGNALING_CODE_RELEASE                   7.04
COAP_SIGNALING_CODE_ABORT                     7.05

and session is used to set up other default values.

Function: coap_pdu_init()

The coap_pdu_init() function does the same work as coap_new_pdu() but gives the additional ability to define the default values for message_id and max_size that coap_new_pdu() creates.

The message_id must be unique per request (which is not the same as the token), and must not be reused within EXCHANGE_LIFETIME (usually 247 seconds). To automate this, the function coap_new_message_id(session) should be called.

At the CoAP protocol level, requests and responses are matched by message_id which is why it needs to be unique. At the application level, for "separate" responses, the initial empty ACK response matches the message_id of the request (handled by libcoap) but the actual response has the same token as the request and this must be used for the match. For "piggybacked" responses the token must still be used as the valid match for request and response. and the message_id just happens to match (but unsafe in case the server is sending back a "separate" response).

The max_size parameter defines the maximum size of a PDU and is usually determined by calling coap_session_max_pdu_size(session);

Function: coap_new_message_id()

The coap_new_message_id() function returns the next message id to use for sending a new request message.

NOTE: For reliable messages RFC8323, this will always return 0.

Function: coap_pdu_set_mid()

The coap_pdu_set_mid() function is used to set the message id mid in the PDU pdu.

Function: coap_pdu_set_code()

The coap_pdu_set_code() function is used to set the code code in the PDU pdu.

Function: coap_pdu_set_type()

The coap_pdu_set_type() function is used to set the type of the PDU pdu.

NOTE: A PDU does not need to be created by the server application to send back a response. The libcoap server logic creates the initial PDU with COAP_EMPTY_CODE, appropriate message_id, matching token and potentially some other options before calling the appropriate request handler (See coap_register_request_handler(3)).

PDU TOKEN FUNCTIONS

Function: coap_session_init_token()

The coap_session_init_token() function is used to initialize the starting token of length for the session.

NOTE: this only takes the first 8 bytes of the token if extended tokens are being used (RFC8974).

Function: coap_session_new_token()

The coap_session_new_token() function is used to obtain the next available token of length for the session. Note that the same token must be used for doing an observe cancellation that was used for doing the observe registration. Otherwise tokens should be unique for each request/response so that they can be correctly matched.

NOTE: Only a token of up to 8 bytes is returned.

Function: coap_add_token()

The coap_add_token() function adds in the specified token’s data of length length to the PDU pdu. The maximum (but impractical due to PDU sizes) length of the token is 65804 bytes. If anything more than 8, the remote peer needs to support extended tokens for this to work. Adding the token must be done before any options or data are added. This function must only be called once per pdu, and must not be called in the appropriate request handler as the token has already been added into the skeletal response PDU.

If a token is not added, then the token in the PDU is zero length, but still a valid token which is used for matching. The exception is an empty ACK packet.

NOTE: The token provided by the client application may not be the same as used internally by libcoap - for example when doing data transmission where the body of data is spread over multiple payloads (see coap_block(3)). However, when the data transfers complete, the application will receive the corrected token in the response PDU.

PDU OPTIONS FUNCTIONS

See coap_pdu_options(3).

PDU PAYLOAD FUNCTIONS

Function: coap_add_data()

The coap_add_data() function adds in the specified payload data of length length to the PDU pdu. Adding the payload data must be done after any token or options are added. This function must only be called once per pdu.

NOTE: coap_add_data() cannot add data that will exceed the available space within a single CoAP PDU. It is recommended that coap_add_data_large_request(3) or coap_add_data_large_response(3) (depending on whether pdu is a request or response) is used instead if there is a possibility of the PDU space being insufficient. See coap_block(3).

Function: coap_add_data_blocked_response()

The coap_add_data_blocked_response() function adds in the appropriate part of the payload data of length length to the PDU pdu. It should be used as a direct replacement for coap_add_data() if it is possible that the data will not fit into a single pdu. It also adds in the appropriate CoAP options to handle Block-Wise transfer. This function is usually used for a server’s GET / FETCH response. The request and response are the same parameters for the registered GET / FETCH resource handler. The media_type is for the format of the data and maxage defines the lifetime of the response. If set to -1, then the Max-Age option does not get included. This function must only be called once per pdu. It is the responsibility of the client to recognize that it has only received a part of the data and request the next block (with the appropriate Block options) from the server. Returning the next requested block is handled by this function.

NOTE: This function has been superseded by coap_add_data_large_response(3). See coap_block(3).

RETURN VALUES

coap_new_pdu() and coap_pdu_init() return a newly created PDU or NULL if there is a malloc or parameter failure.

coap_add_token() and coap_add_data() return 0 on failure, 1 on success.

coap_new_message_id() returns the next CoAP message ID to use.

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;

}

Resource Request Handler Response PDU Update

#include <coap3/coap.h>

#include <stdio.h>
#include <string.h>
#include <time.h>

static void
hnd_get_time(coap_resource_t *resource, coap_session_t *session,
             const coap_pdu_t *request, const coap_string_t *query,
             coap_pdu_t *response) {
  unsigned char buf[40];
  size_t len;
  time_t now;

  /* ... Additional analysis code for resource, request pdu etc.  ... */

  /* After analysis, generate a suitable response */

  now = time(NULL);

  if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) {
    /* Output secs since Jan 1 1970 */
    len = snprintf((char *)buf, sizeof(buf), "%lu", now);
  } else {
    /* Output human-readable time */
    struct tm *tmp;
    tmp = gmtime(&now);
    if (!tmp) {
      /* If 'now' is not valid */
      coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
      return;
    }
    len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp);
  }
  coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
  /*
   * Invoke coap_add_data_large_response() to do all the hard work.
   *
   * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in
   * Define how long this response is valid for (secs) - 1 - to add in.
   * Etag Option added internally with unique value as param set to 0
   *
   * Observe Option added internally if needed within the function
   * Block2 Option added internally if output too large
   * Size2 Option added internally
   */
  coap_add_data_large_response(resource, session, request, response,
                               query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0,
                               len,
                               buf, NULL, NULL);

  /*
   * Returning from the request handler will cause the response to be
   * sent off (assuming coap_pdu_set_code() has been called), unless
   * the response is confirmable and the code is COAP_EMPTY_CODE which
   * will cause an empty ACK packet to be returned).
   */

}

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_session_init_token(3)