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