1/*
2 * coap_pdu_internal.h -- CoAP PDU structure
3 *
4 * Copyright (C) 2010-2023 Olaf Bergmann <bergmann@tzi.org>
5 *
6 * SPDX-License-Identifier: BSD-2-Clause
7 *
8 * This file is part of the CoAP library libcoap. Please see README for terms
9 * of use.
10 */
11
12/**
13 * @file coap_pdu_internal.h
14 * @brief CoAP PDU internal information
15 */
16
17#ifndef COAP_COAP_PDU_INTERNAL_H_
18#define COAP_COAP_PDU_INTERNAL_H_
19
20#include "coap_internal.h"
21
22#ifdef WITH_LWIP
23#include <lwip/pbuf.h>
24#endif
25
26#include <stdint.h>
27
28/**
29 * @ingroup internal_api
30 * @defgroup pdu_internal PDU
31 * Internal API for PDUs
32 * @{
33 */
34
35#define COAP_DEFAULT_VERSION      1 /* version of CoAP supported */
36
37/* TCP Message format constants, do not modify */
38#define COAP_MESSAGE_SIZE_OFFSET_TCP8 13
39#define COAP_MESSAGE_SIZE_OFFSET_TCP16 269 /* 13 + 256 */
40#define COAP_MESSAGE_SIZE_OFFSET_TCP32 65805 /* 269 + 65536 */
41
42/* Derived message size limits */
43#define COAP_MAX_MESSAGE_SIZE_TCP0 (COAP_MESSAGE_SIZE_OFFSET_TCP8-1) /* 12 */
44#define COAP_MAX_MESSAGE_SIZE_TCP8 (COAP_MESSAGE_SIZE_OFFSET_TCP16-1) /* 268 */
45#define COAP_MAX_MESSAGE_SIZE_TCP16 (COAP_MESSAGE_SIZE_OFFSET_TCP32-1) /* 65804 */
46#define COAP_MAX_MESSAGE_SIZE_TCP32 (COAP_MESSAGE_SIZE_OFFSET_TCP32+0xFFFFFFFF)
47#if COAP_OSCORE_SUPPORT
48/* for oscore encryption   */
49#define COAP_MAX_CHUNK_SIZE COAP_DEFAULT_MAX_PDU_RX_SIZE
50#define OSCORE_CRYPTO_BUFFER_SIZE (COAP_MAX_CHUNK_SIZE+16)
51#endif /* COAP_OSCORE_SUPPORT  */
52
53/* Extended Token constants */
54#define COAP_TOKEN_EXT_1B_TKL 13
55#define COAP_TOKEN_EXT_2B_TKL 14
56#define COAP_TOKEN_EXT_1B_BIAS 13
57#define COAP_TOKEN_EXT_2B_BIAS 269 /* 13 + 256 */
58
59#ifndef COAP_DEBUG_BUF_SIZE
60#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
61#define COAP_DEBUG_BUF_SIZE 128
62#else /* defined(WITH_CONTIKI) || defined(WITH_LWIP) */
63/* 1024 derived from RFC7252 4.6.  Message Size max payload */
64#define COAP_DEBUG_BUF_SIZE (8 + 1024 * 2)
65#endif /* defined(WITH_CONTIKI) || defined(WITH_LWIP) */
66#endif /* COAP_DEBUG_BUF_SIZE */
67
68#ifndef COAP_DEFAULT_MAX_PDU_RX_SIZE
69#if defined(WITH_LWIP)
70#define COAP_DEFAULT_MAX_PDU_RX_SIZE (COAP_MAX_MESSAGE_SIZE_TCP16+4UL)
71#elif defined(WITH_CONTIKI)
72#define COAP_DEFAULT_MAX_PDU_RX_SIZE (sizeof(coap_packet_t) + UIP_APPDATA_SIZE)
73#else
74/* 8 MiB max-message-size plus some space for options */
75#define COAP_DEFAULT_MAX_PDU_RX_SIZE (8UL*1024*1024+256)
76#endif
77#endif /* COAP_DEFAULT_MAX_PDU_RX_SIZE */
78
79/**
80 * Indicates that a response is suppressed. This will occur for error
81 * responses if the request was received via IP multicast.
82 */
83#define COAP_DROPPED_RESPONSE -2
84
85#define COAP_PDU_DELAYED -3
86
87#define COAP_PAYLOAD_START 0xFF /* payload marker */
88
89#define COAP_PDU_IS_EMPTY(pdu)     ((pdu)->code == 0)
90#define COAP_PDU_IS_REQUEST(pdu)   (!COAP_PDU_IS_EMPTY(pdu) && (pdu)->code < 32)
91#define COAP_PDU_IS_RESPONSE(pdu)  ((pdu)->code >= 64 && (pdu)->code < 224)
92#define COAP_PDU_IS_SIGNALING(pdu) ((pdu)->code >= 224)
93
94#define COAP_PDU_MAX_UDP_HEADER_SIZE 4
95#define COAP_PDU_MAX_TCP_HEADER_SIZE 6
96
97/**
98 * structure for CoAP PDUs
99 *
100 * Separate COAP_PDU_BUF is allocated with offsets held in coap_pdu_t.
101
102 * token, if any, follows the fixed size header, then optional options until
103 * payload marker (0xff) (if paylooad), then the optional payload.
104 *
105 * Memory layout is:
106 * <---header--->|<---token---><---options--->0xff<---payload--->
107 *
108 * header is addressed with a negative offset to token, its maximum size is
109 * max_hdr_size.
110 *
111 * allocated buffer always starts max_hdr_size before token.
112 *
113 * options starts at token + e_token_length.
114 * payload starts at data, its length is used_size - (data - token).
115 *
116 * alloc_size, used_size and max_size are the offsets from token.
117 */
118
119struct coap_pdu_t {
120  coap_pdu_type_t type;     /**< message type */
121  coap_pdu_code_t code;     /**< request method (value 1--31) or response code
122                                 (value 64-255) */
123  coap_mid_t mid;           /**< message id, if any, in regular host byte
124                                 order */
125  uint8_t max_hdr_size;     /**< space reserved for protocol-specific header */
126  uint8_t hdr_size;         /**< actual size used for protocol-specific
127                                 header (0 until header is encoded) */
128  uint8_t crit_opt;         /**< Set if unknown critical option for proxy */
129  uint16_t max_opt;         /**< highest option number in PDU */
130  uint32_t e_token_length;  /**< length of Token space (includes leading
131                                 extended bytes */
132  coap_bin_const_t actual_token; /**< Actual token in pdu */
133  size_t alloc_size;        /**< allocated storage for token, options and
134                                 payload */
135  size_t used_size;         /**< used bytes of storage for token, options and
136                                 payload */
137  size_t max_size;          /**< maximum size for token, options and payload,
138                                 or zero for variable size pdu */
139  uint8_t *token;           /**< first byte of token (or extended length bytes
140                                 prefix), if any, or options */
141  uint8_t *data;            /**< first byte of payload, if any */
142#ifdef WITH_LWIP
143  struct pbuf *pbuf;        /**< lwIP PBUF. The package data will always reside
144                             *   inside the pbuf's payload, but this pointer
145                             *   has to be kept because no exact offset can be
146                             *   given. This field must not be accessed from
147                             *   outside, because the pbuf's reference count
148                             *   is checked to be 1 when the pbuf is assigned
149                             *   to the pdu, and the pbuf stays exclusive to
150                             *   this pdu. */
151#endif
152  const uint8_t *body_data; /**< Holds ptr to re-assembled data or NULL */
153  size_t body_length;       /**< Holds body data length */
154  size_t body_offset;       /**< Holds body data offset */
155  size_t body_total;        /**< Holds body data total size */
156  coap_lg_xmit_t *lg_xmit;  /**< Holds ptr to lg_xmit if sending a set of
157                                 blocks */
158  coap_session_t *session;  /**< Session responsible for PDU or NULL */
159};
160
161/**
162 * Dynamically grows the size of @p pdu to @p new_size. The new size
163 * must not exceed the PDU's configure maximum size. On success, this
164 * function returns 1, otherwise 0.
165 *
166 * @param pdu      The PDU to resize.
167 * @param new_size The new size in bytes.
168 * @return         1 if the operation succeeded, 0 otherwise.
169 */
170int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size);
171
172/**
173 * Dynamically grows the size of @p pdu to @p new_size if needed. The new size
174 * must not exceed the PDU's configured maximum size. On success, this
175 * function returns 1, otherwise 0.
176 *
177 * @param pdu      The PDU to resize.
178 * @param new_size The new size in bytes.
179 * @return         1 if the operation succeeded, 0 otherwise.
180 */
181int coap_pdu_check_resize(coap_pdu_t *pdu, size_t new_size);
182
183/**
184* Interprets @p data to determine the number of bytes in the header.
185* This function returns @c 0 on error or a number greater than zero on success.
186*
187* @param proto  Session's protocol
188* @param data   The first byte of raw data to parse as CoAP PDU.
189*
190* @return       A value greater than zero on success or @c 0 on error.
191*/
192size_t coap_pdu_parse_header_size(coap_proto_t proto,
193                                  const uint8_t *data);
194
195/**
196 * Parses @p data to extract the message size.
197 * @p length must be at least coap_pdu_parse_header_size(proto, data).
198 * This function returns @c 0 on error or a number greater than zero on success.
199 *
200 * @param proto  Session's protocol
201 * @param data   The raw data to parse as CoAP PDU.
202 * @param length The actual size of @p data.
203 *
204 * @return       PDU size including token on success or @c 0 on error.
205 */
206size_t coap_pdu_parse_size(coap_proto_t proto,
207                           const uint8_t *data,
208                           size_t length);
209
210/**
211 * Decode the protocol specific header for the specified PDU.
212 * @param pdu A newly received PDU.
213 * @param proto The target wire protocol.
214 * @return 1 for success or 0 on error.
215 */
216
217int coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto);
218
219/**
220 * Verify consistency in the given CoAP PDU structure and locate the data.
221 * This function returns @c 0 on error or a number greater than zero on
222 * success.
223 * This function only parses the token and options, up to the payload start
224 * marker.
225 *
226 * @param pdu     The PDU structure to check.
227 *
228 * @return       1 on success or @c 0 on error.
229 */
230int coap_pdu_parse_opt(coap_pdu_t *pdu);
231
232/**
233 * Clears any contents from @p pdu and resets @c used_size,
234 * and @c data pointers. @c max_size is set to @p size, any
235 * other field is set to @c 0. Note that @p pdu must be a valid
236 * pointer to a coap_pdu_t object created e.g. by coap_pdu_init().
237 *
238 * @param pdu   The PDU to clear.
239 * @param size  The maximum size of the PDU.
240 */
241void coap_pdu_clear(coap_pdu_t *pdu, size_t size);
242
243/**
244 * Adds option of given @p number to @p pdu that is passed as first
245 * parameter.
246 *
247 * The internal version of coap_add_option() may cause an @p option to be
248 * inserted, even if there is any data in the @p pdu.
249 *
250 * Note: Where possible, the option @p data needs to be stripped of leading
251 * zeros (big endian) to reduce the amount of data needed in the PDU, as well
252 * as in some cases the maximum data size of an option can be exceeded if not
253 * stripped and hence be illegal. This is done by using coap_encode_var_safe()
254 * or coap_encode_var_safe8().
255 *
256 * @param pdu    The PDU where the option is to be added.
257 * @param number The number of the new option.
258 * @param len    The length of the new option.
259 * @param data   The data of the new option.
260 *
261 * @return The overall length of the option or @c 0 on failure.
262 */
263size_t coap_add_option_internal(coap_pdu_t *pdu,
264                                coap_option_num_t number,
265                                size_t len,
266                                const uint8_t *data);
267/**
268 * Removes (first) option of given number from the @p pdu.
269 *
270 * @param pdu   The PDU to remove the option from.
271 * @param number The number of the CoAP option to remove (first only removed).
272 *
273 * @return @c 1 if success else @c 0 if error.
274 */
275int coap_remove_option(coap_pdu_t *pdu, coap_option_num_t number);
276
277/**
278 * Inserts option of given number in the @p pdu with the appropriate data.
279 * The option will be inserted in the appropriate place in the options in
280 * the pdu.
281 *
282 * @param pdu    The PDU where the option is to be inserted.
283 * @param number The number of the new option.
284 * @param len    The length of the new option.
285 * @param data   The data of the new option.
286 *
287 * @return The overall length of the option or @c 0 on failure.
288 */
289size_t coap_insert_option(coap_pdu_t *pdu, coap_option_num_t number,
290                          size_t len, const uint8_t *data);
291
292/**
293 * Updates existing first option of given number in the @p pdu with the new
294 * data.
295 *
296 * @param pdu    The PDU where the option is to be updated.
297 * @param number The number of the option to update (first only updated).
298 * @param len    The length of the updated option.
299 * @param data   The data of the updated option.
300 *
301 * @return The overall length of the updated option or @c 0 on failure.
302 */
303size_t coap_update_option(coap_pdu_t *pdu,
304                          coap_option_num_t number,
305                          size_t len,
306                          const uint8_t *data);
307
308/**
309 * Compose the protocol specific header for the specified PDU.
310 *
311 * @param pdu A newly composed PDU.
312 * @param proto The target wire protocol.
313 *
314 * @return Number of header bytes prepended before pdu->token or 0 on error.
315 */
316
317size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto);
318
319/**
320 * Updates token in @p pdu with length @p len and @p data.
321 * This function returns @c 0 on error or a value greater than zero on success.
322 *
323 * @param pdu  The PDU where the token is to be updated.
324 * @param len  The length of the new token.
325 * @param data The token to add.
326 *
327 * @return     A value greater than zero on success, or @c 0 on error.
328 */
329int coap_update_token(coap_pdu_t *pdu,
330                      size_t len,
331                      const uint8_t *data);
332
333/**
334 * Check whether the option is allowed to be repeated or not.
335 * This function returns @c 0 if not repeatable or @c 1 if repeatable
336 *
337 * @param number The option number to check for repeatability.
338 *
339 * @return     @c 0 if not repeatable or @c 1 if repeatable.
340 */
341int coap_option_check_repeatable(coap_option_num_t number);
342
343/** @} */
344
345#endif /* COAP_COAP_PDU_INTERNAL_H_ */
346