1COAP_PDU_SETUP(3) libcoap Manual COAP_PDU_SETUP(3)
2
3
4
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
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
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
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
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
390 coap_observe(3), coap_resource(3)
391
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
401 Please report bugs on the mailing list for libcoap:
402 libcoap-developers@lists.sourceforge.net
403
405 The libcoap project <libcoap-developers@lists.sourceforge.net>
406
407
408
409coap_pdu_setup 4.2.1 07/28/2020 COAP_PDU_SETUP(3)