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