'\" t .\" Title: coap_pdu_setup .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 10/28/2023 .\" Manual: libcoap Manual .\" Source: coap_pdu_setup 4.3.4 .\" Language: English .\" .TH "COAP_PDU_SETUP" "3" "10/28/2023" "coap_pdu_setup 4\&.3\&.4" "libcoap Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" coap_pdu_setup, coap_new_pdu, coap_pdu_init, coap_new_message_id, coap_session_init_token, coap_session_new_token, coap_add_token, coap_new_optlist, coap_insert_optlist, coap_delete_optlist, coap_encode_var_safe, coap_encode_var_safe8, coap_add_optlist_pdu, coap_add_option, coap_add_data, coap_add_data_blocked_response, coap_send, coap_split_path, coap_split_query, coap_pdu_set_mid, coap_pdu_set_code, coap_pdu_set_type \- Setting up CoAP PDUs .SH "SYNOPSIS" .sp \fB#include \fR .sp \fBcoap_pdu_t *coap_new_pdu(coap_pdu_type_t \fR\fB\fItype\fR\fR\fB, coap_pdu_code_t \fR\fB\fIcode\fR\fR\fB, coap_session_t *\fR\fB\fIsession\fR\fR\fB);\fR .sp \fBcoap_pdu_t *coap_pdu_init(coap_pdu_type_t \fR\fB\fItype\fR\fR\fB, coap_pdu_code_t \fR\fB\fIcode\fR\fR\fB, coap_mid_t \fR\fB\fImessage_id\fR\fR\fB, size_t \fR\fB\fImax_size\fR\fR\fB);\fR .sp \fBuint16_t coap_new_message_id(coap_session_t *\fR\fB\fIsession\fR\fR\fB);\fR .sp \fBvoid coap_session_init_token(coap_session_t *\fR\fB\fIsession\fR\fR\fB, size_t \fR\fB\fIlength\fR\fR\fB, const uint8_t *\fR\fB\fItoken\fR\fR\fB);\fR .sp \fBvoid coap_session_new_token(coap_session_t *\fR\fB\fIsession\fR\fR\fB, size_t *\fR\fB\fIlength\fR\fR\fB, uint8_t *\fR\fB\fItoken\fR\fR\fB);\fR .sp \fBint coap_add_token(coap_pdu_t *\fR\fB\fIpdu\fR\fR\fB, size_t \fR\fB\fIlength\fR\fR\fB, const uint8_t *\fR\fB\fIdata\fR\fR\fB);\fR .sp \fBcoap_optlist_t *coap_new_optlist(uint16_t \fR\fB\fInumber\fR\fR\fB, size_t \fR\fB\fIlength\fR\fR\fB, const uint8_t *\fR\fB\fIdata\fR\fR\fB);\fR .sp \fBint coap_insert_optlist(coap_optlist_t **\fR\fB\fIoptlist_chain\fR\fR\fB, coap_optlist_t *\fR\fB\fIoptlist\fR\fR\fB);\fR .sp \fBvoid coap_delete_optlist(coap_optlist_t *\fR\fB\fIoptlist_chain\fR\fR\fB);\fR .sp \fBunsigned int coap_encode_var_safe(uint8_t *\fR\fB\fIbuffer\fR\fR\fB, size_t \fR\fB\fIsize\fR\fR\fB, unsigned int \fR\fB\fIvalue\fR\fR\fB);\fR .sp \fBunsigned int coap_encode_var_safe8(uint8_t *\fR\fB\fIbuffer\fR\fR\fB, size_t \fR\fB\fIsize\fR\fR\fB, uint64_t \fR\fB\fIvalue\fR\fR\fB);\fR .sp \fBint coap_add_optlist_pdu(coap_pdu_t *\fR\fB\fIpdu\fR\fR\fB, coap_optlist_t **\fR\fB\fIoptlist_chain\fR\fR\fB);\fR .sp \fBsize_t coap_add_option(coap_pdu_t *\fR\fB\fIpdu\fR\fR\fB, uint16_t \fR\fB\fInumber\fR\fR\fB, size_t \fR\fB\fIlength\fR\fR\fB, const uint8_t *\fR\fB\fIdata\fR\fR\fB);\fR .sp \fBint coap_add_data(coap_pdu_t *\fR\fB\fIpdu\fR\fR\fB, size_t \fR\fB\fIlength\fR\fR\fB, const uint8_t *\fR\fB\fIdata\fR\fR\fB);\fR .sp \fBvoid coap_add_data_blocked_response(const coap_pdu_t *\fR\fB\fIrequest\fR\fR\fB, coap_pdu_t *\fR\fB\fIresponse\fR\fR\fB, uint16_t \fR\fB\fImedia_type\fR\fR\fB, int \fR\fB\fImaxage\fR\fR\fB, size_t \fR\fB\fIlength\fR\fR\fB, const uint8_t *\fR\fB\fIdata\fR\fR\fB);\fR .sp \fBcoap_mid_t coap_send(coap_session_t *\fR\fB\fIsession\fR\fR\fB, coap_pdu_t *\fR\fB\fIpdu\fR\fR\fB);\fR .sp \fBint coap_split_path(const uint8_t *\fR\fB\fIpath\fR\fR\fB, size_t \fR\fB\fIlength\fR\fR\fB, uint8_t *\fR\fB\fIbuffer\fR\fR\fB, size_t *\fR\fB\fIbuflen\fR\fR\fB);\fR .sp \fBint coap_split_query(const uint8_t *\fR\fB\fIquery\fR\fR\fB, size_t \fR\fB\fIlength\fR\fR\fB, uint8_t *\fR\fB\fIbuffer\fR\fR\fB, size_t *\fR\fB\fIbuflen\fR\fR\fB);\fR .sp \fBvoid coap_pdu_set_mid(coap_pdu_t *\fR\fB\fIpdu\fR\fR\fB, coap_mid_t \fR\fB\fImid\fR\fR\fB);\fR .sp \fBvoid coap_pdu_set_code(coap_pdu_t *\fR\fB\fIpdu\fR\fR\fB, coap_pdu_code_t \fR\fB\fIcode\fR\fR\fB);\fR .sp \fBvoid coap_pdu_set_type(coap_pdu_t *\fR\fB\fIpdu\fR\fR\fB, coap_pdu_type_t \fR\fB\fItype\fR\fR\fB);\fR .sp For specific (D)TLS library support, link with \fB\-lcoap\-3\-notls\fR, \fB\-lcoap\-3\-gnutls\fR, \fB\-lcoap\-3\-openssl\fR, \fB\-lcoap\-3\-mbedtls\fR or \fB\-lcoap\-3\-tinydtls\fR\&. Otherwise, link with \fB\-lcoap\-3\fR to get the default (D)TLS library support\&. .SH "DESCRIPTION" .sp The CoAP PDU is of the form .sp \-\-header\-\-|\-\-optional token\-\-|\-\-optional options\-\-|\-\-optional payload\-\- .sp The terminology used is taken mainly from "RFC7252 1\&.2\&. Terminology"\&. .sp 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\&. .sp 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\&. .sp Typically for clients, when creating a request, the PDU needs to be created before filling it with the appropriate information\&. .sp 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\(cqs 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\&. .sp For handling situations where the data to be transmitted does not fit into a single packet, see \fBcoap_block\fR(3)\&. .SH "PDU CREATE AND HEADER FUNCTIONS" .sp \fBFunction: coap_new_pdu()\fR .sp The \fBcoap_new_pdu\fR() function returns a newly created PDU of type \fIcoap_pdu_t\fR\&. .sp The \fItype\fR is one of the following .sp .if n \{\ .RS 4 .\} .nf 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\&. .fi .if n \{\ .RE .\} .sp The \fIcode\fR is one of the following .sp .if n \{\ .RS 4 .\} .nf 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 .fi .if n \{\ .RE .\} .sp and \fIsession\fR is used to set up other default values\&. .sp \fBFunction: coap_pdu_init()\fR .sp The \fBcoap_pdu_init\fR() function does the same work as \fBcoap_new_pdu\fR() but gives the additional ability to define the default values for \fImessage_id\fR and \fImax_size\fR that \fBcoap_new_pdu\fR() creates\&. .sp The \fImessage_id\fR 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 \fBcoap_new_message_id\fR(\fIsession\fR) should be called\&. .sp At the CoAP protocol level, requests and responses are matched by \fImessage_id\fR which is why it needs to be unique\&. At the application level, for "separate" responses, the initial empty ACK response matches the \fImessage_id\fR 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 \fImessage_id\fR just happens to match (but unsafe in case the server is sending back a "separate" response)\&. .sp The \fImax_size\fR parameter defines the maximum size of a \fIPDU\fR and is usually determined by calling \fBcoap_session_max_pdu_size\fR(session); .sp \fBFunction: coap_new_message_id()\fR .sp The \fBcoap_new_message_id\fR() function returns the next message id to use for sending a new request message\&. .sp \fBNOTE:\fR For reliable messages RFC8323, this will always return 0\&. .sp \fBFunction: coap_pdu_set_mid()\fR .sp The \fBcoap_pdu_set_mid\fR() function is used to set the message id \fImid\fR in the PDU \fIpdu\fR\&. .sp \fBFunction: coap_pdu_set_code()\fR .sp The \fBcoap_pdu_set_code\fR() function is used to set the code \fIcode\fR in the PDU \fIpdu\fR\&. .sp \fBFunction: coap_pdu_set_type()\fR .sp The \fBcoap_pdu_set_type\fR() function is used to set the \fItype\fR of the PDU \fIpdu\fR\&. .sp \fBNOTE:\fR 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 \fBcoap_register_request_handler\fR(3))\&. .SH "PDU TOKEN FUNCTIONS" .sp \fBFunction: coap_session_init_token()\fR .sp The \fBcoap_session_init_token\fR() function is used to initialize the starting \fItoken\fR of \fIlength\fR for the \fIsession\fR\&. .sp \fBNOTE:\fR this only takes the first 8 bytes of the token if extended tokens are being used (RFC8974)\&. .sp \fBFunction: coap_session_new_token()\fR .sp The \fBcoap_session_new_token\fR() function is used to obtain the next available \fItoken\fR of \fIlength\fR for the \fIsession\fR\&. 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\&. .sp \fBNOTE:\fR Only a token of up to 8 bytes is returned\&. .sp \fBFunction: coap_add_token()\fR .sp The \fBcoap_add_token\fR() function adds in the specified token\(cqs \fIdata\fR of length \fIlength\fR to the PDU \fIpdu\fR\&. 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 \fIpdu\fR, and must not be called in the appropriate request handler as the token has already been added into the skeletal response PDU\&. .sp 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\&. .sp \fBNOTE:\fR 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 \fBcoap_block\fR(3))\&. However, when the data transfers complete, the application will receive the corrected token in the response PDU\&. .SH "PDU OPTIONS FUNCTIONS" .sp The following is the current list of options with their numeric value .sp .if n \{\ .RS 4 .\} .nf /* * 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 */ .fi .if n \{\ .RE .\} .sp See FURTHER INFORMATION as to how to get the latest list\&. .sp \fBFunction: coap_new_optlist()\fR .sp The \fBcoap_new_optlist\fR() function returns a newly created \fIoptlist\fR entry of type \fIcoap_optlist_t\fR*\&. The \fInumber\fR specifies which CoAP option is to be used, and is one of the COAP_OPTION_* definitions\&. The \fIlength\fR is the length of the data of the option, and \fIdata\fR points to the content of the option\&. .sp \fBNOTE:\fR 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 \fBcoap_encode_var_safe\fR() or \fBcoap_encode_var_safe8\fR()\&. .sp \fBFunction: coap_insert_optlist()\fR .sp The \fBcoap_insert_optlist\fR() function adds the \fIoptlist\fR entry onto the end of the \fIoptlist_chain\fR\&. The initial \fIoptlist_chain\fR entry needs to be set to NULL before this function is first called\&. The \fBcoap_delete_optlist\fR() function has to be called to free off all the \fIoptlist_chain\fR entries\&. .sp \fBFunction: coap_delete_optlist()\fR .sp The \fBcoap_delete_optlist\fR() function deletes and frees off all the optlist entries in the \fIoptlist_chain\fR\&. .sp \fBFunction: coap_add_optlist_pdu()\fR .sp The \fBcoap_add_optlist_pdu\fR() function sorts all of the entries in \fIoptlist_chain\fR into ascending option numeric order and adds all the entries to the \fIpdu\fR\&. This function does not free off the entries in \fIoptlist_chain\fR\&. This function must be called after adding any token and before adding in the payload data\&. .sp \fBFunction: coap_add_option()\fR .sp The \fBcoap_add_option\fR() function adds in the specified option of type \fInumber\fR with \fIdata\fR of length \fIlength\fR to the PDU \fIpdu\fR\&. It is important that options are added to the \fIpdu\fR with \fInumber\fR either being the same or greater than the previous option \fInumber\fR that was added\&. .sp \fBNOTE:\fR 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 \fBcoap_encode_var_safe\fR() or \fBcoap_encode_var_safe8\fR()\&. .sp \fBFunction: coap_encode_var_safe()\fR .sp The \fBcoap_encode_var_safe\fR() function encodes \fIvalue\fR into \fIbuffer\fR which has a size of \fIsize\fR in bytes\&. Normally, the \fIbuffer\fR size should be at least the sizeof(int) bytes unless you definitely know less space is required\&. .sp \fBFunction: coap_encode_var_safe8()\fR .sp The \fBcoap_encode_var_safe8\fR() function encodes 8 byte \fIvalue\fR into \fIbuffer\fR which has a size of \fIsize\fR in bytes\&. Normally, the \fIbuffer\fR size should be at least 8 bytes unless you definitely know less space is required\&. .sp \fBFunction: coap_split_path()\fR .sp The \fBcoap_split_path\fR() function splits up \fIpath\fR of length \fIlength\fR and places the result in \fIbuffer\fR which has a size of \fIbuflen\fR with the nul character separating each path component\&. \fIbuflen\fR needs to be preset with the size of \fIbuffer\fR before the function call, and then \fIbuflen\fR is updated with the actual size of \fIbuffer\fR used\&. The return value indicates the number of components that individual COAP_OPTION_URI_PATH options need to be created for\&. .sp \fBFunction: coap_split_query()\fR .sp The \fBcoap_split_query\fR() function splits up \fIquery\fR of length \fIlength\fR and places the result in \fIbuffer\fR which has a size of \fIbuflen\fR with the nul character separating each path component\&. \fIbuflen\fR needs to be preset with the size of \fIbuffer\fR before the function call, and then \fIbuflen\fR is updated with the actual size of \fIbuffer\fR used\&. The return value indicates the number of components that individual COAP_OPTION_URI_QUERY options need to be created for\&. .SH "PDU OPTIONS \- LIBCOAP HANDLING" .sp Most of the options are under the control of the applications, but the following are primarily used internally by libcoap\&. .sp \fBCOAP_OPTION_BLOCK1\fR and \fBCOAP_OPTION_BLOCK2\fR .sp These Block options are used when a large body needs to be split up into multiple payloads\&. Following the introduction of \fBcoap_context_set_block_mode\fR(3), libcoap can internally handle the setting of these options (see \fBcoap_block\fR(3))\&. Applications can continue to include these options to set hint block size values\&. .sp It is recommended that \fBcoap_context_set_block_mode(context, COAP_BLOCK_USE_LIBCOAP|COAP_BLOCK_SINGLE_BODY)\fR is used to reduce the programming requirements for block handling within the applications\&. .sp \fBCOAP_OPTION_ECHO\fR .sp This option can be set by the server application to indicate that the state of the client\(cqs 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\&. .sp \fBCOAP_OPTION_ETAG\fR .sp 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\&. .sp \fBCOAP_OPTION_HOP_LIMIT\fR .sp 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\&. .sp \fBCOAP_OPTION_RTAG\fR .sp 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\&. .sp \fBCOAP_OPTION_SIZE1\fR and \fBCOAP_OPTION_SIZE2\fR .sp 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 \fBcoap_block\fR(3)\&. .sp \fBCOAP_OPTION_OSCORE\fR .sp This option is used during OSCORE enabled communications\&. It should not be set by any application, but is used internally\&. See \fBcoap_oscore\fR(3) for further information on how to set up OSCORE\&. .SH "PDU PAYLOAD FUNCTIONS" .sp \fBFunction: coap_add_data()\fR .sp The \fBcoap_add_data\fR() function adds in the specified payload \fIdata\fR of length \fIlength\fR to the PDU \fIpdu\fR\&. Adding the payload data must be done after any token or options are added\&. This function must only be called once per \fIpdu\fR\&. .sp \fBFunction: coap_add_data_blocked_response()\fR .sp The \fBcoap_add_data_blocked_response\fR() function adds in the appropriate part of the payload \fIdata\fR of length \fIlength\fR to the PDU \fIpdu\fR\&. It should be used as a direct replacement for \fBcoap_add_data\fR() 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\(cqs GET / FETCH response\&. The \fIrequest\fR and \fIresponse\fR are the same parameters for the registered GET / FETCH resource handler\&. The \fImedia_type\fR is for the format of the \fIdata\fR and \fImaxage\fR 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 \fIpdu\fR\&. 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\&. .sp \fBNOTE:\fR This function has been superseded by \fBcoap_add_data_large_response\fR()\&. See \fBcoap_block\fR(3)\&. .SH "PDU TRANSMIT FUNCTIONS" .sp \fBFunction: coap_send()\fR .sp The \fBcoap_send\fR() function is used to initiate the transmission of the \fIpdu\fR associated with the \fIsession\fR\&. The caller must not access or delete \fIpdu\fR after calling \fBcoap_send\fR() \- even if there is a return error\&. .sp \fBNOTE:\fR For request handlers, returning from the request handler will cause the response PDU to be transmitted as appropriate and there is no need to call \fBcoap_send\fR() to do this\&. .SH "RETURN VALUES" .sp \fBcoap_new_pdu\fR() and \fBcoap_pdu_init\fR() return a newly created \fIPDU\fR or NULL if there is a malloc or parameter failure\&. .sp \fBcoap_new_optlist\fR() returns a newly created \fIoptlist\fR or NULL if there is a malloc failure\&. .sp \fBcoap_add_token\fR(), \fBcoap_insert_optlist\fR(), \fBcoap_add_optlist_pdu\fR() and \fBcoap_add_data\fR() return 0 on failure, 1 on success\&. .sp \fBcoap_encode_var_safe\fR() returns either the length of bytes encoded (which can be 0 when encoding 0) or 0 on failure\&. .sp \fBcoap_encode_var_safe8\fR() returns either the length of bytes encoded (which can be 0 when encoding 0) or 0 on failure\&. .sp \fBcoap_add_option\fR() returns the size of option added, or 0 on failure\&. .sp \fBcoap_send\fR() returns the CoAP message ID on success or COAP_INVALID_MID on failure\&. .sp \fBcoap_split_path\fR() and \fBcoap_split_query\fR() return the number of components found\&. .sp \fBcoap_new_message_id\fR() returns the next CoAP message ID to use\&. .SH "EXAMPLES" .sp \fBSetup PDU and Transmit\fR .sp .if n \{\ .RS 4 .\} .nf #include static int build_send_pdu(coap_context_t *context, coap_session_t *session, uint8_t msgtype, uint8_t request_code, const char *uri, const char *query, unsigned char *data, size_t length, int observe) { coap_pdu_t *pdu; uint8_t buf[1024]; size_t buflen; uint8_t *sbuf = buf; int res; 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\en"); goto error; } if (uri) { /* Add in the URI options */ buflen = sizeof(buf); res = coap_split_path((const uint8_t*)uri, strlen(uri), sbuf, &buflen); while (res\-\-) { if (!coap_insert_optlist(&optlist_chain, coap_new_optlist(COAP_OPTION_URI_PATH, coap_opt_length(sbuf), coap_opt_value(sbuf)))) goto error; sbuf += coap_opt_size(sbuf); } } if (query) { /* Add in the QUERY options */ buflen = sizeof(buf); res = coap_split_query((const uint8_t*)query, strlen(query), sbuf, &buflen); while (res\-\-) { if (!coap_insert_optlist(&optlist_chain, coap_new_optlist(COAP_OPTION_URI_QUERY, coap_opt_length(sbuf), coap_opt_value(sbuf)))) goto error; sbuf += coap_opt_size(sbuf); } } 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; } .fi .if n \{\ .RE .\} .sp \fBResource Request Handler Response PDU Update\fR .sp .if n \{\ .RS 4 .\} .nf #include #include 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 \*(Aqnow\*(Aq 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)\&. */ } .fi .if n \{\ .RE .\} .SH "SEE ALSO" .sp \fBcoap_block\fR(3), \fBcoap_observe\fR(3), \fBcoap_oscore\fR(3), \fBcoap_pdu_access\fR(3) and \fBcoap_resource\fR(3) .SH "FURTHER INFORMATION" .sp See .sp "RFC7252: The Constrained Application Protocol (CoAP)" .sp "RFC7959: Block\-Wise Transfers in the Constrained Application Protocol (CoAP)" .sp "RFC8613: Object Security for Constrained RESTful Environments (OSCORE)" .sp "RFC8974: Extended Tokens and Stateless Clients in the Constrained Application Protocol (CoAP)" .sp for further information\&. .sp See https://www\&.iana\&.org/assignments/core\-parameters/core\-parameters\&.xhtml#option\-numbers for the current set of defined CoAP Options\&. .SH "BUGS" .sp Please report bugs on the mailing list for libcoap: libcoap\-developers@lists\&.sourceforge\&.net or raise an issue on GitHub at https://github\&.com/obgm/libcoap/issues .SH "AUTHORS" .sp The libcoap project