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

NAME

6       coap_pdu_setup, coap_pdu_init, coap_add_token, coap_new_optlist,
7       coap_insert_optlist, coap_delete_optlist, coap_add_optlist_pdu,
8       coap_add_option, coap_add_data - Work with CoAP PDUs
9

SYNOPSIS

11       #include <coap2/coap.h>
12
13       coap_pdu_t *coap_pdu_init(uint8_t type, uint8_t code, uint16_t
14       message_id, size_t max_size);
15
16       int coap_add_token(coap_pdu_t *pdu, size_t length, const uint8_t
17       *data);
18
19       coap_optlist_t *coap_new_optlist(uint16_t number, size_t length, const
20       uint8_t *data);
21
22       int coap_insert_optlist(coap_optlist_t **optlist_chain, coap_optlist_t
23       *optlist);
24
25       void coap_delete_optlist(coap_optlist_t *optlist_chain);
26
27       int coap_add_optlist_pdu(coap_pdu_t *pdu, coap_optlist_t
28       **optlist_chain);
29
30       size_t coap_add_option(coap_pdu_t *pdu, uint16_t number, size_t length,
31       const uint8_t *data);
32
33       int coap_add_data(coap_pdu_t *pdu, size_t length, const uint8_t *data);
34
35       void coap_add_data_blocked_response(coap_resource_t *resource,
36       coap_session_t *session, coap_pdu_t *request, coap_pdu_t *response,
37       const coap_binary_t *token, uint16_t media_type, int maxage, size_t
38       length, const uint8_t data);
39
40       unsigned int coap_encode_var_safe(uint8_t *buffer, size_t size,
41       unsigned int value);
42
43       int coap_split_path(const uint8_t *path, size_t length, uint8_t
44       *buffer, size_t *buflen);
45
46       int coap_split_query(const uint8_t *query, size_t length, uint8_t
47       *buffer, size_t *buflen);
48
49       Link with -lcoap-2, -lcoap-2-gnutls, -lcoap-2-openssl or
50       -lcoap-2-tinydtls depending on your (D)TLS library type.
51

DESCRIPTION

53       The CoAP PDU is of the form
54
55       --header--|--optional token--|--optional options--|--optional payload--
56
57       The PDU must be built in the correct order, from left to right. In
58       particular, the options need to be added in the correct numerical
59       option order as they are stored in the PDU using relative numeric
60       offsets from the previous option number.
61
62       There are option list functions available where options can be added to
63       a chained list of options and then the chain list is sorted and then be
64       added to the PDU.
65
66       Typically for clients, when creating a request, the PDU needs to be
67       created before filling it with the appropriate information.
68
69       Typically with a server, the response PDU, with the optional token
70       already added in, will already be created before the response handler
71       is called, and the response PDU will need to be updated as appropriate
72       starting with the optional options. Note that updating the response
73       pdu’s code variable will cause the response pdu to get transmitted. If
74       code does not get updated, then the response pdu is freed off by the
75       underlying library.
76
77       The coap_pdu_init() function returns a newly created PDU of type
78       coap_pdu_t*. type is one of the following
79
80
81       COAP_MESSAGE_CON   Set the PDU to be of type
82                          confirmable.
83
84       COAP_MESSAGE_NON   Set the PDU to be of type
85                          non-confirmable.
86
87       COAP_MESSAGE_ACK   Set the PDU to be of type
88                          acknowledge (for internal
89                          use).
90
91       COAP_MESSAGE_RST   Set the PDU to be of type
92                          reset.
93
94
95       The code is one of the following
96
97
98       COAP_REQUEST_GET      Set the PDU request to be
99                             of type GET.
100
101       COAP_REQUEST_POST     Set the PDU request to be
102                             of type POST.
103
104       COAP_REQUEST_PUT      Set the PDU request to be
105                             of type PUT.
106
107       COAP_REQUEST_DELETE   Set the PDU request to be
108                             of type DELETE.
109
110       COAP_REQUEST_FETCH    Set the PDU request to be
111                             of type FETCH.
112
113       COAP_REQUEST_PATCH    Set the PDU request to be
114                             of type PATCH.
115
116       COAP_REQUEST_IPATCH   Set the PDU request to be
117                             of type IPATCH.
118
119
120       The message_id must be unique per request (which is not the same as the
121       token), and must not be reused within EXCHANGE_LIFETIME (usually 247
122       seconds). To automate this, the function coap_new_message_id(session)
123       should be called.
124
125       The max_size parameter defines the maximum size of a PDU and is usually
126       determined by calling coap_session_max_pdu_size(session);
127
128       The coap_add_token() function adds in the specified token’s data of
129       length length to the PDU pdu. The maximum length of the token is 8
130       bytes. Adding the token must be done before any options or data are
131       added. This function must only be called once per pdu, and must not be
132       called in the appropriate response handler.
133
134       The coap_new_optlist() function returns a newly created optlist entry
135       of type coap_optlist_t*. The number specifies which CoAP option is to
136       be used, and is one of the COAP_OPTION_* definitions. The length is the
137       length of the data of the option, and data points to the content of the
138       option.
139
140       The following is the current list of options with their numeric value
141
142           #define COAP_OPTION_IF_MATCH        1 /* opaque, 0-8 B */
143           #define COAP_OPTION_URI_HOST        3 /* String, 1-255 B */
144           #define COAP_OPTION_ETAG            4 /* opaque, 1-8 B */
145           #define COAP_OPTION_IF_NONE_MATCH   5 /* empty,  0 B */
146           #define COAP_OPTION_OBSERVE         6 /* empty/uint, 0 B/0-3 B */
147           #define COAP_OPTION_URI_PORT        7 /* uint, 0-2 B */
148           #define COAP_OPTION_LOCATION_PATH   8 /* String, 0-255 B */
149           #define COAP_OPTION_URI_PATH       11 /* String, 0-255 B */
150           #define COAP_OPTION_CONTENT_FORMAT 12 /* uint, 0-2 B */
151           #define COAP_OPTION_MAXAGE         14 /* uint, 0-4 B, default 60 Seconds */
152           #define COAP_OPTION_URI_QUERY      15 /* String, 1-255 B */
153           #define COAP_OPTION_ACCEPT         17 /* uint, 0-2 B */
154           #define COAP_OPTION_LOCATION_QUERY 20 /* String, 0-255 B */
155           #define COAP_OPTION_BLOCK2         23 /* uint, 0-3 B */
156           #define COAP_OPTION_BLOCK1         27 /* uint, 0-3 B */
157           #define COAP_OPTION_SIZE2          28 /* uint, 0-4 B */
158           #define COAP_OPTION_PROXY_URI      35 /* String, 1-1034 B */
159           #define COAP_OPTION_PROXY_SCHEME   39 /* String, 1-255 B */
160           #define COAP_OPTION_SIZE1          60 /* uint, 0-4 B */
161           #define COAP_OPTION_NORESPONSE    258 /* uint, 0-1 B */
162
163       See FURTHER INFORMATION as to how to get the latest list.
164
165       The coap_insert_optlist() function adds the optlist entry onto the
166       optlist_chain and then sorts the optlist_chain before returning. The
167       initial optlist_chain entry needs to be set to NULL before this
168       function is first called. The coap_delete_optlist() function has to be
169       called to free off all the optlist_chain entries.
170
171       The coap_delete_optlist() function deletes and frees off all the
172       optlist entries in the optlist_chain.
173
174       The coap_add_optlist_pdu() function sorts all of the entries in
175       optlist_chain into ascending option numeric order and adds all the
176       entries to the pdu. This function does not free off the entries in
177       optlist_chain. This function must be called after adding any token and
178       before adding in the payload data.
179
180       The coap_add_option() function adds in the specified option of type
181       number with data of length length to the PDU pdu. It is critical that
182       options are added to the pdu with number either being the same or
183       greater than the previous option number that was added.
184
185       The coap_add_data() function adds in the specified payload data of
186       length length to the PDU pdu. Adding the payload data must be done
187       after any token or options are added. This function must only be called
188       once per pdu.
189
190       The coap_add_data_blocked_response() function adds in the appropriate
191       part of the payload data of length length to the PDU pdu. It should be
192       used as a direct replacement for coap_add_data() if it is possible that
193       the data will not fit into a single pdu. It also adds in the
194       appropriate CoAP options to handle Block-Wise transfer. This function
195       is usually used for a server’s GET response. The resource, session,
196       request, response and token are the same parameters for the registered
197       GET resource handler. The media_type is for the format of the data and
198       maxage defines the lifetime of the response. If set to -1, then the
199       MAXAGE option does not get included. This function must only be called
200       once per pdu. It is the responsibility of the client to recognize that
201       it has only received a part of the data and request the next block
202       (with the appropriate Block options) from the server. Returning the
203       next requested block is handled by this function.
204
205       The coap_encode_var_safe() function encodes value into buffer which has
206       a size of size in bytes. Normally, the buffer size should be at least
207       the sizeof(int) bytes unless you definitely know less space is
208       required.
209
210       The coap_split_path() function splits up path of length length and
211       places the result in buffer which has a size of buflen. buflen needs to
212       be preset with the size of buffer before the function call, and then
213       buflen is updated with the actual size of buffer used.
214
215       The coap_split_query() function splits up query of length length and
216       places the result in buffer which has a size of buflen. buflen needs to
217       be preset with the size of buffer before the function call, and then
218       buflen is updated with the actual size of buffer used.
219

RETURN VALUES

221       The coap_pdu_init() function returns a newly created PDU or NULL if
222       there is a malloc or parameter failure.
223
224       The coap_new_optlist() function returns a newly created optlist or NULL
225       if there is a malloc failure.
226
227       The coap_add_token(), coap_insert_optlist(), coap_delete_optlist(),
228       coap_add_optlist_pdu() and coap_add_data() functions return 0 on
229       failure, 1 on success.
230
231       The coap_add_optlist() function returns either the length of the option
232       or 0 on failure.
233
234       The coap_encode_var_safe() function returns either the length of bytes
235       encoded or 0 on failure.
236

EXAMPLES

238       Setup PDU and Transmit
239
240           #include <coap2/coap.h>
241
242           static int token = 0;
243
244           int
245           build_send_pdu(coap_context_t *context, coap_session_t *session,
246           uint8_t msgtype, uint8_t request_code, const char *uri, const char *query,
247           unsigned char *data, size_t length, int observe) {
248
249             coap_pdu_t *pdu;
250             (void)context;
251             char buf[1024];
252             size_t buflen;
253             char *sbuf = buf;
254             int res;
255             coap_optlist_t *optlist_chain = NULL;
256
257             /* Create the pdu with the appropriate options */
258             pdu = coap_pdu_init(msgtype, request_code, coap_new_message_id(session),
259                                 coap_session_max_pdu_size(session));
260             if (!pdu)
261               return 0;
262
263             /*
264              * Create uniqueness token for this request for handling unsolicited /
265              * delayed responses
266              */
267             token++;
268             if (!coap_add_token(pdu, sizeof(token), (unsigned char*)&token)) {
269               coap_log(LOG_DEBUG, "cannot add token to request\n");
270               goto error;
271             }
272
273             if (uri) {
274               /* Add in the URI options */
275               buflen = sizeof(buf);
276               res = coap_split_path((const uint8_t*)uri, strlen(uri), sbuf, &buflen);
277               while (res--) {
278                 if (!coap_insert_optlist(&optlist_chain,
279                                          coap_new_optlist(COAP_OPTION_URI_PATH,
280                                   coap_opt_length(sbuf), coap_opt_value(sbuf))))
281                   goto error;
282                 sbuf += coap_opt_size(sbuf);
283               }
284             }
285
286             if (query) {
287               /* Add in the QUERY options */
288               buflen = sizeof(buf);
289               res = coap_split_query((const uint8_t*)query, strlen(query), sbuf, &buflen);
290               while (res--) {
291                 if (!coap_insert_optlist(&optlist_chain,
292                                          coap_new_optlist(COAP_OPTION_URI_QUERY,
293                                   coap_opt_length(sbuf), coap_opt_value(sbuf))))
294                   goto error;
295                 sbuf += coap_opt_size(sbuf);
296               }
297             }
298
299             if (request_code == COAP_REQUEST_GET && observe) {
300               /* Indicate that we want to observe this resource */
301               if (!coap_insert_optlist(&optlist_chain,
302                                        coap_new_optlist(COAP_OPTION_OBSERVE,
303                                                    COAP_OBSERVE_ESTABLISH, NULL)))
304                 goto error;
305             }
306
307             /* ... Other code / options etc. ... */
308
309             /* Add in all the options (after internal sorting) to the pdu */
310             if (!coap_add_optlist_pdu(pdu, &optlist_chain))
311               goto error;
312
313             if (data && length) {
314               /* Add in the specified data */
315               if (!coap_add_data(pdu, length, data))
316                 goto error;
317             }
318
319             if (coap_send(session, pdu) == COAP_INVALID_TID)
320               goto error;
321             return 1;
322
323           error:
324
325             if (pdu)
326               coap_pdu_delete(pdu);
327             return 0;
328
329           }
330
331       Resource Handler Response PDU Update
332
333           #include <coap2/coap.h>
334
335           static void
336           hnd_get_time(coap_context_t *context, coap_resource_t *resource,
337           coap_session_t *session, coap_pdu_t *request, coap_string_t *token,
338           coap_string_t *query, coap_pdu_t *response) {
339
340             unsigned char buf[40];
341             size_t len;
342             time_t now;
343
344             /* ... Additional analysis code for resource, request pdu etc.  ... */
345
346             /* After analysis, generate a suitable response */
347
348             /* Note that token, if set, is already in the response pdu */
349
350             now = time(NULL);
351
352             if (query != NULL && coap_string_equal(query, coap_make_str_const("secs"))) {
353               /* Output secs since Jan 1 1970 */
354               len = snprintf((char *)buf, sizeof(buf), "%lu", now);
355             }
356             else {
357               /* Output human-readable time */
358               struct tm *tmp;
359               tmp = gmtime(&now);
360               if (!tmp) {
361                 /* If 'now' is not valid */
362                 response->code = COAP_RESPONSE_CODE(404);
363                 return;
364               }
365               len = strftime((char *)buf, sizeof(buf), "%b %d %H:%M:%S", tmp);
366             }
367             /*
368              * Invoke coap_add_data_blocked_response() to do all the hard work.
369              *
370              * Define the format - COAP_MEDIATYPE_TEXT_PLAIN - to add in
371              * Define how long this response is valid for (secs) - 1 - to add in.
372              *
373              * OBSERVE Option added internally if needed within the function
374              * BLOCK2 Option added internally if output too large
375              * ETAG Option added internally
376              */
377             coap_add_data_blocked_response(resource, session, request, response, token,
378                                            COAP_MEDIATYPE_TEXT_PLAIN, 1,
379                                            len,
380                                            buf);
381
382             /*
383              * As resource->code has been updated in coap_add_data_blocked_response(),
384              * the response pdu will be transmitted by the underlying library.
385              */
386
387           }
388

SEE ALSO

390       coap_observe(3), coap_resource(3)
391

FURTHER INFORMATION

393       See "RFC7252: The Constrained Application Protocol (CoAP)" for further
394       information.
395
396       See
397       https://www.iana.org/assignments/core-parameters/core-parameters.xhtml#option-numbers
398       for the current set of defined CoAP Options.
399

BUGS

401       Please report bugs on the mailing list for libcoap:
402       libcoap-developers@lists.sourceforge.net
403

AUTHORS

405       The libcoap project <libcoap-developers@lists.sourceforge.net>
406
407
408
409coap_pdu_setup 4.2.1              01/26/2021                 COAP_PDU_SETUP(3)
Impressum