nano attachment add

This commit is contained in:
wiaamm
2026-01-14 19:44:01 +02:00
parent db963739bd
commit 4402e6a861
4 changed files with 308 additions and 38 deletions

View File

@@ -95,6 +95,7 @@ InitNanoAttachment(uint8_t attachment_type, int worker_id, int num_of_workers, i
attachment->inspection_mode = NON_BLOCKING_THREAD;
attachment->num_of_nano_ipc_elements = 200;
attachment->keep_alive_interval_msec = DEFAULT_KEEP_ALIVE_INTERVAL_MSEC;
attachment->paired_affinity_enabled = 0;
if (nano_attachment_init_process(attachment) != NANO_OK) {
write_dbg(attachment, 0, DBG_LEVEL_WARNING, "Could not initialize nano attachment");
@@ -548,6 +549,46 @@ GetRedirectPage(NanoAttachment *attachment, HttpSessionData *session_data, Attac
};
}
CustomResponseWithHeaders *
GetCustomResponseWithHeaders(
NanoAttachment *attachment,
HttpSessionData *session_data,
AttachmentVerdictResponse *response
)
{
WebResponseData *web_response_data = response->web_response_data;
if (web_response_data == NULL) {
write_dbg(
attachment,
session_data->session_id,
DBG_LEVEL_WARNING,
"Trying to get custom response with headers but no response object"
);
return NULL;
}
if (web_response_data->web_response_type != CUSTOM_RESPONSE_WITH_HEADERS) {
write_dbg(
attachment,
session_data->session_id,
DBG_LEVEL_WARNING,
"Trying to get custom response with headers but response type is %d",
web_response_data->web_response_type
);
return NULL;
}
write_dbg(
attachment,
session_data->session_id,
DBG_LEVEL_TRACE,
"Getting custom response with headers"
);
return (CustomResponseWithHeaders *) web_response_data->data;
}
void
FreeAttachmentResponseContent(
NanoAttachment *attachment,
@@ -582,7 +623,31 @@ FreeAttachmentResponseContent(
"Freeing custom web response data"
);
free(response->web_response_data->data);
// Free custom response with headers if applicable
if (response->web_response_data->web_response_type == CUSTOM_RESPONSE_WITH_HEADERS) {
CustomResponseWithHeaders *custom_resp =
(CustomResponseWithHeaders *)response->web_response_data->data;
if (custom_resp != NULL) {
uint8_t i;
if (custom_resp->headers != NULL) {
for (i = 0; i < custom_resp->headers_count; i++) {
if (custom_resp->headers[i].key != NULL) {
free(custom_resp->headers[i].key);
}
if (custom_resp->headers[i].value != NULL) {
free(custom_resp->headers[i].value);
}
}
free(custom_resp->headers);
}
if (custom_resp->body != NULL) {
free(custom_resp->body);
}
free(custom_resp);
}
} else {
free(response->web_response_data->data);
}
free(response->web_response_data);
response->web_response_data = NULL;
}
@@ -624,22 +689,3 @@ freeCompressedBody(NanoAttachment *attachment, HttpSessionData *session_data, Na
{
nano_free_compressed_body(attachment, bodies, session_data);
}
uint32_t
GetRequestProcessingTimeout(NanoAttachment *attachment)
{
if (attachment == NULL) {
return 3000;
}
return attachment->req_max_proccessing_ms_time;
}
uint32_t
GetResponseProcessingTimeout(NanoAttachment *attachment)
{
if (attachment == NULL) {
return 3000;
}
return attachment->res_max_proccessing_ms_time;
}

View File

@@ -707,6 +707,161 @@ handle_redirect_response(
*ctx_response_data = new_response_data;
}
///
/// @brief Handle custom response with dynamic headers
///
/// @param[in] attachment Nano attachment.
/// @param[in] session_id Session ID.
/// @param[in] ctx_response_data Web response data to be set.
/// @param[in] custom_response_data Custom response data with headers.
///
static void
handle_custom_response_with_headers(
NanoAttachment *attachment,
SessionID session_id,
WebResponseData **ctx_response_data,
HttpCustomResponseData *custom_response_data
)
{
WebResponseData *new_response_data = NULL;
CustomResponseWithHeaders *response_with_headers = NULL;
char *data_ptr = custom_response_data->data;
uint16_t body_size = custom_response_data->body_size;
uint8_t headers_count = custom_response_data->headers_count;
uint8_t i, j;
write_dbg(
attachment,
session_id,
DBG_LEVEL_TRACE,
"Preparing to set custom response with %d headers and body size %d",
headers_count,
body_size
);
new_response_data = malloc(sizeof(WebResponseData));
if (new_response_data == NULL) {
write_dbg(attachment, session_id, DBG_LEVEL_WARNING, "Failed to allocate memory for web response data");
return;
}
response_with_headers = malloc(sizeof(CustomResponseWithHeaders));
if (response_with_headers == NULL) {
write_dbg(attachment, session_id, DBG_LEVEL_WARNING, "Failed to allocate memory for custom response with headers");
free(new_response_data);
return;
}
response_with_headers->response_code = custom_response_data->response_code;
response_with_headers->headers_count = headers_count;
// Allocate headers array
if (headers_count > 0) {
response_with_headers->headers = malloc(sizeof(CustomResponseHeaderData) * headers_count);
if (response_with_headers->headers == NULL) {
write_dbg(attachment, session_id, DBG_LEVEL_WARNING, "Failed to allocate memory for headers");
free(response_with_headers);
free(new_response_data);
return;
}
// Parse each header
for (i = 0; i < headers_count; i++) {
HttpHeaderPackedData *header_data = (HttpHeaderPackedData *)data_ptr;
response_with_headers->headers[i].key_size = header_data->key_size;
response_with_headers->headers[i].value_size = header_data->value_size;
// Allocate and copy key
response_with_headers->headers[i].key = malloc(header_data->key_size + 1);
if (response_with_headers->headers[i].key == NULL) {
write_dbg(attachment, session_id, DBG_LEVEL_WARNING, "Failed to allocate memory for header key");
// Free previously allocated headers
for (j = 0; j < i; j++) {
free(response_with_headers->headers[j].key);
free(response_with_headers->headers[j].value);
}
free(response_with_headers->headers);
free(response_with_headers);
free(new_response_data);
return;
}
data_ptr += sizeof(HttpHeaderPackedData);
memcpy(response_with_headers->headers[i].key, data_ptr, header_data->key_size);
response_with_headers->headers[i].key[header_data->key_size] = '\0';
data_ptr += header_data->key_size;
// Allocate and copy value
response_with_headers->headers[i].value = malloc(header_data->value_size + 1);
if (response_with_headers->headers[i].value == NULL) {
write_dbg(attachment, session_id, DBG_LEVEL_WARNING, "Failed to allocate memory for header value");
free(response_with_headers->headers[i].key);
for (j = 0; j < i; j++) {
free(response_with_headers->headers[j].key);
free(response_with_headers->headers[j].value);
}
free(response_with_headers->headers);
free(response_with_headers);
free(new_response_data);
return;
}
memcpy(response_with_headers->headers[i].value, data_ptr, header_data->value_size);
response_with_headers->headers[i].value[header_data->value_size] = '\0';
data_ptr += header_data->value_size;
write_dbg(
attachment,
session_id,
DBG_LEVEL_TRACE,
"Parsed header %d: '%s' = '%s'",
i,
response_with_headers->headers[i].key,
response_with_headers->headers[i].value
);
}
} else {
response_with_headers->headers = NULL;
}
// Allocate and copy body
response_with_headers->body_size = body_size;
if (body_size > 0) {
response_with_headers->body = malloc(body_size + 1);
if (response_with_headers->body == NULL) {
write_dbg(attachment, session_id, DBG_LEVEL_WARNING, "Failed to allocate memory for response body");
for (i = 0; i < headers_count; i++) {
free(response_with_headers->headers[i].key);
free(response_with_headers->headers[i].value);
}
if (response_with_headers->headers) free(response_with_headers->headers);
free(response_with_headers);
free(new_response_data);
return;
}
memcpy(response_with_headers->body, data_ptr, body_size);
response_with_headers->body[body_size] = '\0';
} else {
response_with_headers->body = NULL;
}
new_response_data->web_response_type = CUSTOM_RESPONSE_WITH_HEADERS;
new_response_data->uuid[0] = '\0'; // No UUID for custom responses
new_response_data->data = response_with_headers;
*ctx_response_data = new_response_data;
write_dbg(
attachment,
session_id,
DBG_LEVEL_TRACE,
"Successfully set custom response: code=%d, headers=%d, body_size=%d",
response_with_headers->response_code,
headers_count,
body_size
);
}
///
/// @brief Handles drop response received from a service.
///
@@ -876,6 +1031,34 @@ service_reply_receiver(
return NANO_HTTP_FORBIDDEN;
}
case TRAFFIC_VERDICT_CUSTOM_RESPONSE: {
// After a custom response verdict no more replies will be sent
write_dbg(
attachment,
session_data->session_id,
DBG_LEVEL_TRACE,
"Verdict custom response received from the nano service"
);
updateMetricField(attachment, DROP_VERDICTS_COUNT, 1);
handle_custom_response_with_headers(
attachment,
session_data->session_id,
web_response_data,
reply_p->modify_data->custom_response_data
);
session_data->remaining_messages_to_reply = 0;
while (*modification_list) {
current_modification = *modification_list;
*modification_list = (*modification_list)->next;
free(current_modification->modification.data);
free(current_modification);
}
popData(attachment->nano_service_ipc);
return NANO_HTTP_FORBIDDEN;
}
case TRAFFIC_VERDICT_ACCEPT: {
// After an accept verdict no more replies will be sent, so we can leave the loop
write_dbg(
@@ -938,6 +1121,17 @@ service_reply_receiver(
updateMetricField(attachment, HOLD_VERDICTS_COUNT, 1);
break;
}
case LIMIT_RESPONSE_HEADERS: {
// TODO: Handle this verdict in the future.
write_dbg(
attachment,
session_data->session_id,
DBG_LEVEL_WARNING,
"Verdict %d received from the nano service, which is not supported yet",
session_data->verdict
);
break;
}
}
popData(attachment->nano_service_ipc);
}