Coverage Report

Created: 2025-10-10 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libcoap/include/coap3/coap_pdu_internal.h
Line
Count
Source
1
/*
2
 * coap_pdu_internal.h -- CoAP PDU structure
3
 *
4
 * Copyright (C) 2010-2025 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
#ifdef RIOT_VERSION
27
#include <limits.h>
28
#endif /* RIOT_VERSION */
29
30
#ifdef HAVE_LIMITS_H
31
#include <limits.h>
32
#endif /* HAVE_LIMITS_H */
33
34
#include <stdint.h>
35
36
#ifdef __cplusplus
37
extern "C" {
38
#endif
39
40
/**
41
 * @ingroup internal_api
42
 * @defgroup pdu_internal PDU
43
 * Internal API for PDUs
44
 * @{
45
 */
46
47
12.8k
#define COAP_DEFAULT_VERSION      1 /* version of CoAP supported */
48
49
/* TCP Message format constants, do not modify */
50
5.30k
#define COAP_MESSAGE_SIZE_OFFSET_TCP8 13
51
1.88k
#define COAP_MESSAGE_SIZE_OFFSET_TCP16 269 /* 13 + 256 */
52
725
#define COAP_MESSAGE_SIZE_OFFSET_TCP32 65805 /* 269 + 65536 */
53
54
/* Derived message size limits */
55
4.56k
#define COAP_MAX_MESSAGE_SIZE_TCP0 (COAP_MESSAGE_SIZE_OFFSET_TCP8-1) /* 12 */
56
1.16k
#define COAP_MAX_MESSAGE_SIZE_TCP8 (COAP_MESSAGE_SIZE_OFFSET_TCP16-1) /* 268 */
57
433
#define COAP_MAX_MESSAGE_SIZE_TCP16 (COAP_MESSAGE_SIZE_OFFSET_TCP32-1) /* 65804 */
58
#define COAP_MAX_MESSAGE_SIZE_TCP32 (COAP_MESSAGE_SIZE_OFFSET_TCP32+0xFFFFFFFF)
59
#if COAP_OSCORE_SUPPORT
60
/* for oscore encryption   */
61
0
#define COAP_MAX_CHUNK_SIZE COAP_DEFAULT_MAX_PDU_RX_SIZE
62
0
#define OSCORE_CRYPTO_BUFFER_SIZE (COAP_MAX_CHUNK_SIZE+16)
63
#endif /* COAP_OSCORE_SUPPORT  */
64
65
/* Extended Token constants */
66
11.0k
#define COAP_TOKEN_EXT_1B_TKL 13
67
292
#define COAP_TOKEN_EXT_2B_TKL 14
68
9.99k
#define COAP_TOKEN_EXT_1B_BIAS 13
69
398
#define COAP_TOKEN_EXT_2B_BIAS 269 /* 13 + 256 */
70
71
#ifndef COAP_DEBUG_BUF_SIZE
72
#if defined(WITH_CONTIKI) || defined(WITH_LWIP)
73
#define COAP_DEBUG_BUF_SIZE 128
74
#else /* defined(WITH_CONTIKI) || defined(WITH_LWIP) */
75
/* 1024 derived from RFC7252 4.6.  Message Size max payload */
76
#define COAP_DEBUG_BUF_SIZE (8 + 1024 * 2)
77
#endif /* defined(WITH_CONTIKI) || defined(WITH_LWIP) */
78
#endif /* COAP_DEBUG_BUF_SIZE */
79
80
#ifndef COAP_DEFAULT_MAX_PDU_RX_SIZE
81
#if defined(WITH_LWIP)
82
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (COAP_MAX_MESSAGE_SIZE_TCP16+6UL)
83
#elif defined(WITH_CONTIKI)
84
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (UIP_APPDATA_SIZE)
85
#elif (UINT_MAX < (8UL*1024*1024+256))
86
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (1500UL)
87
#elif defined(RIOT_VERSION) && COAP_DISABLE_TCP
88
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (1500UL)
89
#else
90
/* 8 MiB max-message-size plus some space for options */
91
10.7k
#define COAP_DEFAULT_MAX_PDU_RX_SIZE (8UL*1024*1024+256)
92
#endif
93
#endif /* COAP_DEFAULT_MAX_PDU_RX_SIZE */
94
95
/**
96
 * Indicates that a response is suppressed. This will occur for error
97
 * responses if the request was received via IP multicast.
98
 */
99
0
#define COAP_DROPPED_RESPONSE -2
100
101
0
#define COAP_PDU_DELAYED -3
102
103
91.9M
#define COAP_PAYLOAD_START 0xFF /* payload marker */
104
105
0
#define COAP_PDU_IS_EMPTY(pdu)     ((pdu)->code == 0)
106
0
#define COAP_PDU_IS_REQUEST(pdu)   (!COAP_PDU_IS_EMPTY(pdu) && (pdu)->code < 32)
107
/* Code 1.xx (32-63) and 6.xx (192-224) currently invalid */
108
0
#define COAP_PDU_IS_RESPONSE(pdu)  ((pdu)->code >= 64 && (pdu)->code < 192)
109
37.1M
#define COAP_PDU_IS_SIGNALING(pdu) ((pdu)->code >= 224)
110
0
#define COAP_PDU_IS_PING(pdu)      ((COAP_PDU_IS_EMPTY(pdu) && \
111
0
                                     ((pdu)->type == COAP_MESSAGE_CON)) || \
112
0
                                    ((pdu)->code == COAP_SIGNALING_CODE_PING))
113
114
0
#define COAP_PDU_MAX_UDP_HEADER_SIZE 4
115
10.7k
#define COAP_PDU_MAX_TCP_HEADER_SIZE 6
116
117
/**
118
 * structure for CoAP PDUs
119
 *
120
 * Separate COAP_PDU_BUF is allocated with offsets held in coap_pdu_t.
121
122
 * token, if any, follows the fixed size header, then optional options until
123
 * payload marker (0xff) (if paylooad), then the optional payload.
124
 *
125
 * Memory layout is:
126
 * <---header--->|<---token---><---options--->0xff<---payload--->
127
 *
128
 * header is addressed with a negative offset to token, its maximum size is
129
 * max_hdr_size.
130
 *
131
 * allocated buffer always starts max_hdr_size before token.
132
 *
133
 * options starts at token + e_token_length.
134
 * payload starts at data, its length is used_size - (data - token).
135
 *
136
 * alloc_size, used_size and max_size are the offsets from token.
137
 */
138
139
struct coap_pdu_t {
140
  coap_pdu_type_t type;     /**< message type */
141
  coap_pdu_code_t code;     /**< request method (value 1--31) or response code
142
                                 (value 64-255) */
143
  coap_mid_t mid;           /**< message id, if any, in regular host byte
144
                                 order */
145
  uint8_t max_hdr_size;     /**< space reserved for protocol-specific header */
146
  uint8_t hdr_size;         /**< actual size used for protocol-specific
147
                                 header (0 until header is encoded) */
148
  uint8_t crit_opt;         /**< Set if unknown critical option for proxy */
149
  uint16_t max_opt;         /**< highest option number in PDU */
150
  uint32_t e_token_length;  /**< length of Token space (includes leading
151
                                 extended bytes */
152
  unsigned ref;             /**< reference count */
153
  coap_bin_const_t actual_token; /**< Actual token in pdu */
154
  size_t alloc_size;        /**< allocated storage for token, options and
155
                                 payload */
156
  size_t used_size;         /**< used bytes of storage for token, options and
157
                                 payload */
158
  size_t max_size;          /**< maximum size for token, options and payload,
159
                                 or zero for variable size pdu */
160
  uint8_t *token;           /**< first byte of token (or extended length bytes
161
                                 prefix), if any, or options */
162
  uint8_t *data;            /**< first byte of payload, if any */
163
#ifdef WITH_LWIP
164
  struct pbuf *pbuf;        /**< lwIP PBUF. The package data will always reside
165
                             *   inside the pbuf's payload, but this pointer
166
                             *   has to be kept because no exact offset can be
167
                             *   given. This field must not be accessed from
168
                             *   outside, because the pbuf's reference count
169
                             *   is checked to be 1 when the pbuf is assigned
170
                             *   to the pdu, and the pbuf stays exclusive to
171
                             *   this pdu. */
172
#endif
173
  const uint8_t *body_data; /**< Holds ptr to re-assembled data or NULL. This
174
                                 does not get released by coap_delete_pdu() */
175
  size_t body_length;       /**< Holds body data length */
176
  size_t body_offset;       /**< Holds body data offset */
177
  size_t body_total;        /**< Holds body data total size */
178
  coap_lg_xmit_t *lg_xmit;  /**< Holds ptr to lg_xmit if sending a set of
179
                                 blocks */
180
  coap_session_t *session;  /**< Session responsible for PDU or NULL */
181
  coap_binary_t *data_free; /**< Data to be freed off by coap_delete_pdu() */
182
};
183
184
/**
185
 * Parses @p data into the CoAP PDU structure given in @p result.
186
 * The target pdu must be large enough to hold the token, options and data.
187
 * This function returns @c 0 on error or a number greater than zero on success.
188
 *
189
 * @param proto   Session's protocol
190
 * @param data    The raw data to parse as CoAP PDU.
191
 * @param length  The actual size of @p data.
192
 * @param pdu     The PDU structure to fill. Note that the structure must
193
 *                provide space to hold the token, optional options and
194
 *                optional data.
195
 * @param error_opts Filled in with any options that have an error in the parsing.
196
 *
197
 * @return       1 on success or @c 0 on error.
198
 */
199
int coap_pdu_parse2(coap_proto_t proto,
200
                    const uint8_t *data,
201
                    size_t length,
202
                    coap_pdu_t *pdu,
203
                    coap_opt_filter_t *error_opts);
204
205
/**
206
 * Dynamically grows the size of @p pdu to @p new_size. The new size
207
 * must not exceed the PDU's configure maximum size. On success, this
208
 * function returns 1, otherwise 0.
209
 *
210
 * @param pdu      The PDU to resize.
211
 * @param new_size The new size in bytes.
212
 * @return         1 if the operation succeeded, 0 otherwise.
213
 */
214
int coap_pdu_resize(coap_pdu_t *pdu, size_t new_size);
215
216
/**
217
 * Dynamically grows the size of @p pdu to @p new_size if needed. The new size
218
 * must not exceed the PDU's configured maximum size. On success, this
219
 * function returns 1, otherwise 0.
220
 *
221
 * @param pdu      The PDU to resize.
222
 * @param new_size The new size in bytes.
223
 * @return         1 if the operation succeeded, 0 otherwise.
224
 */
225
int coap_pdu_check_resize(coap_pdu_t *pdu, size_t new_size);
226
227
/**
228
* Interprets @p data to determine the number of bytes in the header.
229
* This function returns @c 0 on error or a number greater than zero on success.
230
*
231
* @param proto  Session's protocol
232
* @param data   The first byte of raw data to parse as CoAP PDU.
233
*
234
* @return       A value greater than zero on success or @c 0 on error.
235
*/
236
size_t coap_pdu_parse_header_size(coap_proto_t proto,
237
                                  const uint8_t *data);
238
239
/**
240
 * Parses @p data to extract the message size.
241
 * @p length must be at least coap_pdu_parse_header_size(proto, data).
242
 * This function returns @c 0 on error or a number greater than zero on success.
243
 *
244
 * @param proto  Session's protocol
245
 * @param data   The raw data to parse as CoAP PDU.
246
 * @param length The actual size of @p data.
247
 *
248
 * @return       PDU size including token on success or @c 0 on error.
249
 */
250
size_t coap_pdu_parse_size(coap_proto_t proto,
251
                           const uint8_t *data,
252
                           size_t length);
253
254
/**
255
 * Decode the protocol specific header for the specified PDU.
256
 * @param pdu A newly received PDU.
257
 * @param proto The target wire protocol.
258
 * @return 1 for success or 0 on error.
259
 */
260
261
int coap_pdu_parse_header(coap_pdu_t *pdu, coap_proto_t proto);
262
263
/**
264
 * Verify consistency in the given CoAP PDU structure and locate the data.
265
 * This function returns @c 0 on error or a number greater than zero on
266
 * success.
267
 * This function only parses the token and options, up to the payload start
268
 * marker.
269
 *
270
 * @param pdu     The PDU structure to check.
271
 * @param error_opts Updated with error option(s) on failure.
272
 *
273
 * @return       1 on success or @c 0 on error.
274
 */
275
int coap_pdu_parse_opt(coap_pdu_t *pdu, coap_opt_filter_t *error_opts);
276
277
/**
278
 * Clears any contents from @p pdu and resets @c used_size,
279
 * and @c data pointers. @c max_size is set to @p size, any
280
 * other field is set to @c 0. Note that @p pdu must be a valid
281
 * pointer to a coap_pdu_t object created e.g. by coap_pdu_init().
282
 *
283
 * @param pdu   The PDU to clear.
284
 * @param size  The maximum size of the PDU.
285
 */
286
void coap_pdu_clear(coap_pdu_t *pdu, size_t size);
287
288
/**
289
 * Adds option of given @p number to @p pdu that is passed as first
290
 * parameter.
291
 *
292
 * The internal version of coap_add_option() may cause an @p option to be
293
 * inserted, even if there is any data in the @p pdu.
294
 *
295
 * Note: Where possible, the option @p data needs to be stripped of leading
296
 * zeros (big endian) to reduce the amount of data needed in the PDU, as well
297
 * as in some cases the maximum data size of an option can be exceeded if not
298
 * stripped and hence be illegal. This is done by using coap_encode_var_safe()
299
 * or coap_encode_var_safe8().
300
 *
301
 * @param pdu    The PDU where the option is to be added.
302
 * @param number The number of the new option.
303
 * @param len    The length of the new option.
304
 * @param data   The data of the new option.
305
 *
306
 * @return The overall length of the option or @c 0 on failure.
307
 */
308
size_t coap_add_option_internal(coap_pdu_t *pdu,
309
                                coap_option_num_t number,
310
                                size_t len,
311
                                const uint8_t *data);
312
/**
313
 * Removes (first) option of given number from the @p pdu.
314
 *
315
 * @param pdu   The PDU to remove the option from.
316
 * @param number The number of the CoAP option to remove (first only removed).
317
 *
318
 * @return @c 1 if success else @c 0 if error.
319
 */
320
int coap_remove_option(coap_pdu_t *pdu, coap_option_num_t number);
321
322
/**
323
 * Inserts option of given number in the @p pdu with the appropriate data.
324
 * The option will be inserted in the appropriate place in the options in
325
 * the pdu.
326
 *
327
 * @param pdu    The PDU where the option is to be inserted.
328
 * @param number The number of the new option.
329
 * @param len    The length of the new option.
330
 * @param data   The data of the new option.
331
 *
332
 * @return The overall length of the option or @c 0 on failure.
333
 */
334
size_t coap_insert_option(coap_pdu_t *pdu, coap_option_num_t number,
335
                          size_t len, const uint8_t *data);
336
337
/**
338
 * Updates existing first option of given number in the @p pdu with the new
339
 * data.
340
 *
341
 * @param pdu    The PDU where the option is to be updated.
342
 * @param number The number of the option to update (first only updated).
343
 * @param len    The length of the updated option.
344
 * @param data   The data of the updated option.
345
 *
346
 * @return The overall length of the updated option or @c 0 on failure.
347
 */
348
size_t coap_update_option(coap_pdu_t *pdu,
349
                          coap_option_num_t number,
350
                          size_t len,
351
                          const uint8_t *data);
352
353
/**
354
 * Compose the protocol specific header for the specified PDU.
355
 *
356
 * @param pdu A newly composed PDU.
357
 * @param proto The target wire protocol.
358
 *
359
 * @return Number of header bytes prepended before pdu->token or 0 on error.
360
 */
361
362
size_t coap_pdu_encode_header(coap_pdu_t *pdu, coap_proto_t proto);
363
364
/**
365
 * Updates token in @p pdu with length @p len and @p data.
366
 * This function returns @c 0 on error or a value greater than zero on success.
367
 *
368
 * @param pdu  The PDU where the token is to be updated.
369
 * @param len  The length of the new token.
370
 * @param data The token to add.
371
 *
372
 * @return     A value greater than zero on success, or @c 0 on error.
373
 */
374
int coap_update_token(coap_pdu_t *pdu,
375
                      size_t len,
376
                      const uint8_t *data);
377
378
/**
379
 * Check whether the option is allowed to be repeated or not.
380
 * This function returns @c 0 if not repeatable or @c 1 if repeatable
381
 *
382
 * @param number The option number to check for repeatability.
383
 *
384
 * @return     @c 0 if not repeatable or @c 1 if repeatable.
385
 */
386
int coap_option_check_repeatable(coap_option_num_t number);
387
388
/**
389
 * Creates a new CoAP PDU.
390
 *
391
 * Note: This function must be called in the locked state.
392
 *
393
 * @param type The type of the PDU (one of COAP_MESSAGE_CON, COAP_MESSAGE_NON,
394
 *             COAP_MESSAGE_ACK, COAP_MESSAGE_RST).
395
 * @param code The message code of the PDU.
396
 * @param session The session that will be using this PDU
397
 *
398
 * @return The skeletal PDU or @c NULL if failure.
399
 */
400
coap_pdu_t *coap_new_pdu_lkd(coap_pdu_type_t type, coap_pdu_code_t code,
401
                             coap_session_t *session);
402
403
/**
404
 * Dispose of an CoAP PDU and free off associated storage.
405
 *
406
 * Note: This function must be called in the locked state.
407
 *
408
 * Note: In general you should not call this function directly.
409
 * When a PDU is sent with coap_send(), coap_delete_pdu() will be called
410
 * automatically for you. This is not for the case for coap_send_recv()
411
 * where the sending and receiving PDUs need to be explicitly deleted.
412
 *
413
 * Note: If called with a reference count > 0, the reference count is
414
 * decremented and the PDU is not deleted.
415
 *
416
 * @param pdu The PDU for free off.
417
 */
418
void coap_delete_pdu_lkd(coap_pdu_t *pdu);
419
420
COAP_STATIC_INLINE void
421
0
coap_pdu_release_lkd(coap_pdu_t *pdu) {
422
0
  coap_delete_pdu_lkd(pdu);
423
0
}
Unexecuted instantiation: coap_debug.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_encode.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_net.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_netif.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_notls.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_option.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_oscore.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_pdu.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_proxy.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_prng.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_resource.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_session.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_sha1.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_str.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_strm_posix.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_subscribe.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_threadsafe.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_time.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_uri.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_ws.c:coap_pdu_release_lkd
Unexecuted instantiation: oscore.c:coap_pdu_release_lkd
Unexecuted instantiation: oscore_cbor.c:coap_pdu_release_lkd
Unexecuted instantiation: oscore_context.c:coap_pdu_release_lkd
Unexecuted instantiation: oscore_cose.c:coap_pdu_release_lkd
Unexecuted instantiation: oscore_crypto.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_address.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_async.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_block.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_cache.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_dgrm_posix.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_dtls.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_hashkey.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_io.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_io_posix.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_layers.c:coap_pdu_release_lkd
Unexecuted instantiation: coap_mem.c:coap_pdu_release_lkd
424
425
/**
426
 * Duplicate an existing PDU. Specific options can be ignored and not copied
427
 * across.  The PDU data payload is not copied across.
428
 *
429
 * Note: This function must be called in the locked state.
430
 *
431
 * @param old_pdu      The PDU to duplicate
432
 * @param session      The session that will be using this PDU.
433
 * @param token_length The length of the token to use in this duplicated PDU.
434
 * @param token        The token to use in this duplicated PDU.
435
 * @param drop_options A list of options not to copy into the duplicated PDU.
436
 *                     If @c NULL, then all options are copied across.
437
 *
438
 * @return The duplicated PDU or @c NULL if failure.
439
 */
440
coap_pdu_t *coap_pdu_duplicate_lkd(const coap_pdu_t *old_pdu,
441
                                   coap_session_t *session,
442
                                   size_t token_length,
443
                                   const uint8_t *token,
444
                                   coap_opt_filter_t *drop_options);
445
446
/**
447
 * Increment reference counter on a pdu to stop it prematurely getting freed off
448
 * when coap_delete_pdu() is called.
449
 *
450
 * In other words, if coap_pdu_reference_lkd() is called once, then the first call
451
 * to coap_delete_pdu() will decrement the reference counter, but not delete the PDU
452
 * and the second call to coap_delete_pdu() then actually deletes the PDU.
453
 *
454
 * Note: This function must be called in the locked state.
455
 *
456
 * @param pdu The CoAP PDU.
457
 * @return same as PDU
458
 */
459
coap_pdu_t *coap_pdu_reference_lkd(coap_pdu_t *pdu);
460
461
/**
462
 * Increment reference counter on a const pdu to stop it prematurely getting freed
463
 * off when coap_delete_pdu() is called.
464
 *
465
 * In other words, if coap_const_pdu_reference_lkd() is called once, then the first
466
 * call to coap_delete_pdu() will decrement the reference counter, but not delete
467
 * the PDU and the second call to coap_delete_pdu() then actually deletes the PDU.
468
 *
469
 * Needed when const coap_pdu_t* is passed from application handlers.
470
 *
471
 * Note: This function must be called in the locked state.
472
 *
473
 * @param pdu The CoAP PDU.
474
 * @return non const version of PDU.
475
 */
476
coap_pdu_t *coap_const_pdu_reference_lkd(const coap_pdu_t *pdu);
477
478
/** @} */
479
480
#ifdef __cplusplus
481
}
482
#endif
483
484
#endif /* COAP_COAP_PDU_INTERNAL_H_ */