mirror of
https://github.com/openappsec/attachment.git
synced 2026-01-17 16:00:26 +03:00
nano attachment add
This commit is contained in:
@@ -95,6 +95,7 @@ InitNanoAttachment(uint8_t attachment_type, int worker_id, int num_of_workers, i
|
|||||||
attachment->inspection_mode = NON_BLOCKING_THREAD;
|
attachment->inspection_mode = NON_BLOCKING_THREAD;
|
||||||
attachment->num_of_nano_ipc_elements = 200;
|
attachment->num_of_nano_ipc_elements = 200;
|
||||||
attachment->keep_alive_interval_msec = DEFAULT_KEEP_ALIVE_INTERVAL_MSEC;
|
attachment->keep_alive_interval_msec = DEFAULT_KEEP_ALIVE_INTERVAL_MSEC;
|
||||||
|
attachment->paired_affinity_enabled = 0;
|
||||||
|
|
||||||
if (nano_attachment_init_process(attachment) != NANO_OK) {
|
if (nano_attachment_init_process(attachment) != NANO_OK) {
|
||||||
write_dbg(attachment, 0, DBG_LEVEL_WARNING, "Could not initialize nano attachment");
|
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
|
void
|
||||||
FreeAttachmentResponseContent(
|
FreeAttachmentResponseContent(
|
||||||
NanoAttachment *attachment,
|
NanoAttachment *attachment,
|
||||||
@@ -582,7 +623,31 @@ FreeAttachmentResponseContent(
|
|||||||
"Freeing custom web response data"
|
"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);
|
free(response->web_response_data);
|
||||||
response->web_response_data = NULL;
|
response->web_response_data = NULL;
|
||||||
}
|
}
|
||||||
@@ -624,22 +689,3 @@ freeCompressedBody(NanoAttachment *attachment, HttpSessionData *session_data, Na
|
|||||||
{
|
{
|
||||||
nano_free_compressed_body(attachment, bodies, session_data);
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|||||||
@@ -707,6 +707,161 @@ handle_redirect_response(
|
|||||||
*ctx_response_data = new_response_data;
|
*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.
|
/// @brief Handles drop response received from a service.
|
||||||
///
|
///
|
||||||
@@ -876,6 +1031,34 @@ service_reply_receiver(
|
|||||||
return NANO_HTTP_FORBIDDEN;
|
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: {
|
case TRAFFIC_VERDICT_ACCEPT: {
|
||||||
// After an accept verdict no more replies will be sent, so we can leave the loop
|
// After an accept verdict no more replies will be sent, so we can leave the loop
|
||||||
write_dbg(
|
write_dbg(
|
||||||
@@ -938,6 +1121,17 @@ service_reply_receiver(
|
|||||||
updateMetricField(attachment, HOLD_VERDICTS_COUNT, 1);
|
updateMetricField(attachment, HOLD_VERDICTS_COUNT, 1);
|
||||||
break;
|
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);
|
popData(attachment->nano_service_ipc);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ uint16_t GetResponseCode(
|
|||||||
);
|
);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Retrieves the redict page data for a response.
|
/// @brief Retrieves the redirect page data for a response.
|
||||||
///
|
///
|
||||||
/// @param attachment The NanoAttachment object associated with the session.
|
/// @param attachment The NanoAttachment object associated with the session.
|
||||||
/// @param session_data The HttpSessionData object representing the session.
|
/// @param session_data The HttpSessionData object representing the session.
|
||||||
@@ -209,6 +209,21 @@ RedirectPageData GetRedirectPage(
|
|||||||
AttachmentVerdictResponse *response
|
AttachmentVerdictResponse *response
|
||||||
);
|
);
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Retrieves the custom response with headers data.
|
||||||
|
///
|
||||||
|
/// @param attachment The NanoAttachment object associated with the session.
|
||||||
|
/// @param session_data The HttpSessionData object representing the session.
|
||||||
|
/// @param response The AttachmentVerdictResponse object containing the verdict.
|
||||||
|
///
|
||||||
|
/// @return CustomResponseWithHeaders structure containing response code, headers, and body.
|
||||||
|
///
|
||||||
|
CustomResponseWithHeaders * GetCustomResponseWithHeaders(
|
||||||
|
NanoAttachment *attachment,
|
||||||
|
HttpSessionData *session_data,
|
||||||
|
AttachmentVerdictResponse *response
|
||||||
|
);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// @brief Free allocated resources of an AttachmentVerdictResponse.
|
/// @brief Free allocated resources of an AttachmentVerdictResponse.
|
||||||
///
|
///
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ typedef int64_t NanoHttpCpInjectPos;
|
|||||||
#define MAX_NGINX_UID_LEN 32
|
#define MAX_NGINX_UID_LEN 32
|
||||||
#define MAX_SHARED_MEM_PATH_LEN 128
|
#define MAX_SHARED_MEM_PATH_LEN 128
|
||||||
#define NUM_OF_NGINX_IPC_ELEMENTS 200
|
#define NUM_OF_NGINX_IPC_ELEMENTS 200
|
||||||
|
// The maximum is 2048, but we limit it to 2000 to avoid Alpine memory page layout issues (SIGBUS)
|
||||||
|
#define NUM_OF_NGINX_IPC_ELEMENTS_ASYNC 2000
|
||||||
#define DEFAULT_KEEP_ALIVE_INTERVAL_MSEC 300000u
|
#define DEFAULT_KEEP_ALIVE_INTERVAL_MSEC 300000u
|
||||||
#define SHARED_MEM_PATH "/dev/shm/"
|
#define SHARED_MEM_PATH "/dev/shm/"
|
||||||
#define SHARED_REGISTRATION_SIGNAL_PATH SHARED_MEM_PATH "check-point/cp-nano-attachment-registration"
|
#define SHARED_REGISTRATION_SIGNAL_PATH SHARED_MEM_PATH "check-point/cp-nano-attachment-registration"
|
||||||
@@ -49,6 +51,7 @@ typedef enum NanoWebResponseType
|
|||||||
CUSTOM_WEB_BLOCK_PAGE_RESPONSE,
|
CUSTOM_WEB_BLOCK_PAGE_RESPONSE,
|
||||||
RESPONSE_CODE_ONLY,
|
RESPONSE_CODE_ONLY,
|
||||||
REDIRECT_WEB_RESPONSE,
|
REDIRECT_WEB_RESPONSE,
|
||||||
|
CUSTOM_RESPONSE_WITH_HEADERS,
|
||||||
|
|
||||||
NO_WEB_RESPONSE
|
NO_WEB_RESPONSE
|
||||||
} NanoWebResponseType;
|
} NanoWebResponseType;
|
||||||
@@ -220,18 +223,6 @@ typedef enum ServiceVerdict
|
|||||||
TRAFFIC_VERDICT_CUSTOM_RESPONSE
|
TRAFFIC_VERDICT_CUSTOM_RESPONSE
|
||||||
} ServiceVerdict;
|
} ServiceVerdict;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
typedef enum class AttachmentContentType
|
|
||||||
#else
|
|
||||||
typedef enum AttachmentContentType
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
CONTENT_TYPE_APPLICATION_JSON,
|
|
||||||
CONTENT_TYPE_TEXT_HTML,
|
|
||||||
CONTENT_TYPE_TEXT_PLAIN,
|
|
||||||
CONTENT_TYPE_OTHER
|
|
||||||
} AttachmentContentType;
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
typedef enum class AttachmentVerdict
|
typedef enum class AttachmentVerdict
|
||||||
#else
|
#else
|
||||||
@@ -285,12 +276,14 @@ typedef struct __attribute__((__packed__)) HttpWebResponseData {
|
|||||||
} response_data;
|
} response_data;
|
||||||
} HttpWebResponseData;
|
} HttpWebResponseData;
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) HttpJsonResponseData {
|
// Custom response structure with dynamic headers
|
||||||
|
typedef struct __attribute__((__packed__)) HttpCustomResponseData {
|
||||||
uint16_t response_code;
|
uint16_t response_code;
|
||||||
uint16_t body_size;
|
uint16_t body_size;
|
||||||
AttachmentContentType content_type;
|
uint8_t headers_count;
|
||||||
char body[0];
|
char data[0]; // headers followed by body
|
||||||
} HttpJsonResponseData;
|
// Memory layout: [HttpHeaderPackedData1][HttpHeaderPackedData2]...[body_data]
|
||||||
|
} HttpCustomResponseData;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
size_t len;
|
size_t len;
|
||||||
@@ -307,6 +300,21 @@ typedef struct RedirectData {
|
|||||||
unsigned char redirect_location[REDIRECT_RESPONSE_LOCATION_SIZE];
|
unsigned char redirect_location[REDIRECT_RESPONSE_LOCATION_SIZE];
|
||||||
} RedirectData;
|
} RedirectData;
|
||||||
|
|
||||||
|
typedef struct CustomResponseHeaderData {
|
||||||
|
uint16_t key_size;
|
||||||
|
uint16_t value_size;
|
||||||
|
char *key;
|
||||||
|
char *value;
|
||||||
|
} CustomResponseHeaderData;
|
||||||
|
|
||||||
|
typedef struct CustomResponseWithHeaders {
|
||||||
|
uint16_t response_code;
|
||||||
|
uint16_t body_size;
|
||||||
|
uint8_t headers_count;
|
||||||
|
CustomResponseHeaderData *headers;
|
||||||
|
char *body;
|
||||||
|
} CustomResponseWithHeaders;
|
||||||
|
|
||||||
typedef struct WebResponseData {
|
typedef struct WebResponseData {
|
||||||
NanoWebResponseType web_response_type;
|
NanoWebResponseType web_response_type;
|
||||||
unsigned char uuid[UUID_SIZE];
|
unsigned char uuid[UUID_SIZE];
|
||||||
@@ -416,6 +424,13 @@ typedef struct HttpHeaderData {
|
|||||||
nano_str_t value;
|
nano_str_t value;
|
||||||
} HttpHeaderData;
|
} HttpHeaderData;
|
||||||
|
|
||||||
|
// Packed header data structure for dynamic headers in custom responses (IPC transfer)
|
||||||
|
typedef struct __attribute__((__packed__)) HttpHeaderPackedData {
|
||||||
|
uint16_t key_size;
|
||||||
|
uint16_t value_size;
|
||||||
|
char data[0]; // key followed by value
|
||||||
|
} HttpHeaderPackedData;
|
||||||
|
|
||||||
typedef struct HttpHeaders {
|
typedef struct HttpHeaders {
|
||||||
HttpHeaderData *data;
|
HttpHeaderData *data;
|
||||||
size_t headers_count;
|
size_t headers_count;
|
||||||
@@ -448,7 +463,7 @@ typedef struct AttachmentData {
|
|||||||
typedef union __attribute__((__packed__)) HttpModifyData {
|
typedef union __attribute__((__packed__)) HttpModifyData {
|
||||||
HttpInjectData inject_data[0];
|
HttpInjectData inject_data[0];
|
||||||
HttpWebResponseData web_response_data[0];
|
HttpWebResponseData web_response_data[0];
|
||||||
HttpJsonResponseData json_response_data[0];
|
HttpCustomResponseData custom_response_data[0];
|
||||||
} HttpModifyData;
|
} HttpModifyData;
|
||||||
|
|
||||||
typedef struct __attribute__((__packed__)) HttpReplyFromService {
|
typedef struct __attribute__((__packed__)) HttpReplyFromService {
|
||||||
|
|||||||
Reference in New Issue
Block a user