1 /*
2 * Copyright (c) 2018 Intel Corporation
3 * Copyright (c) 2021 Nordic Semiconductor
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 */
7
8 /**
9 * @file
10 *
11 * @brief CoAP implementation for Zephyr.
12 */
13
14 #ifndef ZEPHYR_INCLUDE_NET_COAP_H_
15 #define ZEPHYR_INCLUDE_NET_COAP_H_
16
17 /**
18 * @brief COAP library
19 * @defgroup coap COAP Library
20 * @since 1.10
21 * @version 0.8.0
22 * @ingroup networking
23 * @{
24 */
25
26 #include <zephyr/types.h>
27 #include <stddef.h>
28 #include <stdbool.h>
29 #include <zephyr/net/net_ip.h>
30 #include <zephyr/sys/math_extras.h>
31 #include <zephyr/sys/slist.h>
32
33 #ifdef __cplusplus
34 extern "C" {
35 #endif
36
37 /**
38 * @brief Set of CoAP packet options we are aware of.
39 *
40 * Users may add options other than these to their packets, provided
41 * they know how to format them correctly. The only restriction is
42 * that all options must be added to a packet in numeric order.
43 *
44 * Refer to RFC 7252, section 12.2 for more information.
45 */
46 enum coap_option_num {
47 COAP_OPTION_IF_MATCH = 1, /**< If-Match */
48 COAP_OPTION_URI_HOST = 3, /**< Uri-Host */
49 COAP_OPTION_ETAG = 4, /**< ETag */
50 COAP_OPTION_IF_NONE_MATCH = 5, /**< If-None-Match */
51 COAP_OPTION_OBSERVE = 6, /**< Observe (RFC 7641) */
52 COAP_OPTION_URI_PORT = 7, /**< Uri-Port */
53 COAP_OPTION_LOCATION_PATH = 8, /**< Location-Path */
54 COAP_OPTION_URI_PATH = 11, /**< Uri-Path */
55 COAP_OPTION_CONTENT_FORMAT = 12, /**< Content-Format */
56 COAP_OPTION_MAX_AGE = 14, /**< Max-Age */
57 COAP_OPTION_URI_QUERY = 15, /**< Uri-Query */
58 COAP_OPTION_ACCEPT = 17, /**< Accept */
59 COAP_OPTION_LOCATION_QUERY = 20, /**< Location-Query */
60 COAP_OPTION_BLOCK2 = 23, /**< Block2 (RFC 7959) */
61 COAP_OPTION_BLOCK1 = 27, /**< Block1 (RFC 7959) */
62 COAP_OPTION_SIZE2 = 28, /**< Size2 (RFC 7959) */
63 COAP_OPTION_PROXY_URI = 35, /**< Proxy-Uri */
64 COAP_OPTION_PROXY_SCHEME = 39, /**< Proxy-Scheme */
65 COAP_OPTION_SIZE1 = 60, /**< Size1 */
66 COAP_OPTION_ECHO = 252, /**< Echo (RFC 9175) */
67 COAP_OPTION_NO_RESPONSE = 258, /**< No-Response (RFC 7967) */
68 COAP_OPTION_REQUEST_TAG = 292 /**< Request-Tag (RFC 9175) */
69 };
70
71 /**
72 * @brief Available request methods.
73 *
74 * To be used when creating a request or a response.
75 */
76 enum coap_method {
77 COAP_METHOD_GET = 1, /**< GET */
78 COAP_METHOD_POST = 2, /**< POST */
79 COAP_METHOD_PUT = 3, /**< PUT */
80 COAP_METHOD_DELETE = 4, /**< DELETE */
81 COAP_METHOD_FETCH = 5, /**< FETCH */
82 COAP_METHOD_PATCH = 6, /**< PATCH */
83 COAP_METHOD_IPATCH = 7, /**< IPATCH */
84 };
85
86 /** @cond INTERNAL_HIDDEN */
87
88 #define COAP_REQUEST_MASK 0x07
89
90 #define COAP_VERSION_1 1U
91
92 #define COAP_OBSERVE_MAX_AGE 0xFFFFFF
93
94 /** @endcond */
95
96 /**
97 * @brief CoAP packets may be of one of these types.
98 */
99 enum coap_msgtype {
100 /**
101 * Confirmable message.
102 *
103 * The packet is a request or response the destination end-point must
104 * acknowledge.
105 */
106 COAP_TYPE_CON = 0,
107 /**
108 * Non-confirmable message.
109 *
110 * The packet is a request or response that doesn't
111 * require acknowledgements.
112 */
113 COAP_TYPE_NON_CON = 1,
114 /**
115 * Acknowledge.
116 *
117 * Response to a confirmable message.
118 */
119 COAP_TYPE_ACK = 2,
120 /**
121 * Reset.
122 *
123 * Rejecting a packet for any reason is done by sending a message
124 * of this type.
125 */
126 COAP_TYPE_RESET = 3
127 };
128
129 /**
130 * Utility macro to create a CoAP response code.
131 * @param class Class of the response code (ex. 2, 4, 5, ...)
132 * @param det Detail of the response code
133 * @return Response code literal
134 */
135 #define COAP_MAKE_RESPONSE_CODE(class, det) ((class << 5) | (det))
136
137 /**
138 * @brief Set of response codes available for a response packet.
139 *
140 * To be used when creating a response.
141 */
142 enum coap_response_code {
143 /** 2.00 - OK */
144 COAP_RESPONSE_CODE_OK = COAP_MAKE_RESPONSE_CODE(2, 0),
145 /** 2.01 - Created */
146 COAP_RESPONSE_CODE_CREATED = COAP_MAKE_RESPONSE_CODE(2, 1),
147 /** 2.02 - Deleted */
148 COAP_RESPONSE_CODE_DELETED = COAP_MAKE_RESPONSE_CODE(2, 2),
149 /** 2.03 - Valid */
150 COAP_RESPONSE_CODE_VALID = COAP_MAKE_RESPONSE_CODE(2, 3),
151 /** 2.04 - Changed */
152 COAP_RESPONSE_CODE_CHANGED = COAP_MAKE_RESPONSE_CODE(2, 4),
153 /** 2.05 - Content */
154 COAP_RESPONSE_CODE_CONTENT = COAP_MAKE_RESPONSE_CODE(2, 5),
155 /** 2.31 - Continue */
156 COAP_RESPONSE_CODE_CONTINUE = COAP_MAKE_RESPONSE_CODE(2, 31),
157 /** 4.00 - Bad Request */
158 COAP_RESPONSE_CODE_BAD_REQUEST = COAP_MAKE_RESPONSE_CODE(4, 0),
159 /** 4.01 - Unauthorized */
160 COAP_RESPONSE_CODE_UNAUTHORIZED = COAP_MAKE_RESPONSE_CODE(4, 1),
161 /** 4.02 - Bad Option */
162 COAP_RESPONSE_CODE_BAD_OPTION = COAP_MAKE_RESPONSE_CODE(4, 2),
163 /** 4.03 - Forbidden */
164 COAP_RESPONSE_CODE_FORBIDDEN = COAP_MAKE_RESPONSE_CODE(4, 3),
165 /** 4.04 - Not Found */
166 COAP_RESPONSE_CODE_NOT_FOUND = COAP_MAKE_RESPONSE_CODE(4, 4),
167 /** 4.05 - Method Not Allowed */
168 COAP_RESPONSE_CODE_NOT_ALLOWED = COAP_MAKE_RESPONSE_CODE(4, 5),
169 /** 4.06 - Not Acceptable */
170 COAP_RESPONSE_CODE_NOT_ACCEPTABLE = COAP_MAKE_RESPONSE_CODE(4, 6),
171 /** 4.08 - Request Entity Incomplete */
172 COAP_RESPONSE_CODE_INCOMPLETE = COAP_MAKE_RESPONSE_CODE(4, 8),
173 /** 4.12 - Precondition Failed */
174 COAP_RESPONSE_CODE_CONFLICT = COAP_MAKE_RESPONSE_CODE(4, 9),
175 /** 4.12 - Precondition Failed */
176 COAP_RESPONSE_CODE_PRECONDITION_FAILED = COAP_MAKE_RESPONSE_CODE(4, 12),
177 /** 4.13 - Request Entity Too Large */
178 COAP_RESPONSE_CODE_REQUEST_TOO_LARGE = COAP_MAKE_RESPONSE_CODE(4, 13),
179 /** 4.15 - Unsupported Content-Format */
180 COAP_RESPONSE_CODE_UNSUPPORTED_CONTENT_FORMAT =
181 COAP_MAKE_RESPONSE_CODE(4, 15),
182 /** 4.22 - Unprocessable Entity */
183 COAP_RESPONSE_CODE_UNPROCESSABLE_ENTITY = COAP_MAKE_RESPONSE_CODE(4, 22),
184 /** 4.29 - Too Many Requests */
185 COAP_RESPONSE_CODE_TOO_MANY_REQUESTS = COAP_MAKE_RESPONSE_CODE(4, 29),
186 /** 5.00 - Internal Server Error */
187 COAP_RESPONSE_CODE_INTERNAL_ERROR = COAP_MAKE_RESPONSE_CODE(5, 0),
188 /** 5.01 - Not Implemented */
189 COAP_RESPONSE_CODE_NOT_IMPLEMENTED = COAP_MAKE_RESPONSE_CODE(5, 1),
190 /** 5.02 - Bad Gateway */
191 COAP_RESPONSE_CODE_BAD_GATEWAY = COAP_MAKE_RESPONSE_CODE(5, 2),
192 /** 5.03 - Service Unavailable */
193 COAP_RESPONSE_CODE_SERVICE_UNAVAILABLE = COAP_MAKE_RESPONSE_CODE(5, 3),
194 /** 5.04 - Gateway Timeout */
195 COAP_RESPONSE_CODE_GATEWAY_TIMEOUT = COAP_MAKE_RESPONSE_CODE(5, 4),
196 /** 5.05 - Proxying Not Supported */
197 COAP_RESPONSE_CODE_PROXYING_NOT_SUPPORTED =
198 COAP_MAKE_RESPONSE_CODE(5, 5)
199 };
200
201 /** @cond INTERNAL_HIDDEN */
202
203 #define COAP_CODE_EMPTY (0)
204
205 #define COAP_TOKEN_MAX_LEN 8UL
206
207 /** @endcond */
208
209 /**
210 * @brief Set of Content-Format option values for CoAP.
211 *
212 * To be used when encoding or decoding a Content-Format option.
213 */
214 enum coap_content_format {
215 COAP_CONTENT_FORMAT_TEXT_PLAIN = 0, /**< text/plain;charset=utf-8 */
216 COAP_CONTENT_FORMAT_APP_LINK_FORMAT = 40, /**< application/link-format */
217 COAP_CONTENT_FORMAT_APP_XML = 41, /**< application/xml */
218 COAP_CONTENT_FORMAT_APP_OCTET_STREAM = 42, /**< application/octet-stream */
219 COAP_CONTENT_FORMAT_APP_EXI = 47, /**< application/exi */
220 COAP_CONTENT_FORMAT_APP_JSON = 50, /**< application/json */
221 COAP_CONTENT_FORMAT_APP_JSON_PATCH_JSON = 51, /**< application/json-patch+json */
222 COAP_CONTENT_FORMAT_APP_MERGE_PATCH_JSON = 52, /**< application/merge-patch+json */
223 COAP_CONTENT_FORMAT_APP_CBOR = 60 /**< application/cbor */
224 };
225
226 /**
227 * @brief Set of No-Response option values for CoAP.
228 *
229 * To be used when encoding or decoding a No-Response option defined
230 * in RFC 7967.
231 */
232 enum coap_no_response {
233 COAP_NO_RESPONSE_SUPPRESS_2_XX = 0x02,
234 COAP_NO_RESPONSE_SUPPRESS_4_XX = 0x08,
235 COAP_NO_RESPONSE_SUPPRESS_5_XX = 0x10,
236
237 COAP_NO_RESPONSE_SUPPRESS_ALL = COAP_NO_RESPONSE_SUPPRESS_2_XX |
238 COAP_NO_RESPONSE_SUPPRESS_4_XX |
239 COAP_NO_RESPONSE_SUPPRESS_5_XX,
240 };
241
242 /** @cond INTERNAL_HIDDEN */
243
244 /* block option helper */
245 #define GET_BLOCK_NUM(v) ((v) >> 4)
246 #define GET_BLOCK_SIZE(v) (((v) & 0x7))
247 #define GET_MORE(v) (!!((v) & 0x08))
248
249 /** @endcond */
250
251 struct coap_observer;
252 struct coap_packet;
253 struct coap_pending;
254 struct coap_reply;
255 struct coap_resource;
256
257 /**
258 * @typedef coap_method_t
259 * @brief Type of the callback being called when a resource's method is
260 * invoked by the remote entity.
261 */
262 typedef int (*coap_method_t)(struct coap_resource *resource,
263 struct coap_packet *request,
264 struct sockaddr *addr, socklen_t addr_len);
265
266 /**
267 * @typedef coap_notify_t
268 * @brief Type of the callback being called when a resource's has observers
269 * to be informed when an update happens.
270 */
271 typedef void (*coap_notify_t)(struct coap_resource *resource,
272 struct coap_observer *observer);
273
274 /**
275 * @brief Description of CoAP resource.
276 *
277 * CoAP servers often want to register resources, so that clients can act on
278 * them, by fetching their state or requesting updates to them.
279 */
280 struct coap_resource {
281 /** Which function to be called for each CoAP method */
282 coap_method_t get, post, put, del, fetch, patch, ipatch;
283 /** Notify function to call */
284 coap_notify_t notify;
285 /** Resource path */
286 const char * const *path;
287 /** User specific opaque data */
288 void *user_data;
289 /** List of resource observers */
290 sys_slist_t observers;
291 /** Resource age */
292 int age;
293 };
294
295 /**
296 * @brief Represents a remote device that is observing a local resource.
297 */
298 struct coap_observer {
299 /** Observer list node */
300 sys_snode_t list;
301 /** Observer connection end point information */
302 struct sockaddr addr;
303 /** Observer token */
304 uint8_t token[8];
305 /** Extended token length */
306 uint8_t tkl;
307 };
308
309 /**
310 * @brief Representation of a CoAP Packet.
311 */
312 struct coap_packet {
313 uint8_t *data; /**< User allocated buffer */
314 uint16_t offset; /**< CoAP lib maintains offset while adding data */
315 uint16_t max_len; /**< Max CoAP packet data length */
316 uint8_t hdr_len; /**< CoAP header length */
317 uint16_t opt_len; /**< Total options length (delta + len + value) */
318 uint16_t delta; /**< Used for delta calculation in CoAP packet */
319 #if defined(CONFIG_COAP_KEEP_USER_DATA) || defined(DOXYGEN)
320 /**
321 * Application specific user data.
322 * Only available when @kconfig{CONFIG_COAP_KEEP_USER_DATA} is enabled.
323 */
324 void *user_data;
325 #endif
326 };
327
328 /**
329 * @brief Representation of a CoAP option.
330 */
331 struct coap_option {
332 uint16_t delta; /**< Option delta */
333 #if defined(CONFIG_COAP_EXTENDED_OPTIONS_LEN)
334 uint16_t len;
335 uint8_t value[CONFIG_COAP_EXTENDED_OPTIONS_LEN_VALUE];
336 #else
337 uint8_t len; /**< Option length */
338 uint8_t value[12]; /**< Option value */
339 #endif
340 };
341
342 /**
343 * @typedef coap_reply_t
344 * @brief Helper function to be called when a response matches the
345 * a pending request.
346 * When sending blocks, the callback is only executed when the
347 * reply of the last block is received.
348 * i.e. it is not called when the code of the reply is 'continue' (2.31).
349 */
350 typedef int (*coap_reply_t)(const struct coap_packet *response,
351 struct coap_reply *reply,
352 const struct sockaddr *from);
353
354 /**
355 * @brief CoAP transmission parameters.
356 */
357 struct coap_transmission_parameters {
358 /** Initial ACK timeout. Value is used as a base value to retry pending CoAP packets. */
359 uint32_t ack_timeout;
360 #if defined(CONFIG_COAP_RANDOMIZE_ACK_TIMEOUT) || defined(__DOXYGEN__)
361 /**
362 * Set CoAP ack random factor. A value of 150 means a factor of 1.5. A value of 0 defaults
363 * to @kconfig{CONFIG_COAP_ACK_RANDOM_PERCENT}. The value must be >= 100.
364 */
365 uint16_t ack_random_percent;
366 #endif /* defined(CONFIG_COAP_RANDOMIZE_ACK_TIMEOUT) */
367 /** Set CoAP retry backoff factor. A value of 200 means a factor of 2.0. */
368 uint16_t coap_backoff_percent;
369 /** Maximum number of retransmissions. */
370 uint8_t max_retransmission;
371 };
372
373 /**
374 * @brief Represents a request awaiting for an acknowledgment (ACK).
375 */
376 struct coap_pending {
377 struct sockaddr addr; /**< Remote address */
378 int64_t t0; /**< Time when the request was sent */
379 uint32_t timeout; /**< Timeout in ms */
380 uint16_t id; /**< Message id */
381 uint8_t *data; /**< User allocated buffer */
382 uint16_t len; /**< Length of the CoAP packet */
383 uint8_t retries; /**< Number of times the request has been sent */
384 struct coap_transmission_parameters params; /**< Transmission parameters */
385 };
386
387 /**
388 * @brief Represents the handler for the reply of a request, it is
389 * also used when observing resources.
390 */
391 struct coap_reply {
392 /** CoAP reply callback */
393 coap_reply_t reply;
394 /** User specific opaque data */
395 void *user_data;
396 /** Reply age */
397 int age;
398 /** Reply id */
399 uint16_t id;
400 /** Reply token */
401 uint8_t token[8];
402 /** Extended token length */
403 uint8_t tkl;
404 };
405
406 /**
407 * @brief Returns the version present in a CoAP packet.
408 *
409 * @param cpkt CoAP packet representation
410 *
411 * @return the CoAP version in packet
412 */
413 uint8_t coap_header_get_version(const struct coap_packet *cpkt);
414
415 /**
416 * @brief Returns the type of the CoAP packet.
417 *
418 * @param cpkt CoAP packet representation
419 *
420 * @return the type of the packet
421 */
422 uint8_t coap_header_get_type(const struct coap_packet *cpkt);
423
424 /**
425 * @brief Returns the token (if any) in the CoAP packet.
426 *
427 * @param cpkt CoAP packet representation
428 * @param token Where to store the token, must point to a buffer containing
429 * at least COAP_TOKEN_MAX_LEN bytes
430 *
431 * @return Token length in the CoAP packet (0 - COAP_TOKEN_MAX_LEN).
432 */
433 uint8_t coap_header_get_token(const struct coap_packet *cpkt, uint8_t *token);
434
435 /**
436 * @brief Returns the code of the CoAP packet.
437 *
438 * @param cpkt CoAP packet representation
439 *
440 * @return the code present in the packet
441 */
442 uint8_t coap_header_get_code(const struct coap_packet *cpkt);
443
444 /**
445 * @brief Modifies the code of the CoAP packet.
446 *
447 * @param cpkt CoAP packet representation
448 * @param code CoAP code
449 * @return 0 on success, -EINVAL on failure
450 */
451 int coap_header_set_code(const struct coap_packet *cpkt, uint8_t code);
452
453 /**
454 * @brief Returns the message id associated with the CoAP packet.
455 *
456 * @param cpkt CoAP packet representation
457 *
458 * @return the message id present in the packet
459 */
460 uint16_t coap_header_get_id(const struct coap_packet *cpkt);
461
462 /**
463 * @brief Returns the data pointer and length of the CoAP packet.
464 *
465 * @param cpkt CoAP packet representation
466 * @param len Total length of CoAP payload
467 *
468 * @return data pointer and length if payload exists
469 * NULL pointer and length set to 0 in case there is no payload
470 */
471 const uint8_t *coap_packet_get_payload(const struct coap_packet *cpkt,
472 uint16_t *len);
473
474 /**
475 * @brief Verify if CoAP URI path matches with provided options.
476 *
477 * @param path Null-terminated array of strings.
478 * @param options Parsed options from coap_packet_parse()
479 * @param opt_num Number of options
480 *
481 * @return true if the CoAP URI path matches,
482 * false otherwise.
483 */
484 bool coap_uri_path_match(const char * const *path,
485 struct coap_option *options,
486 uint8_t opt_num);
487
488 /**
489 * @brief Parses the CoAP packet in data, validating it and
490 * initializing @a cpkt. @a data must remain valid while @a cpkt is used.
491 *
492 * @param cpkt Packet to be initialized from received @a data.
493 * @param data Data containing a CoAP packet, its @a data pointer is
494 * positioned on the start of the CoAP packet.
495 * @param len Length of the data
496 * @param options Parse options and cache its details.
497 * @param opt_num Number of options
498 *
499 * @retval 0 in case of success.
500 * @retval -EINVAL in case of invalid input args.
501 * @retval -EBADMSG in case of malformed coap packet header.
502 * @retval -EILSEQ in case of malformed coap options.
503 */
504 int coap_packet_parse(struct coap_packet *cpkt, uint8_t *data, uint16_t len,
505 struct coap_option *options, uint8_t opt_num);
506
507 /**
508 * @brief Parses provided coap path (with/without query) or query and appends
509 * that as options to the @a cpkt.
510 *
511 * @param cpkt Packet to append path and query options for.
512 * @param path Null-terminated string of coap path, query or both.
513 *
514 * @retval 0 in case of success or negative in case of error.
515 */
516 int coap_packet_set_path(struct coap_packet *cpkt, const char *path);
517
518 /**
519 * @brief Creates a new CoAP Packet from input data.
520 *
521 * @param cpkt New packet to be initialized using the storage from @a data.
522 * @param data Data that will contain a CoAP packet information
523 * @param max_len Maximum allowable length of data
524 * @param ver CoAP header version
525 * @param type CoAP header type
526 * @param token_len CoAP header token length
527 * @param token CoAP header token
528 * @param code CoAP header code
529 * @param id CoAP header message id
530 *
531 * @return 0 in case of success or negative in case of error.
532 */
533 int coap_packet_init(struct coap_packet *cpkt, uint8_t *data, uint16_t max_len,
534 uint8_t ver, uint8_t type, uint8_t token_len,
535 const uint8_t *token, uint8_t code, uint16_t id);
536
537 /**
538 * @brief Create a new CoAP Acknowledgment message for given request.
539 *
540 * This function works like @ref coap_packet_init, filling CoAP header type,
541 * CoAP header token, and CoAP header message id fields according to
542 * acknowledgment rules.
543 *
544 * @param cpkt New packet to be initialized using the storage from @a data.
545 * @param req CoAP request packet that is being acknowledged
546 * @param data Data that will contain a CoAP packet information
547 * @param max_len Maximum allowable length of data
548 * @param code CoAP header code
549 *
550 * @return 0 in case of success or negative in case of error.
551 */
552 int coap_ack_init(struct coap_packet *cpkt, const struct coap_packet *req,
553 uint8_t *data, uint16_t max_len, uint8_t code);
554
555 /**
556 * @brief Create a new CoAP Reset message for given request.
557 *
558 * This function works like @ref coap_packet_init, filling CoAP header type,
559 * and CoAP header message id fields.
560 *
561 * @param cpkt New packet to be initialized using the storage from @a data.
562 * @param req CoAP request packet that is being acknowledged
563 * @param data Data that will contain a CoAP packet information
564 * @param max_len Maximum allowable length of data
565 *
566 * @return 0 in case of success or negative in case of error.
567 */
568 int coap_rst_init(struct coap_packet *cpkt, const struct coap_packet *req,
569 uint8_t *data, uint16_t max_len);
570 /**
571 * @brief Returns a randomly generated array of 8 bytes, that can be
572 * used as a message's token.
573 *
574 * @return a 8-byte pseudo-random token.
575 */
576 uint8_t *coap_next_token(void);
577
578 /**
579 * @brief Helper to generate message ids
580 *
581 * @return a new message id
582 */
583 uint16_t coap_next_id(void);
584
585 /**
586 * @brief Return the values associated with the option of value @a
587 * code.
588 *
589 * @param cpkt CoAP packet representation
590 * @param code Option number to look for
591 * @param options Array of #coap_option where to store the value
592 * of the options found
593 * @param veclen Number of elements in the options array
594 *
595 * @return The number of options found in packet matching code,
596 * negative on error.
597 */
598 int coap_find_options(const struct coap_packet *cpkt, uint16_t code,
599 struct coap_option *options, uint16_t veclen);
600
601 /**
602 * @brief Appends an option to the packet.
603 *
604 * Note: options can be added out of numeric order of their codes. But
605 * it's more efficient to add them in order.
606 *
607 * @param cpkt Packet to be updated
608 * @param code Option code to add to the packet, see #coap_option_num
609 * @param value Pointer to the value of the option, will be copied to the
610 * packet
611 * @param len Size of the data to be added
612 *
613 * @return 0 in case of success or negative in case of error.
614 */
615 int coap_packet_append_option(struct coap_packet *cpkt, uint16_t code,
616 const uint8_t *value, uint16_t len);
617
618 /**
619 * @brief Remove an option from the packet.
620 *
621 * @param cpkt Packet to be updated
622 * @param code Option code to remove from the packet, see #coap_option_num
623 *
624 * @return 0 in case of success or negative in case of error.
625 */
626 int coap_packet_remove_option(struct coap_packet *cpkt, uint16_t code);
627
628 /**
629 * @brief Converts an option to its integer representation.
630 *
631 * Assumes that the number is encoded in the network byte order in the
632 * option.
633 *
634 * @param option Pointer to the option value, retrieved by
635 * coap_find_options()
636 *
637 * @return The integer representation of the option
638 */
639 unsigned int coap_option_value_to_int(const struct coap_option *option);
640
641 /**
642 * @brief Appends an integer value option to the packet.
643 *
644 * The option must be added in numeric order of their codes, and the
645 * least amount of bytes will be used to encode the value.
646 *
647 * @param cpkt Packet to be updated
648 * @param code Option code to add to the packet, see #coap_option_num
649 * @param val Integer value to be added
650 *
651 * @return 0 in case of success or negative in case of error.
652 */
653 int coap_append_option_int(struct coap_packet *cpkt, uint16_t code,
654 unsigned int val);
655
656 /**
657 * @brief Append payload marker to CoAP packet
658 *
659 * @param cpkt Packet to append the payload marker (0xFF)
660 *
661 * @return 0 in case of success or negative in case of error.
662 */
663 int coap_packet_append_payload_marker(struct coap_packet *cpkt);
664
665 /**
666 * @brief Append payload to CoAP packet
667 *
668 * @param cpkt Packet to append the payload
669 * @param payload CoAP packet payload
670 * @param payload_len CoAP packet payload len
671 *
672 * @return 0 in case of success or negative in case of error.
673 */
674 int coap_packet_append_payload(struct coap_packet *cpkt, const uint8_t *payload,
675 uint16_t payload_len);
676
677 /**
678 * @brief Check if a CoAP packet is a CoAP request.
679 *
680 * @param cpkt Packet to be checked.
681 *
682 * @return true if the packet is a request,
683 * false otherwise.
684 */
685 bool coap_packet_is_request(const struct coap_packet *cpkt);
686
687 /**
688 * @brief When a request is received, call the appropriate methods of
689 * the matching resources.
690 *
691 * @param cpkt Packet received
692 * @param resources Array of known resources
693 * @param resources_len Number of resources in the array
694 * @param options Parsed options from coap_packet_parse()
695 * @param opt_num Number of options
696 * @param addr Peer address
697 * @param addr_len Peer address length
698 *
699 * @retval >= 0 in case of success.
700 * @retval -ENOTSUP in case of invalid request code.
701 * @retval -EPERM in case resource handler is not implemented.
702 * @retval -ENOENT in case the resource is not found.
703 */
704 int coap_handle_request_len(struct coap_packet *cpkt,
705 struct coap_resource *resources,
706 size_t resources_len,
707 struct coap_option *options,
708 uint8_t opt_num,
709 struct sockaddr *addr, socklen_t addr_len);
710
711 /**
712 * @brief When a request is received, call the appropriate methods of
713 * the matching resources.
714 *
715 * @param cpkt Packet received
716 * @param resources Array of known resources (terminated with empty resource)
717 * @param options Parsed options from coap_packet_parse()
718 * @param opt_num Number of options
719 * @param addr Peer address
720 * @param addr_len Peer address length
721 *
722 * @retval >= 0 in case of success.
723 * @retval -ENOTSUP in case of invalid request code.
724 * @retval -EPERM in case resource handler is not implemented.
725 * @retval -ENOENT in case the resource is not found.
726 */
727 int coap_handle_request(struct coap_packet *cpkt,
728 struct coap_resource *resources,
729 struct coap_option *options,
730 uint8_t opt_num,
731 struct sockaddr *addr, socklen_t addr_len);
732
733 /**
734 * Represents the size of each block that will be transferred using
735 * block-wise transfers [RFC7959]:
736 *
737 * Each entry maps directly to the value that is used in the wire.
738 *
739 * https://tools.ietf.org/html/rfc7959
740 */
741 enum coap_block_size {
742 COAP_BLOCK_16, /**< 16-byte block size */
743 COAP_BLOCK_32, /**< 32-byte block size */
744 COAP_BLOCK_64, /**< 64-byte block size */
745 COAP_BLOCK_128, /**< 128-byte block size */
746 COAP_BLOCK_256, /**< 256-byte block size */
747 COAP_BLOCK_512, /**< 512-byte block size */
748 COAP_BLOCK_1024, /**< 1024-byte block size */
749 };
750
751 /**
752 * @brief Helper for converting the enumeration to the size expressed
753 * in bytes.
754 *
755 * @param block_size The block size to be converted
756 *
757 * @return The size in bytes that the block_size represents
758 */
coap_block_size_to_bytes(enum coap_block_size block_size)759 static inline uint16_t coap_block_size_to_bytes(
760 enum coap_block_size block_size)
761 {
762 return (1 << (block_size + 4));
763 }
764
765 /**
766 * @brief Helper for converting block size in bytes to enumeration.
767 *
768 * NOTE: Only valid CoAP block sizes map correctly.
769 *
770 * @param bytes CoAP block size in bytes.
771 * @return enum coap_block_size
772 */
coap_bytes_to_block_size(uint16_t bytes)773 static inline enum coap_block_size coap_bytes_to_block_size(uint16_t bytes)
774 {
775 int sz = u32_count_trailing_zeros(bytes) - 4;
776
777 if (sz < COAP_BLOCK_16) {
778 return COAP_BLOCK_16;
779 }
780 if (sz > COAP_BLOCK_1024) {
781 return COAP_BLOCK_1024;
782 }
783 return (enum coap_block_size)sz;
784 }
785
786 /**
787 * @brief Represents the current state of a block-wise transaction.
788 */
789 struct coap_block_context {
790 /** Total size of the block-wise transaction */
791 size_t total_size;
792 /** Current size of the block-wise transaction */
793 size_t current;
794 /** Block size */
795 enum coap_block_size block_size;
796 };
797
798 /**
799 * @brief Initializes the context of a block-wise transfer.
800 *
801 * @param ctx The context to be initialized
802 * @param block_size The size of the block
803 * @param total_size The total size of the transfer, if known
804 *
805 * @return 0 in case of success or negative in case of error.
806 */
807 int coap_block_transfer_init(struct coap_block_context *ctx,
808 enum coap_block_size block_size,
809 size_t total_size);
810
811 /**
812 * @brief Append BLOCK1 or BLOCK2 option to the packet.
813 *
814 * If the CoAP packet is a request then BLOCK1 is appended
815 * otherwise BLOCK2 is appended.
816 *
817 * @param cpkt Packet to be updated
818 * @param ctx Block context from which to retrieve the
819 * information for the block option
820 *
821 * @return 0 in case of success or negative in case of error.
822 */
823 int coap_append_descriptive_block_option(struct coap_packet *cpkt, struct coap_block_context *ctx);
824
825 /**
826 * @brief Check if a descriptive block option is set in the packet.
827 *
828 * If the CoAP packet is a request then an available BLOCK1 option
829 * would be checked otherwise a BLOCK2 option would be checked.
830 *
831 * @param cpkt Packet to be checked.
832 *
833 * @return true if the corresponding block option is set,
834 * false otherwise.
835 */
836 bool coap_has_descriptive_block_option(struct coap_packet *cpkt);
837
838 /**
839 * @brief Remove BLOCK1 or BLOCK2 option from the packet.
840 *
841 * If the CoAP packet is a request then BLOCK1 is removed
842 * otherwise BLOCK2 is removed.
843 *
844 * @param cpkt Packet to be updated.
845 *
846 * @return 0 in case of success or negative in case of error.
847 */
848 int coap_remove_descriptive_block_option(struct coap_packet *cpkt);
849
850 /**
851 * @brief Check if BLOCK1 or BLOCK2 option has more flag set
852 *
853 * @param cpkt Packet to be checked.
854 * @return true If more flag is set in BLOCK1 or BLOCK2
855 * @return false If MORE flag is not set or BLOCK header not found.
856 */
857 bool coap_block_has_more(struct coap_packet *cpkt);
858
859 /**
860 * @brief Append BLOCK1 option to the packet.
861 *
862 * @param cpkt Packet to be updated
863 * @param ctx Block context from which to retrieve the
864 * information for the Block1 option
865 *
866 * @return 0 in case of success or negative in case of error.
867 */
868 int coap_append_block1_option(struct coap_packet *cpkt,
869 struct coap_block_context *ctx);
870
871 /**
872 * @brief Append BLOCK2 option to the packet.
873 *
874 * @param cpkt Packet to be updated
875 * @param ctx Block context from which to retrieve the
876 * information for the Block2 option
877 *
878 * @return 0 in case of success or negative in case of error.
879 */
880 int coap_append_block2_option(struct coap_packet *cpkt,
881 struct coap_block_context *ctx);
882
883 /**
884 * @brief Append SIZE1 option to the packet.
885 *
886 * @param cpkt Packet to be updated
887 * @param ctx Block context from which to retrieve the
888 * information for the Size1 option
889 *
890 * @return 0 in case of success or negative in case of error.
891 */
892 int coap_append_size1_option(struct coap_packet *cpkt,
893 struct coap_block_context *ctx);
894
895 /**
896 * @brief Append SIZE2 option to the packet.
897 *
898 * @param cpkt Packet to be updated
899 * @param ctx Block context from which to retrieve the
900 * information for the Size2 option
901 *
902 * @return 0 in case of success or negative in case of error.
903 */
904 int coap_append_size2_option(struct coap_packet *cpkt,
905 struct coap_block_context *ctx);
906
907 /**
908 * @brief Get the integer representation of a CoAP option.
909 *
910 * @param cpkt Packet to be inspected
911 * @param code CoAP option code
912 *
913 * @return Integer value >= 0 in case of success or negative in case
914 * of error.
915 */
916 int coap_get_option_int(const struct coap_packet *cpkt, uint16_t code);
917
918 /**
919 * @brief Get the block size, more flag and block number from the
920 * CoAP block1 option.
921 *
922 * @param cpkt Packet to be inspected
923 * @param has_more Is set to the value of the more flag
924 * @param block_number Is set to the number of the block
925 *
926 * @return Integer value of the block size in case of success
927 * or negative in case of error.
928 */
929 int coap_get_block1_option(const struct coap_packet *cpkt, bool *has_more, uint32_t *block_number);
930
931 /**
932 * @brief Get values from CoAP block2 option.
933 *
934 * Decode block number, more flag and block size from option.
935 *
936 * @param cpkt Packet to be inspected
937 * @param has_more Is set to the value of the more flag
938 * @param block_number Is set to the number of the block
939 *
940 * @return Integer value of the block size in case of success
941 * or negative in case of error.
942 */
943 int coap_get_block2_option(const struct coap_packet *cpkt, bool *has_more,
944 uint32_t *block_number);
945
946 /**
947 * @brief Retrieves BLOCK{1,2} and SIZE{1,2} from @a cpkt and updates
948 * @a ctx accordingly.
949 *
950 * @param cpkt Packet in which to look for block-wise transfers options
951 * @param ctx Block context to be updated
952 *
953 * @return 0 in case of success or negative in case of error.
954 */
955 int coap_update_from_block(const struct coap_packet *cpkt,
956 struct coap_block_context *ctx);
957
958 /**
959 * @brief Updates @a ctx according to @a option set in @a cpkt
960 * so after this is called the current entry indicates the correct
961 * offset in the body of data being transferred.
962 *
963 * @param cpkt Packet in which to look for block-wise transfers options
964 * @param ctx Block context to be updated
965 * @param option Either COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2
966 *
967 * @return The offset in the block-wise transfer, 0 if the transfer
968 * has finished or a negative value in case of an error.
969 */
970 int coap_next_block_for_option(const struct coap_packet *cpkt,
971 struct coap_block_context *ctx,
972 enum coap_option_num option);
973
974 /**
975 * @brief Updates @a ctx so after this is called the current entry
976 * indicates the correct offset in the body of data being
977 * transferred.
978 *
979 * @param cpkt Packet in which to look for block-wise transfers options
980 * @param ctx Block context to be updated
981 *
982 * @return The offset in the block-wise transfer, 0 if the transfer
983 * has finished.
984 */
985 size_t coap_next_block(const struct coap_packet *cpkt,
986 struct coap_block_context *ctx);
987
988 /**
989 * @brief Indicates that the remote device referenced by @a addr, with
990 * @a request, wants to observe a resource.
991 *
992 * @param observer Observer to be initialized
993 * @param request Request on which the observer will be based
994 * @param addr Address of the remote device
995 */
996 void coap_observer_init(struct coap_observer *observer,
997 const struct coap_packet *request,
998 const struct sockaddr *addr);
999
1000 /**
1001 * @brief After the observer is initialized, associate the observer
1002 * with an resource.
1003 *
1004 * @param resource Resource to add an observer
1005 * @param observer Observer to be added
1006 *
1007 * @return true if this is the first observer added to this resource.
1008 */
1009 bool coap_register_observer(struct coap_resource *resource,
1010 struct coap_observer *observer);
1011
1012 /**
1013 * @brief Remove this observer from the list of registered observers
1014 * of that resource.
1015 *
1016 * @param resource Resource in which to remove the observer
1017 * @param observer Observer to be removed
1018 *
1019 * @return true if the observer was found and removed.
1020 */
1021 bool coap_remove_observer(struct coap_resource *resource,
1022 struct coap_observer *observer);
1023
1024 /**
1025 * @brief Returns the observer that matches address @a addr
1026 * and has token @a token.
1027 *
1028 * @param observers Pointer to the array of observers
1029 * @param len Size of the array of observers
1030 * @param addr Address of the endpoint observing a resource
1031 * @param token Pointer to the token
1032 * @param token_len Length of valid bytes in the token
1033 *
1034 * @return A pointer to a observer if a match is found, NULL
1035 * otherwise.
1036 */
1037 struct coap_observer *coap_find_observer(
1038 struct coap_observer *observers, size_t len,
1039 const struct sockaddr *addr,
1040 const uint8_t *token, uint8_t token_len);
1041
1042 /**
1043 * @brief Returns the observer that matches address @a addr.
1044 *
1045 * @param observers Pointer to the array of observers
1046 * @param len Size of the array of observers
1047 * @param addr Address of the endpoint observing a resource
1048 *
1049 * @note The function coap_find_observer() should be preferred
1050 * if both the observer's address and token are known.
1051 *
1052 * @return A pointer to a observer if a match is found, NULL
1053 * otherwise.
1054 */
1055 struct coap_observer *coap_find_observer_by_addr(
1056 struct coap_observer *observers, size_t len,
1057 const struct sockaddr *addr);
1058
1059 /**
1060 * @brief Returns the observer that has token @a token.
1061 *
1062 * @param observers Pointer to the array of observers
1063 * @param len Size of the array of observers
1064 * @param token Pointer to the token
1065 * @param token_len Length of valid bytes in the token
1066 *
1067 * @note The function coap_find_observer() should be preferred
1068 * if both the observer's address and token are known.
1069 *
1070 * @return A pointer to a observer if a match is found, NULL
1071 * otherwise.
1072 */
1073 struct coap_observer *coap_find_observer_by_token(
1074 struct coap_observer *observers, size_t len,
1075 const uint8_t *token, uint8_t token_len);
1076
1077 /**
1078 * @brief Returns the next available observer representation.
1079 *
1080 * @param observers Pointer to the array of observers
1081 * @param len Size of the array of observers
1082 *
1083 * @return A pointer to a observer if there's an available observer,
1084 * NULL otherwise.
1085 */
1086 struct coap_observer *coap_observer_next_unused(
1087 struct coap_observer *observers, size_t len);
1088
1089 /**
1090 * @brief Indicates that a reply is expected for @a request.
1091 *
1092 * @param reply Reply structure to be initialized
1093 * @param request Request from which @a reply will be based
1094 */
1095 void coap_reply_init(struct coap_reply *reply,
1096 const struct coap_packet *request);
1097
1098 /**
1099 * @brief Initialize a pending request with a request.
1100 *
1101 * The request's fields are copied into the pending struct, so @a
1102 * request doesn't have to live for as long as the pending struct
1103 * lives, but "data" that needs to live for at least that long.
1104 *
1105 * @param pending Structure representing the waiting for a
1106 * confirmation message, initialized with data from @a request
1107 * @param request Message waiting for confirmation
1108 * @param addr Address to send the retransmission
1109 * @param params Pointer to the CoAP transmission parameters struct,
1110 * or NULL to use default values
1111 *
1112 * @return 0 in case of success or negative in case of error.
1113 */
1114 int coap_pending_init(struct coap_pending *pending,
1115 const struct coap_packet *request,
1116 const struct sockaddr *addr,
1117 const struct coap_transmission_parameters *params);
1118
1119 /**
1120 * @brief Returns the next available pending struct, that can be used
1121 * to track the retransmission status of a request.
1122 *
1123 * @param pendings Pointer to the array of #coap_pending structures
1124 * @param len Size of the array of #coap_pending structures
1125 *
1126 * @return pointer to a free #coap_pending structure, NULL in case
1127 * none could be found.
1128 */
1129 struct coap_pending *coap_pending_next_unused(
1130 struct coap_pending *pendings, size_t len);
1131
1132 /**
1133 * @brief Returns the next available reply struct, so it can be used
1134 * to track replies and notifications received.
1135 *
1136 * @param replies Pointer to the array of #coap_reply structures
1137 * @param len Size of the array of #coap_reply structures
1138 *
1139 * @return pointer to a free #coap_reply structure, NULL in case
1140 * none could be found.
1141 */
1142 struct coap_reply *coap_reply_next_unused(
1143 struct coap_reply *replies, size_t len);
1144
1145 /**
1146 * @brief After a response is received, returns if there is any
1147 * matching pending request exits. User has to clear all pending
1148 * retransmissions related to that response by calling
1149 * coap_pending_clear().
1150 *
1151 * @param response The received response
1152 * @param pendings Pointer to the array of #coap_reply structures
1153 * @param len Size of the array of #coap_reply structures
1154 *
1155 * @return pointer to the associated #coap_pending structure, NULL in
1156 * case none could be found.
1157 */
1158 struct coap_pending *coap_pending_received(
1159 const struct coap_packet *response,
1160 struct coap_pending *pendings, size_t len);
1161
1162 /**
1163 * @brief After a response is received, call coap_reply_t handler
1164 * registered in #coap_reply structure
1165 *
1166 * @param response A response received
1167 * @param from Address from which the response was received
1168 * @param replies Pointer to the array of #coap_reply structures
1169 * @param len Size of the array of #coap_reply structures
1170 *
1171 * @return Pointer to the reply matching the packet received, NULL if
1172 * none could be found.
1173 */
1174 struct coap_reply *coap_response_received(
1175 const struct coap_packet *response,
1176 const struct sockaddr *from,
1177 struct coap_reply *replies, size_t len);
1178
1179 /**
1180 * @brief Returns the next pending about to expire, pending->timeout
1181 * informs how many ms to next expiration.
1182 *
1183 * @param pendings Pointer to the array of #coap_pending structures
1184 * @param len Size of the array of #coap_pending structures
1185 *
1186 * @return The next #coap_pending to expire, NULL if none is about to
1187 * expire.
1188 */
1189 struct coap_pending *coap_pending_next_to_expire(
1190 struct coap_pending *pendings, size_t len);
1191
1192 /**
1193 * @brief After a request is sent, user may want to cycle the pending
1194 * retransmission so the timeout is updated.
1195 *
1196 * @param pending Pending representation to have its timeout updated
1197 *
1198 * @return false if this is the last retransmission.
1199 */
1200 bool coap_pending_cycle(struct coap_pending *pending);
1201
1202 /**
1203 * @brief Cancels the pending retransmission, so it again becomes
1204 * available.
1205 *
1206 * @param pending Pending representation to be canceled
1207 */
1208 void coap_pending_clear(struct coap_pending *pending);
1209
1210 /**
1211 * @brief Cancels all pending retransmissions, so they become
1212 * available again.
1213 *
1214 * @param pendings Pointer to the array of #coap_pending structures
1215 * @param len Size of the array of #coap_pending structures
1216 */
1217 void coap_pendings_clear(struct coap_pending *pendings, size_t len);
1218
1219 /**
1220 * @brief Count number of pending requests.
1221 *
1222 * @param len Number of elements in array.
1223 * @param pendings Array of pending requests.
1224 * @return count of elements where timeout is not zero.
1225 */
1226 size_t coap_pendings_count(struct coap_pending *pendings, size_t len);
1227
1228 /**
1229 * @brief Cancels awaiting for this reply, so it becomes available
1230 * again. User responsibility to free the memory associated with data.
1231 *
1232 * @param reply The reply to be canceled
1233 */
1234 void coap_reply_clear(struct coap_reply *reply);
1235
1236 /**
1237 * @brief Cancels all replies, so they become available again.
1238 *
1239 * @param replies Pointer to the array of #coap_reply structures
1240 * @param len Size of the array of #coap_reply structures
1241 */
1242 void coap_replies_clear(struct coap_reply *replies, size_t len);
1243
1244 /**
1245 * @brief Indicates that this resource was updated and that the @a
1246 * notify callback should be called for every registered observer.
1247 *
1248 * @param resource Resource that was updated
1249 *
1250 * @return 0 in case of success or negative in case of error.
1251 */
1252 int coap_resource_notify(struct coap_resource *resource);
1253
1254 /**
1255 * @brief Returns if this request is enabling observing a resource.
1256 *
1257 * @param request Request to be checked
1258 *
1259 * @return True if the request is enabling observing a resource, False
1260 * otherwise
1261 */
1262 bool coap_request_is_observe(const struct coap_packet *request);
1263
1264 /**
1265 * @brief Get currently active CoAP transmission parameters.
1266 *
1267 * @return CoAP transmission parameters structure.
1268 */
1269 struct coap_transmission_parameters coap_get_transmission_parameters(void);
1270
1271 /**
1272 * @brief Set CoAP transmission parameters.
1273 *
1274 * @param params Pointer to the transmission parameters structure.
1275 */
1276 void coap_set_transmission_parameters(const struct coap_transmission_parameters *params);
1277
1278 #ifdef __cplusplus
1279 }
1280 #endif
1281
1282 /**
1283 * @}
1284 */
1285
1286 #endif /* ZEPHYR_INCLUDE_NET_COAP_H_ */
1287