ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_fetch_body.c
Go to the documentation of this file.
1
9#include <stdio.h>
10#include <string.h>
11
13#include "mdl_urlname.h"
14
30RA8_INTERNAL static bool internal_body_paths(mdl_fetch_body_t* body, const char* extension)
31{
32 const char* abs_dot = strrchr(body->target_abs, '.');
33 const char* rel_dot = strrchr(body->target_rel, '.');
34 if ((abs_dot == nullptr) || (rel_dot == nullptr) || (extension[0] == '\0')) {
35 return false;
36 }
37 const int abs_length = snprintf(body->actual_abs,
38 sizeof(body->actual_abs),
39 "%.*s.%s",
40 (int)(abs_dot - body->target_abs),
41 body->target_abs,
42 extension);
43 const int rel_length = snprintf(body->actual_rel,
44 sizeof(body->actual_rel),
45 "%.*s.%s",
46 (int)(rel_dot - body->target_rel),
47 body->target_rel,
48 extension);
49 return (abs_length > 0) && ((size_t)abs_length < sizeof(body->actual_abs)) && (rel_length > 0) &&
50 ((size_t)rel_length < sizeof(body->actual_rel));
51}
52
69{
70 if (body->writer.transaction.active) {
71 return k_ra8_ok;
72 }
73 if (body->mode == k_mdl_fetch_body_exact) {
74 const int copied = snprintf(body->actual_abs, sizeof(body->actual_abs), "%s", body->target_abs);
75 if ((copied < 0) || ((size_t)copied >= sizeof(body->actual_abs))) {
77 }
78 } else {
79 char extension[8] = {};
81 body->prefix_bytes,
82 nullptr,
83 extension,
84 sizeof(extension),
85 nullptr,
86 0U)) {
88 }
89 if (!internal_body_paths(body, extension)) {
91 }
92 }
93 return mdl_storage_txn_begin(&body->writer, body->storage, body->actual_abs);
94}
95
111{
112 ra8_err_t error = internal_body_begin(body);
113 if ((error == k_ra8_ok) && (body->prefix_bytes != 0U)) {
114 error = mdl_storage_txn_write(&body->writer, body->prefix, body->prefix_bytes);
115 if (error == k_ra8_ok) {
116 body->prefix_bytes = 0U;
117 }
118 }
119 return error;
120}
121
137{
138 mdl_fetch_body_t* body = (mdl_fetch_body_t*)context;
139 if (body == nullptr) {
141 }
142 const ra8_err_t error = mdl_storage_txn_abort(&body->writer);
143 if (error != k_ra8_ok) {
144 return error;
145 }
146 body->prefix_bytes = 0U;
147 body->received = 0U;
148 body->actual_abs[0] = '\0';
149 body->actual_rel[0] = '\0';
150 return k_ra8_ok;
151}
152
168RA8_INTERNAL static uint32_t
169internal_body_buffer_prefix(mdl_fetch_body_t* body, const uint8_t* bytes, uint32_t length)
170{
171 const uint32_t room = (uint32_t)k_mdl_fetch_magic_bytes - (uint32_t)body->prefix_bytes;
172 const uint32_t take = (length < room) ? length : room;
173 memcpy(body->prefix + body->prefix_bytes, bytes, take);
174 body->prefix_bytes = (uint8_t)((uint32_t)body->prefix_bytes + take);
175 return take;
176}
177
197internal_body_write(void* context, const uint8_t* bytes, uint32_t length, uint32_t* out_written)
198{
199 mdl_fetch_body_t* body = (mdl_fetch_body_t*)context;
200 if ((body == nullptr) || (out_written == nullptr) || ((bytes == nullptr) && (length != 0U))) {
202 }
203 *out_written = 0U;
204 if (length == 0U) {
205 return k_ra8_ok;
206 }
207 uint32_t offset = 0U;
208 if ((body->mode == k_mdl_fetch_body_image) && !body->writer.transaction.active) {
209 offset = internal_body_buffer_prefix(body, bytes, length);
210 if (body->prefix_bytes < (uint8_t)k_mdl_fetch_magic_bytes) {
211 body->received += (uint64_t)length;
212 *out_written = length;
213 return k_ra8_ok;
214 }
215 const ra8_err_t error = internal_body_flush_prefix(body);
216 if (error != k_ra8_ok) {
217 return error;
218 }
219 } else if (!body->writer.transaction.active) {
220 const ra8_err_t error = internal_body_begin(body);
221 if (error != k_ra8_ok) {
222 return error;
223 }
224 }
225 const ra8_err_t error = mdl_storage_txn_write(&body->writer, bytes + offset, length - offset);
226 if (error == k_ra8_ok) {
227 body->received += (uint64_t)length;
228 *out_written = length;
229 }
230 return error;
231}
232
234 mdl_storage_t* storage,
235 const char* target_abs)
236{
237 if ((body == nullptr) || (storage == nullptr) || (target_abs == nullptr) ||
238 (target_abs[0] != '/')) {
240 }
241 *body = (mdl_fetch_body_t){.storage = storage,
242 .target_abs = target_abs,
243 .target_rel = nullptr,
244 .mode = k_mdl_fetch_body_exact};
245 return k_ra8_ok;
246}
247
249 mdl_storage_t* storage,
250 const char* target_abs,
251 const char* target_rel)
252{
253 if ((body == nullptr) || (storage == nullptr) || (target_abs == nullptr) ||
254 (target_rel == nullptr) || (target_abs[0] != '/')) {
256 }
257 *body = (mdl_fetch_body_t){.storage = storage,
258 .target_abs = target_abs,
259 .target_rel = target_rel,
260 .mode = k_mdl_fetch_body_image};
261 return k_ra8_ok;
262}
263
269
271{
272 if ((body == nullptr) || (body->storage == nullptr)) {
274 }
275 if (body->received == 0U) {
277 }
278 if (!body->writer.transaction.active) {
279 return internal_body_flush_prefix(body);
280 }
281 return k_ra8_ok;
282}
283
285{
286 if ((body == nullptr) || !body->writer.transaction.active) {
288 }
289 return mdl_storage_txn_commit(&body->writer);
290}
291
293{
294 if (body == nullptr) {
296 }
297 const ra8_err_t error = mdl_storage_txn_abort(&body->writer);
298 if (error == k_ra8_ok) {
299 body->prefix_bytes = 0U;
300 body->received = 0U;
301 }
302 return error;
303}
ra8_err_t priv_mdl_fetch_body_commit(mdl_fetch_body_t *body)
Validate exact size/hash and publish one prepared body.
ra8_err_t priv_mdl_fetch_body_init_exact(mdl_fetch_body_t *body, mdl_storage_t *storage, const char *target_abs)
Initialize an exact-path transactional body sink.
static ra8_err_t internal_body_write(void *context, const uint8_t *bytes, uint32_t length, uint32_t *out_written)
Consume one exact or magic-typed network body chunk.
mdl_net_body_sink_t priv_mdl_fetch_body_sink(mdl_fetch_body_t *body)
Return the network sink view of one body state.
static bool internal_body_paths(mdl_fetch_body_t *body, const char *extension)
Replace both requested suffixes with one verified image suffix.
ra8_err_t priv_mdl_fetch_body_prepare(mdl_fetch_body_t *body)
Finish prefix classification and make a nonempty stage commit-ready.
static ra8_err_t internal_body_flush_prefix(mdl_fetch_body_t *body)
Flush retained signature bytes into a newly active stage.
ra8_err_t priv_mdl_fetch_body_init_image(mdl_fetch_body_t *body, mdl_storage_t *storage, const char *target_abs, const char *target_rel)
Initialize a magic-typed image body sink.
static ra8_err_t internal_body_reset(void *context)
Abort a prior retry attempt without beginning a new one.
static ra8_err_t internal_body_begin(mdl_fetch_body_t *body)
Begin the exact or classified destination transaction once.
ra8_err_t priv_mdl_fetch_body_abort(mdl_fetch_body_t *body)
Abort any private stage owned by a body sink.
static uint32_t internal_body_buffer_prefix(mdl_fetch_body_t *body, const uint8_t *bytes, uint32_t length)
Retain the bounded image prefix and return consumed source bytes.
Portable single-transaction response-body sink for media fetches.
@ k_mdl_fetch_magic_bytes
Largest supported image signature prefix.
@ k_mdl_fetch_body_image
Derive the suffix from image magic.
@ k_mdl_fetch_body_exact
Publish under the supplied exact path.
ra8_err_t mdl_storage_txn_write(mdl_storage_txn_t *writer, const uint8_t *bytes, uint32_t length)
Append one complete caller chunk, tolerating bounded short writes.
ra8_err_t mdl_storage_txn_abort(mdl_storage_txn_t *writer)
Abort and clear one streamed transaction.
ra8_err_t mdl_storage_txn_commit(mdl_storage_txn_t *writer)
Independently validate and publish a completed streamed transaction.
ra8_err_t mdl_storage_txn_begin(mdl_storage_txn_t *writer, mdl_storage_t *storage, const char *destination)
Begin one streamed create or truthful atomic replacement.
Bounded URL naming and portable image-classification helpers.
bool mdl_urlname_sniff_image_type(const void *buf, size_t buf_len, const char *content_type, char *out_ext, size_t ext_cap, char *out_mime, size_t mime_cap)
Sniff true image extension and MIME type from magic bytes and/or HTTP Content-Type.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_invalid_arg
Invalid function argument.
Definition ra8_err.h:152
@ k_ra8_err_validation_failed
Validation rule failed (caller-supplied invariant not satisfied).
Definition ra8_err.h:459
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_invalid_size
Invalid size parameter (too large, too small, or misaligned).
Definition ra8_err.h:167
ra8_err_codes_t ra8_err_t
Canonical error-return type used by every ra8-firmware API.
Definition ra8_err.h:546
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
char * strrchr(const char *s, int c)
Locate last occurrence of character in string.
bool active
Begin succeeded.
Caller-owned state for one retryable streamed fetch.
mdl_storage_t * storage
Exclusive storage binding.
uint8_t prefix_bytes
Bytes retained in prefix.
const char * target_rel
Requested relative path or NULL.
mdl_storage_txn_t writer
Single private output stage.
uint64_t received
Network bytes accepted.
char actual_rel[k_mdl_relpath_max]
Magic-derived relative path.
mdl_fetch_body_mode_t mode
Exact or magic-typed publication.
uint8_t prefix[k_mdl_fetch_magic_bytes]
Deferred signature bytes.
char actual_abs[PATH_MAX]
Magic-derived final path.
const char * target_abs
Requested absolute destination.
Caller-owned lifecycle and write seam for one response body.
Definition mdl_net.h:162
One non-reentrant downloader filesystem dependency bundle.
Definition mdl_storage.h:40
fw_fs_transaction_t transaction
Active private filesystem stage.
Definition mdl_storage.h:60