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