1COAP_PDU_SETUP(3)               libcoap Manual               COAP_PDU_SETUP(3)
2
3
4

NAME

6       coap_pdu_setup, coap_new_pdu, coap_pdu_init, coap_session_init_token,
7       coap_session_new_token, coap_add_token, coap_new_optlist,
8       coap_insert_optlist, coap_delete_optlist - Setting up CoAP PDUs
9

SYNOPSIS

11       #include <coap3/coap.h>
12
13       coap_pdu_t *coap_new_pdu(coap_pdu_type_t type, coap_pdu_code_t code,
14       coap_session_t *session);
15
16       coap_pdu_t *coap_pdu_init(coap_pdu_type_t type, coap_pdu_code_t code,
17       coap_mid_t message_id, size_t max_size);
18
19       void coap_session_init_token(coap_session_t *session, size_t length,
20       const uint8_t *token);
21
22       void coap_session_new_token(coap_session_t *session, size_t *length,
23       uint8_t *token);
24
25       int coap_add_token(coap_pdu_t *pdu, size_t length, const uint8_t
26       *data);
27
28       coap_optlist_t *coap_new_optlist(uint16_t number, size_t length, const
29       uint8_t *data);
30
31       int coap_insert_optlist(coap_optlist_t **optlist_chain, coap_optlist_t
32       *optlist);
33
34       void coap_delete_optlist(coap_optlist_t *optlist_chain);
35
36       unsigned int coap_encode_var_safe(uint8_t *buffer, size_t size,
37       unsigned int value);
38
39       unsigned int coap_encode_var_safe8(uint8_t *buffer, size_t size,
40       uint64_t value);
41
42       int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t
43       **optlist_chain);
44
45       size_t coap_add_option(coap_pdu_t *pdu, uint16_t number, size_t length,
46       const uint8_t *data);
47
48       int coap_add_data(coap_pdu_t *pdu, size_t length, const uint8_t *data);
49
50       void coap_add_data_blocked_response(const coap_pdu_t *request,
51       coap_pdu_t *response, uint16_t media_type, int maxage, size_t length,
52       const uint8_t *data);
53
54       coap_mid_t coap_send(coap_session_t *session, coap_pdu_t *pdu);
55
56       int coap_split_path(const uint8_t *path, size_t length, uint8_t
57       *buffer, size_t *buflen);
58
59       int coap_split_query(const uint8_t *query, size_t length, uint8_t
60       *buffer, size_t *buflen);
61
62       void coap_pdu_set_mid(coap_pdu_t *pdu, coap_mid_t mid);
63
64       void coap_pdu_set_code(coap_pdu_t *pdu, coap_pdu_code_t code);
65
66       void coap_pdu_set_type(coap_pdu_t *pdu, coap_pdu_type_t type);
67
68       For specific (D)TLS library support, link with -lcoap-3-notls,
69       -lcoap-3-gnutls, -lcoap-3-openssl, -lcoap-3-mbedtls or
70       -lcoap-3-tinydtls. Otherwise, link with -lcoap-3 to get the default
71       (D)TLS library support.
72

DESCRIPTION

74       The CoAP PDU is of the form
75
76       --header--|--optional token--|--optional options--|--optional payload--
77
78       The terminology used is taken mainly from
79       https://tools.ietf.org/html/rfc7252#section-1.2
80
81       The PDU must be built in the correct order, from left to right. In
82       particular, the options need to be added in the correct numerical
83       option order as they are stored in the PDU using relative numeric
84       offsets from the previous option number.
85
86       There are option list functions available where options can be added to
87       a chained list of options and then the chain list is sorted and then be
88       added to the PDU.
89
90       Typically for clients, when creating a request, the PDU needs to be
91       created before filling it with the appropriate information.
92
93       Typically with a server, the response PDU, with the optional token
94       already added in, will already be created before the response handler
95       is called, and the response PDU will need to be updated as appropriate
96       starting with the optional options. Note that updating the response
97       pdu’s code variable will cause the response pdu to get transmitted. If
98       code does not get updated, and the PDU is of type CONFIRMABLE, then the
99       response PDU is transmitted as an empty ACK packet. The response pdu is
100       always freed off by the underlying library.
101
102       For handling situations where the data to be transmitted does not fit
103       into a single packet, see coap_block(3).
104
105       Create and Header:
106
107       The coap_new_pdu() function returns a newly created PDU of type
108       coap_pdu_t*. The type is one of the following
109
110           COAP_MESSAGE_CON Set the _PDU_ to be of type confirmable.
111           COAP_MESSAGE_NON Set the _PDU_ to be of type non-confirmable.
112           COAP_MESSAGE_ACK Set the _PDU_ to be of type acknowledge (for internal use).
113           COAP_MESSAGE_RST Set the _PDU_ to be of type reset.
114
115       The code is one of the following
116
117           COAP_EMPTY_CODE                               0.00
118           COAP_REQUEST_CODE_GET                         0.01
119           COAP_REQUEST_CODE_POST                        0.02
120           COAP_REQUEST_CODE_PUT                         0.03
121           COAP_REQUEST_CODE_DELETE                      0.04
122           COAP_REQUEST_CODE_FETCH                       0.05
123           COAP_REQUEST_CODE_PATCH                       0.06
124           COAP_REQUEST_CODE_IPATCH                      0.07
125           COAP_RESPONSE_CODE_OK                         2.00
126           COAP_RESPONSE_CODE_CREATED                    2.01
127           COAP_RESPONSE_CODE_DELETED                    2.02
128           COAP_RESPONSE_CODE_VALID                      2.03
129           COAP_RESPONSE_CODE_CHANGED                    2.04
130           COAP_RESPONSE_CODE_CONTENT                    2.05
131           COAP_RESPONSE_CODE_CONTINUE                   2.31
132           COAP_RESPONSE_CODE_BAD_REQUEST                4.00
133           COAP_RESPONSE_CODE_UNAUTHORIZED               4.01
134           COAP_RESPONSE_CODE_BAD_OPTION                 4.02
135           COAP_RESPONSE_CODE_FORBIDDEN                  4.03
136           COAP_RESPONSE_CODE_NOT_FOUND                  4.04
137           COAP_RESPONSE_CODE_NOT_ALLOWED                4.05
138           COAP_RESPONSE_CODE_NOT_ACCEPTABLE             4.06
139           COAP_RESPONSE_CODE_INCOMPLETE                 4.08
140           COAP_RESPONSE_CODE_CONFLICT                   4.09
141           COAP_RESPONSE_CODE_PRECONDITION_FAILED        4.12
142           COAP_RESPONSE_CODE_REQUEST_TOO_LARGE          4.13
143           COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT 4.15
144           COAP_RESPONSE_CODE_UNPROCESSABLE              4.22
145           COAP_RESPONSE_CODE_TOO_MANY_REQUESTS          4.29
146           COAP_RESPONSE_CODE_INTERNAL_ERROR             5.00
147           COAP_RESPONSE_CODE_NOT_IMPLEMENTED            5.01
148           COAP_RESPONSE_CODE_BAD_GATEWAY                5.02
149           COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE        5.03
150           COAP_RESPONSE_CODE_GATEWAY_TIMEOUT            5.04
151           COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED     5.05
152           COAP_RESPONSE_CODE_HOP_LIMIT_REACHED          5.08
153           COAP_SIGNALING_CODE_CSM                       7.01
154           COAP_SIGNALING_CODE_PING                      7.02
155           COAP_SIGNALING_CODE_PONG                      7.03
156           COAP_SIGNALING_CODE_RELEASE                   7.04
157           COAP_SIGNALING_CODE_ABORT                     7.05
158
159       and session is used to set up other default values.
160
161       The coap_pdu_init() function does the same work as coap_new_pdu() but
162       gives the additional ability to define the default values for
163       message_id and max_size that coap_new_pdu() creates.
164
165       The message_id must be unique per request (which is not the same as the
166       token), and must not be reused within EXCHANGE_LIFETIME (usually 247
167       seconds). To automate this, the function coap_new_message_id(session)
168       should be called.
169
170       At the CoAP protocol level, requests and responses are matched by
171       message_id which is why it needs to be unique. At the application
172       level, for "separate" responses, the initial empty ACK response matches
173       the message_id of the request (handled by libcoap) but the actual
174       response has the same token as the request and this must be used for
175       the match. For "piggybacked" responses the token must still be used as
176       the valid match for request and response. and the message_id just
177       happens to match (but unsafe in case the server is sending back a
178       "separate" response).
179
180       The max_size parameter defines the maximum size of a PDU and is usually
181       determined by calling coap_session_max_pdu_size(session);
182
183       The coap_pdu_set_mid() function is used to set the message id mid in
184       the PDU pdu.
185
186       The coap_pdu_set_code() function is used to set the code code in the
187       PDU pdu.
188
189       The coap_pdu_set_type() function is used to set the type of the PDU
190       pdu.
191
192       Token:
193
194       The coap_session_init_token() function is used to initialize the
195       starting token of length for the session.
196
197       The coap_session_new_token() function is used to obtain the next
198       available token of length for the session. Note that the same token
199       must be used for doing an observe cancellation that was used for doing
200       the observe registration. Otherwise tokens should be unique for each
201       request/response so that they can be correctly matched.
202
203       The coap_add_token() function adds in the specified token’s data of
204       length length to the PDU pdu. The maximum length of the token is 8
205       bytes. Adding the token must be done before any options or data are
206       added. This function must only be called once per pdu, and must not be
207       called in the appropriate response handler.
208
209       If a token is not added, then the token in the PDU is zero length, but
210       still a valid token which is used for matching. The exception is an
211       empty ACK packet.
212
213       Options:
214
215       The coap_new_optlist() function returns a newly created optlist entry
216       of type coap_optlist_t*. The number specifies which CoAP option is to
217       be used, and is one of the COAP_OPTION_* definitions. The length is the
218       length of the data of the option, and data points to the content of the
219       option.
220
221       NOTE: Where possible, the option data needs to be stripped of leading
222       zeros (big endian) to reduce the amount of data needed in the PDU, as
223       well as in some cases the maximum data size of an opton can be exceeded
224       if not stripped and hence be illegal. This is done by using
225       coap_encode_var_safe() or coap_encode_var_safe8().
226
227       The following is the current list of options with their numeric value
228
229           /*
230            * The C, U, and N flags indicate the properties
231            * Critical, Unsafe, and NoCacheKey, respectively.
232            * If U is set, then N has no meaning as per
233            * https://tools.ietf.org/html/rfc7252#section-5.10
234            * and is set to a -.
235            * Separately, R is for the options that can be repeated
236            *
237            * The least significant byte of the option is set as followed
238            * as per https://tools.ietf.org/html/rfc7252#section-5.4.6
239            *
240            *   0   1   2   3   4   5   6   7
241            * --+---+---+---+---+---+---+---+
242            *           | NoCacheKey| U | C |
243            * --+---+---+---+---+---+---+---+
244            *
245            * https://tools.ietf.org/html/rfc8613#section-4 goes on to define E, I and U
246            * properties Encrypted and Integrity Protected, Integrity Protected Only and
247            * Unprotected respectively.  Integrity Protected Only is not currently used.
248            *
249            * An Option is tagged with CUNREIU with any of the letters replaced with _ if
250            * not set, or - for N if U is set (see above) for aiding understanding of the
251            * Option.
252            */
253
254           COAP_OPTION_IF_MATCH        1 /* C__RE__, opaque,    0-8 B, RFC7252 */
255           COAP_OPTION_URI_HOST        3 /* CU-___U, String,  1-255 B, RFC7252 */
256           COAP_OPTION_ETAG            4 /* ___RE__, opaque,    1-8 B, RFC7252 */
257           ION_IF_NONE_MATCH   5 /* C___E__, empty,       0 B, RFC7252 */
258           COAP_OPTION_OBSERVE         6 /* _U-_E_U, empty/uint,  0 B/0-3 B, RFC7641 */
259           COAP_OPTION_URI_PORT        7 /* CU-___U, uint,      0-2 B, RFC7252 */
260           COAP_OPTION_LOCATION_PATH   8 /* ___RE__, String,  0-255 B, RFC7252 */
261           COAP_OPTION_OSCORE          9 /* C_____U, *,       0-255 B, RFC8613 */
262           COAP_OPTION_URI_PATH       11 /* CU-RE__, String,  0-255 B, RFC7252 */
263           COAP_OPTION_CONTENT_FORMAT 12 /* ____E__, uint,      0-2 B, RFC7252 */
264           /* COAP_OPTION_MAXAGE default 60 seconds if not set */
265           COAP_OPTION_MAXAGE         14 /* _U-_E_U, uint,      0-4 B, RFC7252 */
266           COAP_OPTION_URI_QUERY      15 /* CU-RE__, String,  1-255 B, RFC7252 */
267           COAP_OPTION_HOP_LIMIT      16 /* ______U, uint,        1 B, RFC8768 */
268           COAP_OPTION_ACCEPT         17 /* C___E__, uint,      0-2 B, RFC7252 */
269           COAP_OPTION_LOCATION_QUERY 20 /* ___RE__, String,  0-255 B, RFC7252 */
270           COAP_OPTION_BLOCK2         23 /* CU-_E_U, uint,      0-3 B, RFC7959 */
271           COAP_OPTION_BLOCK1         27 /* CU-_E_U, uint,      0-3 B, RFC7959 */
272           COAP_OPTION_SIZE2          28 /* __N_E_U, uint,      0-4 B, RFC7959 */
273           COAP_OPTION_PROXY_URI      35 /* CU-___U, String, 1-1034 B, RFC7252 */
274           COAP_OPTION_PROXY_SCHEME   39 /* CU-___U, String,  1-255 B, RFC7252 */
275           COAP_OPTION_SIZE1          60 /* __N_E_U, uint,      0-4 B, RFC7252 */
276           COAP_OPTION_NORESPONSE    258 /* _U-_E_U, uint,      0-1 B, RFC7967 */
277
278       See FURTHER INFORMATION as to how to get the latest list.
279
280       The coap_insert_optlist() function adds the optlist entry onto the
281       optlist_chain and then sorts the optlist_chain before returning. The
282       initial optlist_chain entry needs to be set to NULL before this
283       function is first called. The coap_delete_optlist() function has to be
284       called to free off all the optlist_chain entries.
285
286       The coap_delete_optlist() function deletes and frees off all the
287       optlist entries in the optlist_chain.
288
289       The coap_add_optlist_pdu() function sorts all of the entries in
290       optlist_chain into ascending option numeric order and adds all the
291       entries to the pdu. This function does not free off the entries in
292       optlist_chain. This function must be called after adding any token and
293       before adding in the payload data.
294
295       The coap_add_option() function adds in the specified option of type
296       number with data of length length to the PDU pdu. It is important that
297       options are added to the pdu with number either being the same or
298       greater than the previous option number that was added.
299
300       NOTE: Where possible, the option data needs to be stripped of leading
301       zeros (big endian) to reduce the amount of data needed in the PDU, as
302       well as in some cases the maximum data size of an opton can be exceeded
303       if not stripped and hence be illegal. This is done by using
304       coap_encode_var_safe() or coap_encode_var_safe8().
305
306       The coap_encode_var_safe() function encodes value into buffer which has
307       a size of size in bytes. Normally, the buffer size should be at least
308       the sizeof(int) bytes unless you definitely know less space is
309       required.
310
311       The coap_encode_var_safe8() function encodes 8 byte value into buffer
312       which has a size of size in bytes. Normally, the buffer size should be
313       at least 8 bytes unless you definitely know less space is required.
314
315       The coap_split_path() function splits up path of length length and
316       places the result in buffer which has a size of buflen. buflen needs to
317       be preset with the size of buffer before the function call, and then
318       buflen is updated with the actual size of buffer used.
319
320       The coap_split_query() function splits up query of length length and
321       places the result in buffer which has a size of buflen. buflen needs to
322       be preset with the size of buffer before the function call, and then
323       buflen is updated with the actual size of buffer used.
324
325       Payload Data:
326
327       The coap_add_data() function adds in the specified payload data of
328       length length to the PDU pdu. Adding the payload data must be done
329       after any token or options are added. This function must only be called
330       once per pdu.
331
332       The coap_add_data_blocked_response() function adds in the appropriate
333       part of the payload data of length length to the PDU pdu. It should be
334       used as a direct replacement for coap_add_data() if it is possible that
335       the data will not fit into a single pdu. It also adds in the
336       appropriate CoAP options to handle Block-Wise transfer. This function
337       is usually used for a server’s GET / FETCH response. The request and
338       response are the same parameters for the registered GET / FETCH
339       resource handler. The media_type is for the format of the data and
340       maxage defines the lifetime of the response. If set to -1, then the
341       MAXAGE option does not get included. This function must only be called
342       once per pdu. It is the responsibility of the client to recognize that
343       it has only received a part of the data and request the next block
344       (with the appropriate Block options) from the server. Returning the
345       next requested block is handled by this function.
346
347       NOTE: This function has been superseded by
348       coap_add_data_response_large(). See coap_block(3).
349
350       Transmit:
351
352       The coap_send() function is used to initiate the transmission of the
353       pdu associated with the session.
354

RETURN VALUES

356       The coap_new_pdu() and coap_pdu_init() function returns a newly created
357       PDU or NULL if there is a malloc or parameter failure.
358
359       The coap_new_optlist() function returns a newly created optlist or NULL
360       if there is a malloc failure.
361
362       The coap_add_token(), coap_insert_optlist(), coap_delete_optlist(),
363       coap_add_optlist_pdu() and coap_add_data() functions return 0 on
364       failure, 1 on success.
365
366       The coap_add_optlist() function returns either the length of the option
367       or 0 on failure.
368
369       The coap_encode_var_safe() function returns either the length of bytes
370       encoded or 0 on failure.
371
372       The coap_encode_var_safe8() function returns either the length of bytes
373       encoded or 0 on failure.
374
375       The coap_send() function returns the CoAP message ID on success or
376       COAP_INVALID_MID on failure.
377

EXAMPLES

379       Setup PDU and Transmit
380
381           #include <coap3/coap.h>
382
383           static int
384           build_send_pdu(coap_context_t *context, coap_session_t *session,
385           uint8_t msgtype, uint8_t request_code, const char *uri, const char *query,
386           unsigned char *data, size_t length, int observe) {
387
388             coap_pdu_t *pdu;
389             uint8_t buf[1024];
390             size_t buflen;
391             uint8_t *sbuf = buf;
392             int res;
393             coap_optlist_t *optlist_chain = NULL;
394             /* Remove (void) definition if variable is used */
395             (void)context;
396
397             /* Create the pdu with the appropriate options */
398             pdu = coap_pdu_init(msgtype, request_code, coap_new_message_id(session),
399                                 coap_session_max_pdu_size(session));
400             if (!pdu)
401               return 0;
402
403             /*
404              * Create unique token for this request for handling unsolicited /
405              * delayed responses
406              */
407             coap_session_new_token(session, &buflen, buf);
408             if (!coap_add_token(pdu, buflen, buf)) {
409               coap_log(LOG_DEBUG, "cannot add token to request\n");
410               goto error;
411             }
412
413             if (uri) {
414               /* Add in the URI options */
415               buflen = sizeof(buf);
416               res = coap_split_path((const uint8_t*)uri, strlen(uri), sbuf, &buflen);
417               while (res--) {
418                 if (!coap_insert_optlist(&optlist_chain,
419                                          coap_new_optlist(COAP_OPTION_URI_PATH,
420                                   coap_opt_length(sbuf), coap_opt_value(sbuf))))
421                   goto error;
422                 sbuf += coap_opt_size(sbuf);
423               }
424             }
425
426             if (query) {
427               /* Add in the QUERY options */
428               buflen = sizeof(buf);
429               res = coap_split_query((const uint8_t*)query, strlen(query), sbuf, &buflen);
430               while (res--) {
431                 if (!coap_insert_optlist(&optlist_chain,
432                                          coap_new_optlist(COAP_OPTION_URI_QUERY,
433                                   coap_opt_length(sbuf), coap_opt_value(sbuf))))
434                   goto error;
435                 sbuf += coap_opt_size(sbuf);
436               }
437             }
438
439             if (request_code == COAP_REQUEST_GET && observe) {
440               /* Indicate that we want to observe this resource */
441               if (!coap_insert_optlist(&optlist_chain,
442                                        coap_new_optlist(COAP_OPTION_OBSERVE,
443                                          coap_encode_var_safe(buf, sizeof(buf),
444                                          COAP_OBSERVE_ESTABLISH), buf)
445                                        ))
446                 goto error;
447             }
448
449             /* ... Other code / options etc. ... */
450
451             /* Add in all the options (after internal sorting) to the pdu */
452             if (!coap_add_optlist_pdu(pdu, &optlist_chain))
453               goto error;
454
455             if (data && length) {
456               /* Add in the specified data */
457               if (!coap_add_data(pdu, length, data))
458                 goto error;
459             }
460
461             if (coap_send(session, pdu) == COAP_INVALID_MID)
462               goto error;
463             return 1;
464
465           error:
466
467             if (pdu)
468               coap_delete_pdu(pdu);
469             return 0;
470
471           }
472
473       Resource Handler Response PDU Update
474
475           #include <coap3/coap.h>
476
477           #include <stdio.h>
478
479           static void
480           hnd_get_time(coap_resource_t *resource, coap_session_t *session,
481           const coap_pdu_t *request, const coap_string_t *query, coap_pdu_t *response) {
482
483             unsigned char buf[40];
484             size_t len;
485             time_t now;
486
487             /* ... Additional analysis code for resource, request pdu etc.  ... */
488
489             /* After analysis, generate a suitable response */
490
491             now = time(NULL);
492
493             if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) {
494               /* Output secs since Jan 1 1970 */
495               len = snprintf((char *)buf, sizeof(buf), "%lu", now);
496             }
497             else {
498               /* Output human-readable time */
499               struct tm *tmp;
500               tmp = gmtime(&now);
501               if (!tmp) {
502                 /* If 'now' is not valid */
503                 coap_pdu_set_code(response, COAP_RESPONSE_CODE_NOT_FOUND);
504                 return;
505               }
506               len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp);
507             }
508             coap_pdu_set_code(response, COAP_RESPONSE_CODE_CONTENT);
509             /*
510              * Invoke coap_add_data_large_response() to do all the hard work.
511              *
512              * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in
513              * Define how long this response is valid for (secs) - 1 - to add in.
514              * ETAG Option added internally with unique value as param set to 0
515              *
516              * OBSERVE Option added internally if needed within the function
517              * BLOCK2 Option added internally if output too large
518              * SIZE2 Option added internally
519              */
520             coap_add_data_large_response(resource, session, request, response,
521                                          query, COAP_MEDIATYPE_TEXT_PLAIN, 1, 0,
522                                          len,
523                                          buf, NULL, NULL);
524
525           }
526

SEE ALSO

528       coap_block(3), coap_observe(3), coap_pdu_access(3) and coap_resource(3)
529

FURTHER INFORMATION

531       See
532
533       "RFC7252: The Constrained Application Protocol (CoAP)"
534
535       "RFC7959: Block-Wise Transfers in the Constrained Application Protocol
536       (CoAP)"
537
538       for further information.
539
540       See
541       https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#option-numbers
542       for the current set of defined CoAP Options.
543

BUGS

545       Please report bugs on the mailing list for libcoap:
546       libcoap-developers@lists.sourceforge.net or raise an issue on GitHub at
547       https://github.com/obgm/libcoap/issues
548

AUTHORS

550       The libcoap project <libcoap-developers@lists.sourceforge.net>
551
552
553
554coap_pdu_setup 4.3.0              07/22/2021                 COAP_PDU_SETUP(3)
Impressum