ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_app_cover.c
Go to the documentation of this file.
1
10#include <limits.h>
11#include <stdint.h>
12#include <string.h>
13
14#include "mdl_app_internal.h"
16
34RA8_INTERNAL static bool internal_cover_copy(char* destination, size_t capacity, const char* source)
35{
36 if ((destination == nullptr) || (capacity == 0U) || (source == nullptr)) {
37 return false;
38 }
39 const size_t length = strlen(source);
40 if (length >= capacity) {
41 destination[0] = '\0';
42 return false;
43 }
44 memcpy(destination, source, length + 1U);
45 return true;
46}
47
64RA8_INTERNAL static bool internal_cover_current(mdl_fetch_ctx_t* ctx, const char* series_directory)
65{
66 const char* relative = priv_mdl_app_context()->state.cover_path;
67 if (relative[0] == '\0') {
68 return false;
69 }
70 char existing[k_fw_fs_path_cap];
71 return mdl_path_join(series_directory, relative, existing, sizeof(existing)) &&
72 (mdl_urlname_sniff_file(ctx->storage, existing, nullptr, nullptr, 0U, nullptr, 0U) ==
73 k_ra8_ok);
74}
75
94{
96 if (error != k_ra8_ok) {
97 (void)priv_mdl_fetch_body_abort(body);
99 priv_mdl_app_context()->diagnostic,
100 "mdl: downloaded series cover is not a "
101 "supported image (");
102 output_error = priv_mdl_stream_u64(output_error, priv_mdl_app_context()->diagnostic, bytes);
103 output_error =
104 priv_mdl_stream_text(output_error, priv_mdl_app_context()->diagnostic, " bytes)\n");
105 return (output_error == k_ra8_ok) ? error : output_error;
106 }
107 if (!internal_cover_copy(priv_mdl_app_context()->state.cover_path,
108 sizeof(priv_mdl_app_context()->state.cover_path),
109 body->actual_rel)) {
110 (void)priv_mdl_fetch_body_abort(body);
112 }
113 error = priv_mdl_fetch_body_commit(body);
114 if (error != k_ra8_ok) {
116 }
117 return error;
118}
119
139internal_cover_publish_cached(mdl_fetch_ctx_t* ctx, const char* holding, size_t bytes)
140{
141 if (bytes > UINT32_MAX) {
143 }
144 mdl_fetch_body_t body = {};
145 ra8_err_t error = priv_mdl_fetch_body_init_image(&body, ctx->storage, holding, "cover.download");
147 uint32_t accepted = 0U;
148 if (error == k_ra8_ok) {
149 error = sink.write(sink.ctx, (const uint8_t*)ctx->page_buf, (uint32_t)bytes, &accepted);
150 }
151 if ((error == k_ra8_ok) && (accepted != (uint32_t)bytes)) {
153 }
154 if (error != k_ra8_ok) {
155 const ra8_err_t aborted = priv_mdl_fetch_body_abort(&body);
156 return (aborted == k_ra8_ok) ? error : aborted;
157 }
158 return internal_cover_finish(&body, bytes);
159}
160
181 const char* holding,
182 const char* host,
183 uint32_t minimum_delay,
184 uint32_t maximum_delay)
185{
186 const mdl_net_req_t request = {.user_agent = ctx->session->user_agent,
188 .timeout_ms = ctx->timeout_ms};
189 mdl_fetch_body_t body = {};
190 ra8_err_t error = priv_mdl_fetch_body_init_image(&body, ctx->storage, holding, "cover.download");
192 mdl_net_resp_t response = {};
193 size_t bytes = 0U;
194 if (error == k_ra8_ok) {
195 error = priv_mdl_fetch_with_retry(ctx,
196 host,
197 priv_mdl_app_context()->state.cover_url,
198 &request,
199 &sink,
200 minimum_delay,
201 maximum_delay,
202 &response,
203 &bytes);
204 }
205 if (error == k_ra8_ok) {
206 return internal_cover_finish(&body, bytes);
207 }
208 const ra8_err_t aborted = priv_mdl_fetch_body_abort(&body);
209 error = (aborted == k_ra8_ok) ? error : aborted;
210 priv_mdl_fetch_record_fail(ctx, priv_mdl_app_context()->state.cover_url, response.status, error);
211 return error;
212}
213
235 const char* holding,
236 const char* host,
237 uint32_t minimum_delay,
238 uint32_t maximum_delay,
239 bool current)
240{
241 mdl_fetch_cache_request_t fetch = {.ctx = ctx, .jmin = minimum_delay, .jmax = maximum_delay};
242 if (!internal_cover_copy(fetch.host, sizeof(fetch.host), host)) {
244 }
245 const mdl_net_req_t request = {.user_agent = ctx->session->user_agent,
247 .timeout_ms = ctx->timeout_ms};
248 mdl_net_resp_t response = {};
249 mdl_cache_result_t result;
250 size_t bytes = 0U;
251 ra8_err_t error = mdl_cache_get_buf(ctx->cache,
252 priv_mdl_app_context()->state.cover_url,
253 &request,
255 &fetch,
256 ctx->page_buf,
257 ctx->page_cap,
258 &bytes,
259 &response,
260 &result);
261 if (error == k_ra8_ok) {
262 error = priv_mdl_app_report_cache(priv_mdl_app_context()->state.cover_url, &result);
263 }
264 if ((error == k_ra8_ok) && current && result.body_reused) {
265 return k_ra8_ok;
266 }
267 if (error == k_ra8_ok) {
268 return internal_cover_publish_cached(ctx, holding, bytes);
269 }
270 priv_mdl_fetch_record_fail(ctx, priv_mdl_app_context()->state.cover_url, response.status, error);
271 return error;
272}
273
275 const char* series_directory)
276{
277 if ((ctx == nullptr) || (series_directory == nullptr)) {
279 }
280 if (priv_mdl_app_context()->state.cover_url[0] == '\0') {
281 return k_ra8_ok;
282 }
283 const bool current = internal_cover_current(ctx, series_directory);
284 if (current && (ctx->cache == nullptr) && !ctx->refetch) {
285 return k_ra8_ok;
286 }
287 char holding[k_fw_fs_path_cap];
288 if (!mdl_path_join(series_directory, "cover.download", holding, sizeof(holding))) {
290 }
291 uint32_t crawl = 0U;
292 if (!mdl_session_url_allowed(ctx->session, priv_mdl_app_context()->state.cover_url, &crawl)) {
294 }
295 char host[k_mdl_gov_host_max];
296 if (!mdl_url_host(priv_mdl_app_context()->state.cover_url, host, sizeof(host))) {
298 }
299 const uint32_t minimum_delay =
300 (ctx->site->img_delay_min > crawl) ? ctx->site->img_delay_min : crawl;
301 const uint32_t maximum_delay =
302 (ctx->site->img_delay_max > crawl) ? ctx->site->img_delay_max : crawl;
303 return (ctx->cache != nullptr)
304 ? internal_cover_cached(ctx, holding, host, minimum_delay, maximum_delay, current)
305 : internal_cover_stream(ctx, holding, host, minimum_delay, maximum_delay);
306}
@ k_fw_fs_path_cap
Largest portable path including its NUL.
mdl_app_context_t * priv_mdl_app_context(void)
The working set the composition root bound with mdl_app_bind.
Definition mdl_app.c:33
static bool internal_cover_copy(char *destination, size_t capacity, const char *source)
Copy one complete cover metadata string.
static ra8_err_t internal_cover_cached(mdl_fetch_ctx_t *ctx, const char *holding, const char *host, uint32_t minimum_delay, uint32_t maximum_delay, bool current)
Fetch or revalidate one cover through the persistent host cache.
static ra8_err_t internal_cover_finish(mdl_fetch_body_t *body, size_t bytes)
Validate, name, and publish one complete cover body transaction.
static ra8_err_t internal_cover_publish_cached(mdl_fetch_ctx_t *ctx, const char *holding, size_t bytes)
Feed one cached cover buffer into the validated image transaction.
static ra8_err_t internal_cover_stream(mdl_fetch_ctx_t *ctx, const char *holding, const char *host, uint32_t minimum_delay, uint32_t maximum_delay)
Fetch one cover directly into a private image transaction.
static bool internal_cover_current(mdl_fetch_ctx_t *ctx, const char *series_directory)
Determine whether the recorded local cover still has image magic.
ra8_err_t priv_mdl_app_ensure_series_cover(mdl_fetch_ctx_t *ctx, const char *series_directory)
Ensure series state names one verified cached or freshly fetched cover.
Module-private contract shared by the application-mode translation units.
ra8_err_t priv_mdl_app_report_cache(const char *url, const mdl_cache_result_t *result)
Report corruption recovery or verified cache reuse with staleness.
ra8_err_t mdl_cache_get_buf(mdl_cache_t *cache, const char *url, const mdl_net_req_t *base_request, mdl_cache_fetch_fn fetch, void *fetch_context, char *buffer, size_t capacity, size_t *out_length, mdl_net_resp_t *response, mdl_cache_result_t *result)
Fetch one document through the per-host persistent cache.
Definition mdl_cache.c:537
ra8_err_t priv_mdl_fetch_with_retry(mdl_fetch_ctx_t *ctx, const char *host, const char *url, const mdl_net_req_t *req, mdl_net_body_sink_t *sink, uint32_t jmin, uint32_t jmax, mdl_net_resp_t *out_resp, size_t *out_bytes)
Bounded, governed retry of one image transfer; last status latched.
Definition mdl_fetch.c:264
void priv_mdl_fetch_record_fail(const mdl_fetch_ctx_t *ctx, const char *url, long status, ra8_err_t err)
Append one failure to the run's log (when set); always tally total.
Definition mdl_fetch.c:175
ra8_err_t priv_mdl_fetch_cache_get_buf(void *context, const char *url, const mdl_net_req_t *request, char *buffer, size_t capacity, size_t *out_length, mdl_net_resp_t *response)
Fetch one cache attempt through governor and bounded retry policy.
Definition mdl_fetch.c:421
ra8_err_t priv_mdl_fetch_body_commit(mdl_fetch_body_t *body)
Validate exact size/hash and publish one prepared body.
mdl_net_body_sink_t priv_mdl_fetch_body_sink(mdl_fetch_body_t *body)
Return the network sink view of one body state.
ra8_err_t priv_mdl_fetch_body_prepare(mdl_fetch_body_t *body)
Finish prefix classification and make a nonempty stage commit-ready.
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.
ra8_err_t priv_mdl_fetch_body_abort(mdl_fetch_body_t *body)
Abort any private stage owned by a body sink.
Portable single-transaction response-body sink for media fetches.
struct mdl_fetch_cache_request mdl_fetch_cache_request_t
Caller-owned governor parameters for one cached buffer fetch.
@ k_mdl_gov_host_max
Host-key buffer bytes (matches config).
bool mdl_path_join(const char *parent, const char *seg, char *out, size_t cap)
Join one safe child segment under a parent directory path.
bool mdl_session_url_allowed(mdl_session_t *session, const char *url, uint32_t *crawl_delay_ms)
Decide whether url may be fetched under robots.txt, and its delay.
ra8_err_t priv_mdl_stream_text(ra8_err_t prior, ra8_io_stream_t *stream, const char *text)
Append text unless an earlier operation already failed.
Definition mdl_stream.c:16
ra8_err_t priv_mdl_stream_u64(ra8_err_t prior, ra8_io_stream_t *stream, uint64_t value)
Append one unsigned integer unless an earlier append failed.
Definition mdl_stream.c:21
bool mdl_url_host(const char *url, char *out, size_t cap)
Extract the authority (host and optional port) from an http(s) URL.
ra8_err_t mdl_urlname_sniff_file(mdl_storage_t *storage, const char *file_path, 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 portable storage.
#define RA8_PRIV
Module-private helper: shared across TUs but only inside one library.
#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_invalid_state
Module in wrong state for requested operation.
Definition ra8_err.h:161
@ k_ra8_ok
Success – operation completed with all postconditions satisfied.
Definition ra8_err.h:119
@ k_ra8_err_access_denied
Operation refused because the target is protected against it.
Definition ra8_err.h:276
@ 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
size_t strlen(const char *s)
Calculate string length.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
mdl_state_t state
Persistent tracked state.
Definition mdl_app.h:172
Observable outcome of one cache lookup.
Definition mdl_cache.h:105
bool body_reused
Returned bytes came from verified storage.
Definition mdl_cache.h:108
Caller-owned state for one retryable streamed fetch.
char actual_rel[k_mdl_relpath_max]
Magic-derived relative path.
char host[k_mdl_gov_host_max]
Governor host key.
Everything mdl_fetch_run needs, injected for testability.
Definition mdl_fetch.h:164
const mdl_site_t * site
Selectors + politeness bounds.
Definition mdl_fetch.h:172
mdl_storage_t * storage
Portable storage binding + workspaces.
Definition mdl_fetch.h:166
char * page_buf
Chapter-HTML scratch (caller-owned).
Definition mdl_fetch.h:175
mdl_cache_t * cache
Per-host HTML cache binding.
Definition mdl_fetch.h:168
bool refetch
Ignore local page reuse and hit network.
Definition mdl_fetch.h:179
mdl_session_t * session
Identity + robots + net backend.
Definition mdl_fetch.h:165
size_t page_cap
Capacity of page_buf.
Definition mdl_fetch.h:176
uint32_t timeout_ms
Per-request time budget.
Definition mdl_fetch.h:174
Caller-owned lifecycle and write seam for one response body.
Definition mdl_net.h:162
mdl_net_body_write_fn write
Consume one response chunk.
Definition mdl_net.h:164
void * ctx
Caller-owned callback state.
Definition mdl_net.h:165
Per-request session parameters.
Definition mdl_net.h:43
Per-transfer response metadata surfaced to the politeness governor.
Definition mdl_net.h:120
long status
Finished transfer's HTTP status, 0 if none.
Definition mdl_net.h:121
const char * user_agent
Full UA header (caller-owned).
Definition mdl_session.h:41
uint32_t img_delay_max
Per-image spacing ceiling.
Definition mdl_config.h:88
uint32_t img_delay_min
Per-image spacing floor.
Definition mdl_config.h:87
char cover_path[k_mdl_relpath_max]
Local cover path.
Definition mdl_state.h:186
char series_url[k_mdl_url_max]
Series page URL.
Definition mdl_state.h:177