Morse Micro IoT SDK  2.9.7
mmpkt.h
1/*
2 * Copyright 2022-2024 Morse Micro
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
15#pragma once
16
17#include <stdbool.h>
18#include <stddef.h>
19#include <stdint.h>
20
21#include "mmosal.h"
22
23#ifdef __cplusplus
24extern "C" {
25#endif
26
27
33#ifndef MM_FAST_ROUND_UP
34#define MM_FAST_ROUND_UP(x, m) ((((x)-1) | ((m)-1)) + 1)
35#endif
36
37struct mmdrv_cmd_metadata;
38struct mmdrv_tx_metadata;
39struct mmdrv_rx_metadata;
40struct mmpkt_ops;
41
50 void *opaque;
52 struct mmdrv_tx_metadata *tx;
54 struct mmdrv_rx_metadata *rx;
56 struct mmdrv_cmd_metadata *cmd;
57};
58
78struct mmpkt
79{
81 uint8_t *buf;
83 uint32_t buf_len;
85 uint32_t start_offset;
87 uint32_t data_len;
91 const struct mmpkt_ops *ops;
93 struct mmpkt *volatile next;
94};
95
98{
100 void (*free_mmpkt)(void *mmpkt);
101};
102
114struct mmpktview;
115
125static inline void mmpkt_init(struct mmpkt *mmpkt, uint8_t *buf, uint32_t buf_len,
126 uint32_t data_start_offset, const struct mmpkt_ops *ops)
127{
128 memset(mmpkt, 0, sizeof(*mmpkt));
129 mmpkt->buf = buf;
130 mmpkt->buf_len = buf_len;
131 mmpkt->start_offset = data_start_offset;
132 mmpkt->ops = ops;
133}
134
152static inline struct mmpkt *mmpkt_init_buf(uint8_t *buf, uint32_t buf_len,
153 uint32_t space_at_start, uint32_t space_at_end,
154 uint32_t metadata_size, const struct mmpkt_ops *ops)
155{
156 struct mmpkt *mmpkt = (struct mmpkt *)buf;
157
158 uint8_t *data_start;
159 uint32_t header_size = MM_FAST_ROUND_UP(sizeof(*mmpkt), 4);
160 uint32_t data_len;
161 metadata_size = MM_FAST_ROUND_UP(metadata_size, 4);
162
163 if (space_at_end != UINT32_MAX)
164 {
165 data_len = MM_FAST_ROUND_UP(space_at_start + space_at_end, 4);
166 }
167 else
168 {
169 /* Special case: if space_at_end is UINT32_MAX then use the entire buffer.
170 * Note that we round down to ensure that the metadata is word aligned. */
171 data_len = (buf_len - header_size - metadata_size) & ~0x03ul;
172 /* Signed comparison in case buf_len was less than (header_size + metadata_size).
173 * Note that we do not expect to allocate an mmpkt with length > INT32_MAX, so we
174 * can safely treat these as signed integers. */
175 if ((int32_t)data_len < (int32_t)space_at_start)
176 {
177 return NULL;
178 }
179 }
180
181 if (header_size + data_len + metadata_size > buf_len)
182 {
183 return NULL;
184 }
185
186 data_start = ((uint8_t *)mmpkt) + header_size;
187
188 mmpkt_init(mmpkt, data_start, data_len, space_at_start, ops);
189
190 if (metadata_size != 0)
191 {
192 mmpkt->metadata.opaque = data_start + data_len;
193 memset(mmpkt->metadata.opaque, 0, metadata_size);
194 }
195
196 return mmpkt;
197}
198
199
212struct mmpkt *mmpkt_alloc_on_heap(uint32_t space_at_start, uint32_t space_at_end,
213 uint32_t metadata_size);
214
222
236static inline struct mmpktview *mmpkt_open(struct mmpkt *mmpkt)
237{
238 return (struct mmpktview *)mmpkt;
239}
240
247static inline void mmpkt_close(struct mmpktview **view)
248{
249 (void)(view);
250}
251
259static inline struct mmpkt *mmpkt_from_view(struct mmpktview *view)
260{
261 return (struct mmpkt *)view;
262}
263
271static inline uint8_t *mmpkt_get_data_start(struct mmpktview *view)
272{
273 struct mmpkt *mmpkt = (struct mmpkt *)view;
274 return mmpkt->buf + mmpkt->start_offset;
275}
276
284static inline uint8_t *mmpkt_get_data_end(struct mmpktview *view)
285{
286 struct mmpkt *mmpkt = (struct mmpkt *)view;
288}
289
298static inline uint32_t mmpkt_peek_data_length(struct mmpkt *mmpkt)
299{
300 return mmpkt->data_len;
301}
302
311static inline uint32_t mmpkt_get_data_length(struct mmpktview *view)
312{
313 struct mmpkt *mmpkt = (struct mmpkt *)view;
314 return mmpkt->data_len;
315}
316
324static inline uint32_t mmpkt_available_space_at_start(struct mmpktview *view)
325{
326 struct mmpkt *mmpkt = (struct mmpkt *)view;
327 return mmpkt->start_offset;
328}
329
337static inline uint32_t mmpkt_available_space_at_end(struct mmpktview *view)
338{
339 struct mmpkt *mmpkt = (struct mmpkt *)view;
341}
342
356static inline uint8_t *mmpkt_prepend(struct mmpktview *view, uint32_t len)
357{
358 struct mmpkt *mmpkt = (struct mmpkt *)view;
360 mmpkt->start_offset -= len;
361 mmpkt->data_len += len;
362 return mmpkt->buf + mmpkt->start_offset;
363}
364
376static inline void mmpkt_prepend_data(struct mmpktview *view, const uint8_t * data, uint32_t len)
377{
378 uint8_t *dest = mmpkt_prepend(view, len);
379 memcpy(dest, data, len);
380}
381
395static inline uint8_t *mmpkt_append(struct mmpktview *view, uint32_t len)
396{
397 struct mmpkt *mmpkt = (struct mmpkt *)view;
398 uint8_t *ret = mmpkt_get_data_end(view);
400 mmpkt->data_len += len;
401 return ret;
402}
403
413static inline void mmpkt_append_data(struct mmpktview *view, const uint8_t *data, uint32_t len)
414{
415 uint8_t *dest = mmpkt_append(view, len);
416 memcpy(dest, data, len);
417}
418
427{
428 return mmpkt->metadata;
429}
430
439static inline void mmpkt_adjust_start_offset(struct mmpkt *mmpkt, int32_t delta)
440{
442 mmpkt->start_offset += delta;
444}
445
454static inline uint8_t *mmpkt_remove_from_start(struct mmpktview *view, uint32_t len)
455{
456 struct mmpkt *mmpkt = (struct mmpkt *)view;
457 uint8_t *ret;
458
459 if (mmpkt_get_data_length(view) < len)
460 {
461 return NULL;
462 }
463
464 ret = mmpkt_get_data_start(view);
465
466 mmpkt->start_offset += len;
467 mmpkt->data_len -= len;
468
469 return ret;
470}
471
480static inline uint8_t *mmpkt_remove_from_end(struct mmpktview *view, uint32_t len)
481{
482 struct mmpkt *mmpkt = (struct mmpkt *)view;
483 uint8_t *ret;
484
485 if (mmpkt_get_data_length(view) < len)
486 {
487 return NULL;
488 }
489
490 ret = mmpkt_get_data_end(view) - len;
491
492 mmpkt->data_len -= len;
493
494 return ret;
495}
496
504static inline void mmpkt_truncate(struct mmpkt *mmpkt, uint32_t len)
505{
506 MMOSAL_ASSERT(len <= mmpkt->data_len);
507 mmpkt->data_len = len;
508}
509
519static inline struct mmpkt *mmpkt_get_next(struct mmpkt *mmpkt)
520{
521 return mmpkt->next;
522}
523
532static inline void mmpkt_set_next(struct mmpkt *mmpkt, struct mmpkt *next)
533{
534 mmpkt->next = next;
535}
536
548static inline bool mmpkt_contains_ptr(struct mmpktview *view, const void *ptr)
549{
550 struct mmpkt *mmpkt = (struct mmpkt *)view;
551 return ((const uint8_t *)ptr >= &mmpkt->buf[0]
552 && (const uint8_t *)ptr < &mmpkt->buf[mmpkt->buf_len]);
553}
554
555#ifdef __cplusplus
556}
557#endif
558
#define MMOSAL_ASSERT(expr)
Assert that the given expression evaluates to true and abort execution if not.
Definition: mmosal.h:927
struct mmpkt * mmpkt_alloc_on_heap(uint32_t space_at_start, uint32_t space_at_end, uint32_t metadata_size)
Allocate a new mmpkt on the heap (using mmosal_malloc()).
static void mmpkt_append_data(struct mmpktview *view, const uint8_t *data, uint32_t len)
Appends the given data to the data already in the mmpkt.
Definition: mmpkt.h:413
static struct mmpkt * mmpkt_init_buf(uint8_t *buf, uint32_t buf_len, uint32_t space_at_start, uint32_t space_at_end, uint32_t metadata_size, const struct mmpkt_ops *ops)
Initialize an mmpkt in a single buffer using the given values.
Definition: mmpkt.h:152
static struct mmpkt * mmpkt_from_view(struct mmpktview *view)
Get the underlying mmpkt from an opened view.
Definition: mmpkt.h:259
static void mmpkt_close(struct mmpktview **view)
Close the given view.
Definition: mmpkt.h:247
void mmpkt_release(struct mmpkt *mmpkt)
Release a reference to the given mmpkt.
static void mmpkt_init(struct mmpkt *mmpkt, uint8_t *buf, uint32_t buf_len, uint32_t data_start_offset, const struct mmpkt_ops *ops)
Initialize an mmpkt header with the given values.
Definition: mmpkt.h:125
static union mmpkt_metadata_ptr mmpkt_get_metadata(struct mmpkt *mmpkt)
Retrieve a reference to the metadata associated with the given mmpkt.
Definition: mmpkt.h:426
static struct mmpkt * mmpkt_get_next(struct mmpkt *mmpkt)
Get the next pointer embedded in the mmpkt.
Definition: mmpkt.h:519
static void mmpkt_adjust_start_offset(struct mmpkt *mmpkt, int32_t delta)
Adjust the start offset of an mmpkt.
Definition: mmpkt.h:439
static uint32_t mmpkt_available_space_at_start(struct mmpktview *view)
Returns the amount of space available for prepending to the data in the buffer.
Definition: mmpkt.h:324
static uint32_t mmpkt_peek_data_length(struct mmpkt *mmpkt)
Peek the length of the data currently from an unopened mmpkt.
Definition: mmpkt.h:298
#define MM_FAST_ROUND_UP(x, m)
Round x up to the next multiple of m (where m is a power of 2).
Definition: mmpkt.h:34
static uint8_t * mmpkt_get_data_end(struct mmpktview *view)
Gets a pointer to the end of the data in the mmpkt.
Definition: mmpkt.h:284
static uint8_t * mmpkt_prepend(struct mmpktview *view, uint32_t len)
Reserves space immediately before the data currently in the given mmpkt and returns a pointer to this...
Definition: mmpkt.h:356
static void mmpkt_truncate(struct mmpkt *mmpkt, uint32_t len)
Truncate the mmpkt data to the given length.
Definition: mmpkt.h:504
static uint32_t mmpkt_get_data_length(struct mmpktview *view)
Gets the length of the data currently in the mmpkt.
Definition: mmpkt.h:311
static uint32_t mmpkt_available_space_at_end(struct mmpktview *view)
Returns the amount of space available for appending to the data in the buffer.
Definition: mmpkt.h:337
static void mmpkt_prepend_data(struct mmpktview *view, const uint8_t *data, uint32_t len)
Prepends the given data to the data already in the mmpkt.
Definition: mmpkt.h:376
static uint8_t * mmpkt_remove_from_end(struct mmpktview *view, uint32_t len)
Remove data from the end of the mmpkt.
Definition: mmpkt.h:480
static struct mmpktview * mmpkt_open(struct mmpkt *mmpkt)
Open a view of the given mmpkt.
Definition: mmpkt.h:236
static uint8_t * mmpkt_append(struct mmpktview *view, uint32_t len)
Reserves space immediately after the data currently in the given mmpkt and returns a pointer to this ...
Definition: mmpkt.h:395
static uint8_t * mmpkt_get_data_start(struct mmpktview *view)
Gets a pointer to the start of the data in the mmpkt.
Definition: mmpkt.h:271
static bool mmpkt_contains_ptr(struct mmpktview *view, const void *ptr)
Check whether the given pointer is pointing inside the mmpkt's buffer.
Definition: mmpkt.h:548
static uint8_t * mmpkt_remove_from_start(struct mmpktview *view, uint32_t len)
Remove data from the start of the mmpkt.
Definition: mmpkt.h:454
static void mmpkt_set_next(struct mmpkt *mmpkt, struct mmpkt *next)
Set the next pointer embedded in the mmpkt.
Definition: mmpkt.h:532
char buf[1408]
Statically allocated buffer for HTTP GET request, just under 1 packet size.
Definition: sslclient.c:177
Operations data structure for mmpkt.
Definition: mmpkt.h:98
void(* free_mmpkt)(void *mmpkt)
Free the given mmpkt.
Definition: mmpkt.h:100
Core mmpkt data structure.
Definition: mmpkt.h:79
uint32_t buf_len
Length of the buffer.
Definition: mmpkt.h:83
uint32_t data_len
Length of actual data in the buffer.
Definition: mmpkt.h:87
uint32_t start_offset
Offset where actual data starts in the buffer.
Definition: mmpkt.h:85
const struct mmpkt_ops * ops
Reference to operations data structure for this mmpkt.
Definition: mmpkt.h:91
uint8_t * buf
The buffer where data is stored.
Definition: mmpkt.h:81
union mmpkt_metadata_ptr metadata
Packet metadata used by driver (context dependent).
Definition: mmpkt.h:89
struct mmpkt *volatile next
Pointer that can be used to construct linked lists.
Definition: mmpkt.h:93
Union of pointer types for mmpkt metadata.
Definition: mmpkt.h:48
struct mmdrv_rx_metadata * rx
Metadata for a packet which is being received.
Definition: mmpkt.h:54
struct mmdrv_tx_metadata * tx
Metadata for a packet which is being transmitted.
Definition: mmpkt.h:52
void * opaque
Opaque pointer for contexts which are unaware of the specific metadata structure.
Definition: mmpkt.h:50
struct mmdrv_cmd_metadata * cmd
Control block for a command response sent to the host.
Definition: mmpkt.h:56