ra8-firmware 0.1.0
Bare-metal firmware for the Renesas RA8 family (RA8D2 / RA8P1)
Loading...
Searching...
No Matches
mdl_service.c
Go to the documentation of this file.
1
17
18#include <stddef.h>
19#include <stdint.h>
20#include <string.h>
21
23#include "ra8_attributes.h"
24#include "ra8_c6link_mdl_msg.h"
25#include "ra8_mdl_service.h"
26
28typedef enum : uint16_t {
33
57
60static bool s_initialised;
61
73typedef uint32_t (*mdl_component_abi_fn_t)(void);
74
75[[gnu::noinline]] uint32_t ra8_mdl_service_component_abi(void)
76{
77 return 1U;
78}
79
80/* The volatile indirection is intentional: it keeps a relocation to the ABI
81 * marker through optimization and --gc-sections, making the post-link symbol
82 * assertion meaningful in release images. */
84
99{
100 if (state->http != nullptr) {
101 (void)esp_http_client_close( // alloc-allow: ESP-IDF SOUP releases transport state
102 state->http);
103 }
104 state->url[0] = '\0';
105 state->user_agent[0] = '\0';
106 state->referer[0] = '\0';
107 state->if_none_match[0] = '\0';
108 state->if_modified_since[0] = '\0';
110 state->header_error = k_ra8_ok;
111 state->total = 0U;
112 state->received = 0U;
114 state->total_known = false;
115 state->opened = false;
116 state->hashing = false;
117}
118
136RA8_INTERNAL static bool internal_mdl_header_equal(const char* lhs, const char* rhs)
137{
138 if (lhs == nullptr) {
139 return false;
140 }
141 size_t index = 0U;
142 while ((lhs[index] != '\0') && (rhs[index] != '\0')) {
143 unsigned char left = (unsigned char)lhs[index];
144 unsigned char right = (unsigned char)rhs[index];
145 if ((left >= (unsigned char)'A') && (left <= (unsigned char)'Z')) {
146 left = (unsigned char)(left + ((unsigned char)'a' - (unsigned char)'A'));
147 }
148 if ((right >= (unsigned char)'A') && (right <= (unsigned char)'Z')) {
149 right = (unsigned char)(right + ((unsigned char)'a' - (unsigned char)'A'));
150 }
151 if (left != right) {
152 return false;
153 }
154 index++;
155 }
156 return (lhs[index] == '\0') && (rhs[index] == '\0');
157}
158
178internal_mdl_copy_field(char* destination, size_t capacity, const char* source)
179{
180 destination[0] = '\0';
181 if ((source == nullptr) || (source[0] == '\0')) {
182 return k_ra8_ok;
183 }
184 const size_t length = strnlen(source, capacity);
185 if (length >= capacity) {
187 }
188 for (size_t i = 0U; i < length; ++i) {
189 if ((source[i] == '\r') || (source[i] == '\n')) {
191 }
192 }
193 memcpy(destination, source, length + 1U);
194 return k_ra8_ok;
195}
196
213 const char* key,
214 char** destination,
215 size_t* capacity)
216{
217 *destination = nullptr;
218 *capacity = 0U;
219 if (internal_mdl_header_equal(key, "Retry-After")) {
220 *destination = state->response.retry_after;
221 *capacity = sizeof(state->response.retry_after);
222 } else if (internal_mdl_header_equal(key, "ETag")) {
223 *destination = state->response.etag;
224 *capacity = sizeof(state->response.etag);
225 } else if (internal_mdl_header_equal(key, "Last-Modified")) {
226 *destination = state->response.last_modified;
227 *capacity = sizeof(state->response.last_modified);
228 } else if (internal_mdl_header_equal(key, "Content-Type")) {
229 *destination = state->response.content_type;
230 *capacity = sizeof(state->response.content_type);
231 } else {
232 /* Unselected header: destination stays null and capacity stays zero. */
233 }
234}
235
252{
253 if ((event == nullptr) || (event->user_data == nullptr)) {
254 return ESP_FAIL;
255 }
256 if (event->event_id != HTTP_EVENT_ON_HEADER) {
257 return ESP_OK;
258 }
260 char* destination;
261 size_t capacity;
262 internal_mdl_select_response_header(state, event->header_key, &destination, &capacity);
263 if (destination == nullptr) {
264 return ESP_OK;
265 }
266 const ra8_err_t copied = internal_mdl_copy_field(destination, capacity, event->header_value);
267 if (copied != k_ra8_ok) {
268 state->header_error = copied;
269 return ESP_FAIL;
270 }
271 return ESP_OK;
272}
273
291{
292 const esp_http_client_config_t cfg = {
293 .url = "https://127.0.0.1/",
294 .timeout_ms = k_mdl_http_timeout_ms,
295 .buffer_size = k_ra8_mdl_chunk_data_max,
296 .crt_bundle_attach = esp_crt_bundle_attach,
297 .disable_auto_redirect = true,
298 .event_handler = internal_mdl_http_event,
299 .user_data = state,
300 };
301 state->http =
302 esp_http_client_init(&cfg); /* alloc-allow: ESP-IDF SOUP creates one retained HTTP client */
303 if (state->http == nullptr) {
304 return k_ra8_err_no_mem;
305 }
306 mbedtls_sha256_init(&state->sha);
307 return k_ra8_ok;
308}
309
328internal_mdl_http_set_header(mdl_http_state_t* state, const char* name, const char* value)
329{
330 (void)esp_http_client_delete_header(state->http, name);
331 if (value[0] == '\0') {
332 return k_ra8_ok;
333 }
334 return (esp_http_client_set_header(state->http, name, value) == ESP_OK) ? k_ra8_ok : k_ra8_fail;
335}
336
356 const ra8_mdl_request_t* request)
357{
358 ra8_err_t result = internal_mdl_copy_field(state->url, sizeof(state->url), request->url);
359 if (result == k_ra8_ok) {
360 result = internal_mdl_copy_field(state->user_agent,
361 sizeof(state->user_agent),
362 request->http.user_agent);
363 }
364 if (result == k_ra8_ok) {
365 result = internal_mdl_copy_field(state->referer, sizeof(state->referer), request->http.referer);
366 }
367 if (result == k_ra8_ok) {
369 sizeof(state->if_none_match),
370 request->http.if_none_match);
371 }
372 if (result == k_ra8_ok) {
374 sizeof(state->if_modified_since),
375 request->http.if_modified_since);
376 }
377 if (result != k_ra8_ok) {
378 return result;
379 }
380 const uint32_t timeout =
381 (request->http.timeout_ms == 0U) ? k_mdl_http_timeout_ms : request->http.timeout_ms;
382 if (esp_http_client_set_timeout_ms(state->http, (int)timeout) != ESP_OK) {
383 result = k_ra8_fail;
384 }
385 if (result == k_ra8_ok) {
386 result = internal_mdl_http_set_header(state, "User-Agent", state->user_agent);
387 }
388 if (result == k_ra8_ok) {
389 result = internal_mdl_http_set_header(state, "Referer", state->referer);
390 }
391 if (result == k_ra8_ok) {
392 result = internal_mdl_http_set_header(state, "If-None-Match", state->if_none_match);
393 }
394 if (result == k_ra8_ok) {
395 result = internal_mdl_http_set_header(state, "If-Modified-Since", state->if_modified_since);
396 }
397 return result;
398}
399
419{
420 mdl_http_state_t* state = (mdl_http_state_t*)ctx;
421 const size_t https_prefix_len = sizeof("https://") - 1U;
422 if ((uint32_t)request->format > (uint32_t)k_mdl_format_rabook) {
424 }
425 if (strncmp(request->url, "https://", https_prefix_len) != 0) {
427 }
428 if (request->url[https_prefix_len] == '\0') {
430 }
432 const ra8_err_t applied = internal_mdl_http_apply_request(state, request);
433 if (applied != k_ra8_ok) {
435 return applied;
436 }
437 state->format = request->format;
438 const esp_err_t url_status =
439 esp_http_client_set_url( // alloc-allow: ESP-IDF SOUP copies URL state
440 state->http,
441 state->url);
442 if (url_status != ESP_OK) {
444 return k_ra8_fail;
445 }
446 if (mbedtls_sha256_starts(&state->sha, 0) != 0) {
448 return k_ra8_fail;
449 }
450 state->hashing = true;
451 return k_ra8_ok;
452}
453
473{
474 if (state->opened) {
475 return k_ra8_ok;
476 }
477 const esp_err_t open_status = esp_http_client_open( // alloc-allow: ESP-IDF SOUP creates TLS state
478 state->http,
479 0);
480 if (open_status != ESP_OK) {
481 return k_ra8_fail;
482 }
483 const int64_t content_length = esp_http_client_fetch_headers(state->http);
484 const int status = esp_http_client_get_status_code(state->http);
485 if (state->header_error != k_ra8_ok) {
486 return state->header_error;
487 }
488 if ((status < k_mdl_http_status_min) || (status > k_mdl_http_status_max)) {
490 }
491 state->response.status = status;
492 state->total = (content_length >= 0) ? (uint64_t)content_length : 0U;
493 state->total_known = (content_length >= 0);
494 state->opened = true;
495 return k_ra8_ok;
496}
497
519 uint64_t* total_bytes,
520 bool* complete,
521 uint8_t sha256[k_ra8_mdl_sha256_bytes],
522 ra8_mdl_http_response_t* response)
523{
527 }
528 if (state->total_known) {
529 if (state->received != state->total) {
532 }
533 }
534 if (mbedtls_sha256_finish(&state->sha, sha256) != 0) {
536 return k_ra8_fail;
537 }
538 if (!state->total_known) {
539 state->total = state->received;
540 }
541 *total_bytes = state->total;
542 *complete = true;
543 *response = state->response;
545 return k_ra8_ok;
546}
547
571 const uint8_t* out,
572 int read,
573 uint16_t* got,
574 uint64_t* total_bytes)
575{
576 if (state->received > (UINT64_MAX - (uint64_t)read)) {
579 }
580 const uint64_t next_received = state->received + (uint64_t)read;
581 if (state->total_known) {
582 if (next_received > state->total) {
585 }
586 }
587 if (mbedtls_sha256_update(&state->sha, out, (size_t)read) != 0) {
589 return k_ra8_fail;
590 }
591 state->received = next_received;
592 *got = (uint16_t)read;
593 *total_bytes = state->total;
594 return k_ra8_ok;
595}
596
621 uint8_t* out,
622 uint16_t cap,
623 uint16_t* got,
624 uint64_t* total_bytes,
625 bool* complete,
626 uint8_t sha256[k_ra8_mdl_sha256_bytes],
627 ra8_mdl_http_response_t* response)
628{
629 *got = 0U;
630 *total_bytes = 0U;
631 *complete = false;
632 *response = (ra8_mdl_http_response_t){};
633 mdl_http_state_t* state = (mdl_http_state_t*)ctx;
634 const ra8_err_t opened = internal_mdl_http_open(state);
635 if (opened != k_ra8_ok) {
637 return opened;
638 }
639 const int read = esp_http_client_read(state->http, (char*)out, cap);
640 if (read < 0) {
642 return k_ra8_fail;
643 }
644 if ((uint32_t)read > (uint32_t)cap) {
646 return k_ra8_fail;
647 }
648 if (read > 0) {
649 return internal_mdl_http_account_read(state, out, read, got, total_bytes);
650 }
651 return internal_mdl_http_finish(state, total_bytes, complete, sha256, response);
652}
653
672
700{
701 switch (result) {
702 case k_ra8_ok:
703 return ESP_OK;
704 case k_ra8_err_no_mem:
705 return ESP_ERR_NO_MEM;
708 return ESP_ERR_INVALID_ARG;
709 case k_ra8_err_busy:
715 return ESP_ERR_NOT_FOUND;
717 return ESP_ERR_TIMEOUT;
722 return ESP_ERR_INVALID_CRC;
723 default:
724 return ESP_FAIL;
725 }
726}
727
760 const uint8_t* request,
761 size_t request_len,
762 uint8_t* response,
763 size_t response_cap,
764 size_t* response_len)
765{
766 if (response_len == nullptr) {
767 return ESP_ERR_INVALID_ARG;
768 }
769 *response_len = 0U;
770 if ((message_id != k_ra8_mdl_rpc_start) && (message_id != k_ra8_mdl_rpc_next) &&
771 (message_id != k_ra8_mdl_rpc_cancel)) {
773 }
774 if (s_component_abi() != 1U) {
775 return ESP_FAIL;
776 }
777 if (!s_initialised) {
779 return ESP_FAIL;
780 }
781 const ra8_mdl_service_backend_t backend = {.begin = internal_mdl_http_begin,
783 .cancel = internal_mdl_http_cancel,
784 .ctx = &s_http};
785 if (ra8_mdl_service_init(&s_service, &backend) != k_ra8_ok) {
786 return ESP_FAIL;
787 }
788 s_initialised = true;
789 }
791 message_id,
792 request,
793 request_len,
794 response,
795 response_cap,
796 response_len);
797 return internal_mdl_to_esp_status(result);
798}
@ ESP_ERR_TIMEOUT
The operation did not finish in time.
Definition esp_err.h:148
@ ESP_ERR_INVALID_SIZE
A length or buffer size was rejected.
Definition esp_err.h:145
@ ESP_ERR_INVALID_CRC
A checksum did not verify.
Definition esp_err.h:152
@ ESP_ERR_INVALID_STATE
Legal call, wrong moment to make it.
Definition esp_err.h:144
@ ESP_OK
Success.
Definition esp_err.h:139
@ ESP_ERR_INVALID_RESPONSE
Reply was malformed or unexpected.
Definition esp_err.h:151
@ ESP_ERR_NO_MEM
Allocation failed.
Definition esp_err.h:142
@ ESP_ERR_NOT_SUPPORTED
The co-processor image lacks this.
Definition esp_err.h:147
@ ESP_ERR_NOT_FOUND
The requested item does not exist.
Definition esp_err.h:146
@ ESP_FAIL
Generic failure with no more specific code available.
Definition esp_err.h:140
@ ESP_ERR_INVALID_ARG
A parameter was out of range or null.
Definition esp_err.h:143
int esp_err_t
Result of an esp-hosted call: zero on success, non-zero otherwise.
Definition esp_err.h:98
ESP-IDF media-service declarations for target builds and AST audits.
#define mbedtls_sha256_update
Map the parser SHA-256 update operation to its private stand-in.
#define esp_http_client_read
Map the parser body reader to its module-private stand-in.
#define esp_http_client_open
Map the parser HTTP open operation to its private stand-in.
#define mbedtls_sha256_starts
Map the parser SHA-256 start operation to its private stand-in.
#define esp_http_client_fetch_headers
Map the parser header fetch to its module-private stand-in.
#define esp_http_client_close
Map the parser HTTP close operation to its private stand-in.
struct esp_http_client * esp_http_client_handle_t
Opaque host-parser stand-in for an ESP-IDF HTTP client.
#define esp_crt_bundle_attach
Map the parser bundle callback to its module-private stand-in.
#define esp_http_client_init
Map the parser HTTP constructor to its module-private stand-in.
@ HTTP_EVENT_ON_HEADER
One response header is available.
#define esp_http_client_delete_header
Map the parser request-header remover to its private stand-in.
#define mbedtls_sha256_init
Map the parser SHA-256 initializer to its private stand-in.
#define esp_http_client_set_timeout_ms
Map the parser timeout setter to its private stand-in.
#define esp_http_client_set_url
Map the parser URL setter to its module-private stand-in.
#define esp_http_client_set_header
Map the parser request-header setter to its private stand-in.
#define mbedtls_sha256_finish
Map the parser SHA-256 finalizer to its private stand-in.
#define esp_http_client_get_status_code
Map the parser status accessor to its module-private stand-in.
#define esp_http_client_is_complete_data_received
Map the parser completion query to its module-private stand-in.
mdl_format_t
Artifact format selected by a media-download composition root.
Definition mdl_format.h:35
@ k_mdl_format_invalid
Unrecognized or unsupported selection.
Definition mdl_format.h:45
@ k_mdl_format_rabook
Chunked reader-native book (.rabook).
Definition mdl_format.h:44
static esp_err_t internal_mdl_to_esp_status(ra8_err_t result)
Translate a portable media-service result into ESP-IDF's error domain.
esp_err_t esp_hosted_custom_rpc_sync_handler(uint32_t message_id, const uint8_t *request, size_t request_len, uint8_t *response, size_t response_cap, size_t *response_len)
Strong implementation consumed by the pinned ESP-hosted patch.
struct mdl_http_state mdl_http_state_t
static void internal_mdl_select_response_header(mdl_http_state_t *state, const char *key, char **destination, size_t *capacity)
Select retained storage for one response header.
static ra8_err_t internal_mdl_http_init(mdl_http_state_t *state)
Create the retained ESP-IDF client and SHA context once.
static esp_err_t internal_mdl_http_event(esp_http_client_event_t *event)
Capture selected response headers from ESP-IDF events.
static ra8_err_t internal_mdl_http_finish(mdl_http_state_t *state, uint64_t *total_bytes, bool *complete, uint8_t sha256[k_ra8_mdl_sha256_bytes], ra8_mdl_http_response_t *response)
Validate EOF and publish the terminal length and digest.
static ra8_err_t internal_mdl_http_cancel(void *ctx)
Cancel the active HTTP job while retaining one-time objects.
static ra8_err_t internal_mdl_http_apply_request(mdl_http_state_t *state, const ra8_mdl_request_t *request)
Copy and apply the complete bounded request policy.
static ra8_err_t internal_mdl_http_read(void *ctx, uint8_t *out, uint16_t cap, uint16_t *got, uint64_t *total_bytes, bool *complete, uint8_t sha256[k_ra8_mdl_sha256_bytes], ra8_mdl_http_response_t *response)
Pull one bounded body span or verified terminal metadata.
static bool internal_mdl_header_equal(const char *lhs, const char *rhs)
Compare one HTTP header name without ASCII case sensitivity.
static ra8_err_t internal_mdl_copy_field(char *destination, size_t capacity, const char *source)
Copy one optional bounded HTTP field into retained storage.
static void internal_mdl_http_reset_job(mdl_http_state_t *state)
Close one request while retaining the one-time client/hash objects.
Definition mdl_service.c:98
static bool s_initialised
Definition mdl_service.c:60
static mdl_http_state_t s_http
Definition mdl_service.c:58
static ra8_err_t internal_mdl_http_set_header(mdl_http_state_t *state, const char *name, const char *value)
Replace one optional retained request header.
static ra8_err_t internal_mdl_http_open(mdl_http_state_t *state)
Open lazily so Start returns without waiting for network exchange.
static ra8_err_t internal_mdl_http_account_read(mdl_http_state_t *state, const uint8_t *out, int read, uint16_t *got, uint64_t *total_bytes)
Account one successful nonzero body read into job state.
static mdl_component_abi_fn_t volatile s_component_abi
Definition mdl_service.c:83
uint32_t ra8_mdl_service_component_abi(void)
Return the linked first-party media component ABI version.
Definition mdl_service.c:75
static ra8_err_t internal_mdl_http_begin(void *ctx, const ra8_mdl_request_t *request)
Validate and prepare one typed HTTPS-artifact job.
static ra8_mdl_service_t s_service
Definition mdl_service.c:59
mdl_http_const_t
Fixed HTTP policy values for the concrete ESP-IDF adapter.
Definition mdl_service.c:28
@ k_mdl_http_status_min
Lowest valid terminal status.
Definition mdl_service.c:30
@ k_mdl_http_status_max
Highest valid terminal status.
Definition mdl_service.c:31
@ k_mdl_http_timeout_ms
Default whole-request timeout.
Definition mdl_service.c:29
uint32_t(* mdl_component_abi_fn_t)(void)
Return the first-party media component ABI marker.
Definition mdl_service.c:73
Annotation-attribute framework macros for ra8-firmware.
#define RA8_INTERNAL
Marker that a function is intended to be static (file-local).
@ k_ra8_err_no_mem
Static buffer exhausted (no dynamic memory on this project).
Definition ra8_err.h:142
@ k_ra8_err_busy
Resource busy – blocking operation cannot proceed.
Definition ra8_err.h:195
@ k_ra8_err_checksum_mismatch
Stored / transmitted checksum does not match computed value.
Definition ra8_err.h:465
@ k_ra8_fail
Generic unspecified failure.
Definition ra8_err.h:133
@ 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_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_null_ptr
Pointer was NULL where a valid pointer was required.
Definition ra8_err.h:478
@ k_ra8_err_protocol_error
Protocol-level error (e.g.
Definition ra8_err.h:429
@ k_ra8_err_timeout
Operation exceeded its time budget.
Definition ra8_err.h:188
@ k_ra8_err_not_found
Requested item not found (lookup / search missed).
Definition ra8_err.h:173
@ 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
int strncmp(const char *s1, const char *s2, size_t n)
Compare two strings up to a specified length.
void * memcpy(void *dst, const void *src, size_t n)
Copy memory area between non-overlapping regions.
size_t strnlen(const char *s, size_t maxlen)
Calculate bounded string length.
@ k_ra8_mdl_user_agent_max
Maximum User-Agent size, including NUL.
@ k_ra8_mdl_referer_max
Maximum Referer size, including NUL.
@ k_ra8_mdl_chunk_data_max
Maximum raw body bytes in one chunk.
@ k_ra8_mdl_url_max
Maximum URL buffer size, including NUL.
@ k_ra8_mdl_http_date_max
Maximum HTTP-date size, including NUL.
@ k_ra8_mdl_etag_max
Maximum ETag size, including NUL.
@ k_ra8_mdl_sha256_bytes
SHA-256 digest size in bytes.
@ k_ra8_mdl_rpc_start
Start one typed-artifact job.
@ k_ra8_mdl_rpc_cancel
Cancel one active job.
@ k_ra8_mdl_rpc_next
Pull one ordered bounded chunk.
Public integration contract for the ESP32-C6 media RPC component.
uint32_t ra8_mdl_service_component_abi(void)
Return the linked first-party media component ABI version.
Definition mdl_service.c:75
Exact consumed subset of ESP-IDF's HTTP client configuration.
Parser mirror of the ESP-IDF HTTP event record.
void * user_data
Configuration context.
char * header_value
Header value for ON_HEADER.
esp_http_client_event_id_t event_id
Event selector.
char * header_key
Header name for ON_HEADER.
Parser-only storage standing in for ESP-IDF's SHA-256 context.
Single retained ESP-IDF client and one serialized remote transfer.
Definition mdl_service.c:40
uint64_t total
Advertised body length, or zero.
Definition mdl_service.c:50
esp_http_client_handle_t http
Retained ESP HTTP client handle.
Definition mdl_service.c:41
uint64_t received
Independently counted body bytes.
Definition mdl_service.c:51
char if_none_match[k_ra8_mdl_etag_max]
Active If-None-Match request value.
Definition mdl_service.c:46
bool total_known
Whether Content-Length was present.
Definition mdl_service.c:53
char if_modified_since[k_ra8_mdl_http_date_max]
Active If-Modified-Since request value.
Definition mdl_service.c:47
char url[k_ra8_mdl_url_max]
Bounded active HTTPS URL.
Definition mdl_service.c:43
mdl_format_t format
Requested artifact identity.
Definition mdl_service.c:52
char referer[k_ra8_mdl_referer_max]
Active Referer request value.
Definition mdl_service.c:45
bool hashing
Whether a SHA operation is active.
Definition mdl_service.c:55
mbedtls_sha256_context sha
Retained streaming SHA context.
Definition mdl_service.c:42
ra8_mdl_http_response_t response
Selected terminal response metadata.
Definition mdl_service.c:48
bool opened
Whether response headers were accepted.
Definition mdl_service.c:54
char user_agent[k_ra8_mdl_user_agent_max]
Active User-Agent request value.
Definition mdl_service.c:44
ra8_err_t header_error
First response-header capture failure.
Definition mdl_service.c:49
uint32_t timeout_ms
Whole-request timeout, or zero for default.
const char * if_modified_since
If-Modified-Since value, or null/empty.
const char * if_none_match
If-None-Match value, or null/empty to omit.
const char * user_agent
User-Agent value, or null/empty to omit.
const char * referer
Referer value, or null/empty to omit.
HTTP status and selected response headers proven by the C6 backend.
char last_modified[k_ra8_mdl_http_date_max]
Last-Modified or empty.
int32_t status
Final HTTP status.
char retry_after[k_ra8_mdl_retry_after_max]
Retry-After or empty.
char content_type[k_ra8_mdl_content_type_max]
Content-Type or empty.
char etag[k_ra8_mdl_etag_max]
ETag or empty.
Complete typed HTTPS request accepted by protocol version 3.
mdl_format_t format
Exact returned artifact identity.
ra8_mdl_http_policy_t http
Forwarded request policy.
const char * url
Absolute HTTPS source URL.