mirror of
https://github.com/openappsec/attachment.git
synced 2025-12-31 13:49:09 +03:00
Summary: * Implement TRAFFIC_VERDICT_DELAYED handling in SendResponseBody function * Add delayed verdict thread spawning when response body returns delayed verdict This change mirrors the existing delayed verdict handling in SendRequestBody to ensure consistent behavior for both request and response body processing.
821 lines
24 KiB
C
821 lines
24 KiB
C
#include "nano_attachment_sender.h"
|
|
|
|
#include <time.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "nano_attachment_sender_thread.h"
|
|
#include "nano_attachment_thread.h"
|
|
#include "nano_utils.h"
|
|
#include "nano_attachment_metric.h"
|
|
|
|
static unsigned char default_uuid[] = "20118dba-81f7-4999-8e94-003cf242f5dd\0";
|
|
static const size_t default_uuid_size = 37;
|
|
|
|
static unsigned char default_title[] = "Default Title\0";
|
|
static const size_t default_title_size = 14;
|
|
|
|
static unsigned char default_body[] = "Default Body\0";
|
|
static const size_t default_body_size = 13;
|
|
|
|
static uint16_t default_response_code = 403;
|
|
|
|
///
|
|
/// @brief Creates a default block page.
|
|
///
|
|
/// @param attachment Pointer to the NanoAttachment struct representing the attachment.
|
|
/// @param session_id The session ID associated with the attachment.
|
|
/// @return A pointer to a WebResponseData struct containing the default block page data.
|
|
///
|
|
static WebResponseData*
|
|
CreateDefaultBlockPage(NanoAttachment *attachment, SessionID session_id)
|
|
{
|
|
WebResponseData *web_response_data = NULL;
|
|
CustomResponseData *custom_response_data = NULL;
|
|
|
|
web_response_data = (WebResponseData *)malloc(sizeof(WebResponseData));
|
|
if (web_response_data == NULL) {
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_WARNING,
|
|
"Failed to allocate memory for WebResponseData"
|
|
);
|
|
return NULL;
|
|
}
|
|
|
|
custom_response_data = (CustomResponseData *)malloc(sizeof(CustomResponseData));
|
|
if (custom_response_data == NULL) {
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_WARNING,
|
|
"Failed to allocate memory for CustomResponseData"
|
|
);
|
|
free(web_response_data);
|
|
return NULL;
|
|
}
|
|
|
|
web_response_data->web_response_type = CUSTOM_WEB_RESPONSE;
|
|
memcpy(web_response_data->uuid, default_uuid, default_uuid_size);
|
|
custom_response_data->response_code = default_response_code;
|
|
memcpy(custom_response_data->title, default_title, default_title_size);
|
|
memcpy(custom_response_data->body, default_body, default_body_size);
|
|
web_response_data->data = (DataBuffer*)custom_response_data;
|
|
|
|
return web_response_data;
|
|
}
|
|
|
|
///
|
|
/// @brief Get a string representation of the AttachmentVerdict enum.
|
|
///
|
|
/// @param verdict The AttachmentVerdict enum value.
|
|
/// @return A string representation of the enum value.
|
|
///
|
|
static const char*
|
|
AttachmentVerdictToString(AttachmentVerdict verdict)
|
|
{
|
|
switch (verdict) {
|
|
case ATTACHMENT_VERDICT_INSPECT:
|
|
return "inspect";
|
|
case ATTACHMENT_VERDICT_ACCEPT:
|
|
return "accept";
|
|
case ATTACHMENT_VERDICT_DROP:
|
|
return "drop";
|
|
case ATTACHMENT_VERDICT_INJECT:
|
|
return "inject";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
///
|
|
/// @brief Sends a verdict response for a corrupt memory condition.
|
|
///
|
|
/// @param attachment Pointer to the NanoAttachment struct representing the attachment.
|
|
/// @param session_data_p Pointer to the HttpSessionData struct containing the session data.
|
|
/// @return An AttachmentVerdictResponse struct containing the session ID and verdict.
|
|
///
|
|
static AttachmentVerdictResponse
|
|
SendCorruptMemoryVerdict(NanoAttachment *attachment, HttpSessionData *session_data_p)
|
|
{
|
|
AttachmentVerdictResponse response = {
|
|
.session_id = session_data_p->session_id,
|
|
.web_response_data = NULL,
|
|
.modifications = NULL
|
|
};
|
|
|
|
if (attachment->fail_mode_verdict == NANO_OK) {
|
|
updateMetricField(attachment, INSPECTION_OPEN_FAILURES_COUNT, 1);
|
|
response.verdict = ATTACHMENT_VERDICT_ACCEPT;
|
|
session_data_p->verdict = TRAFFIC_VERDICT_ACCEPT;
|
|
} else {
|
|
updateMetricField(attachment, INSPECTION_CLOSE_FAILURES_COUNT, 1);
|
|
response.verdict = ATTACHMENT_VERDICT_DROP;
|
|
session_data_p->verdict = TRAFFIC_VERDICT_DROP;
|
|
response.web_response_data = CreateDefaultBlockPage(attachment, session_data_p->session_id);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
response.session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Shared memory is corrupted, returning default fail mode verdict. Session id: %d, verdict: %s",
|
|
response.session_id,
|
|
response.verdict == ATTACHMENT_VERDICT_ACCEPT ? "accept" : "drop"
|
|
);
|
|
return response;
|
|
}
|
|
|
|
///
|
|
/// @brief Sends a verdict response for a thread timeout condition.
|
|
///
|
|
/// @param attachment Pointer to the NanoAttachment struct representing the attachment.
|
|
/// @param session_id The session ID associated with the attachment.
|
|
/// @param ctx Pointer to the HttpEventThreadCtx struct containing the HTTP event context.
|
|
/// @return An AttachmentVerdictResponse struct containing the session ID and verdict.
|
|
///
|
|
static AttachmentVerdictResponse
|
|
SendThreadTimeoutVerdict(NanoAttachment *attachment, SessionID session_id, HttpEventThreadCtx *ctx)
|
|
{
|
|
AttachmentVerdictResponse response = {
|
|
.session_id = session_id,
|
|
.web_response_data = NULL,
|
|
.modifications = NULL
|
|
};
|
|
|
|
if (attachment->fail_mode_verdict == NANO_OK) {
|
|
response.verdict = ATTACHMENT_VERDICT_ACCEPT;
|
|
ctx->session_data_p->verdict = TRAFFIC_VERDICT_ACCEPT;
|
|
} else {
|
|
response.verdict = ATTACHMENT_VERDICT_DROP;
|
|
ctx->session_data_p->verdict = TRAFFIC_VERDICT_DROP;
|
|
response.web_response_data = CreateDefaultBlockPage(attachment, session_id);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
response.session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Thread failed, returning fail mode verdict. Session id: %d, verdict: %s",
|
|
response.session_id,
|
|
response.verdict == ATTACHMENT_VERDICT_ACCEPT ? "accept" : "drop"
|
|
);
|
|
return response;
|
|
}
|
|
|
|
///
|
|
/// @brief Finalizes a successful response by determining the verdict based on the HTTP response code.
|
|
///
|
|
/// @param attachment Pointer to the NanoAttachment struct representing the attachment.
|
|
/// @param session_id The session ID associated with the attachment.
|
|
/// @param ctx Pointer to the HttpEventThreadCtx struct containing the HTTP event context.
|
|
/// @return An AttachmentVerdictResponse struct containing the session ID and verdict.
|
|
///
|
|
static AttachmentVerdictResponse
|
|
FinalizeSuccessfulResponse(
|
|
NanoAttachment *attachment,
|
|
SessionID session_id,
|
|
HttpEventThreadCtx *ctx
|
|
)
|
|
{
|
|
AttachmentVerdictResponse response = {
|
|
.session_id = session_id,
|
|
.web_response_data = ctx->web_response_data,
|
|
.modifications = ctx->modifications
|
|
};
|
|
|
|
switch (ctx->session_data_p->verdict) {
|
|
case TRAFFIC_VERDICT_INSPECT:
|
|
response.verdict = ATTACHMENT_VERDICT_INSPECT;
|
|
break;
|
|
case TRAFFIC_VERDICT_ACCEPT:
|
|
response.verdict = ATTACHMENT_VERDICT_ACCEPT;
|
|
break;
|
|
case TRAFFIC_VERDICT_DROP:
|
|
response.verdict = ATTACHMENT_VERDICT_DROP;
|
|
break;
|
|
case TRAFFIC_VERDICT_INJECT:
|
|
// Not yet supported
|
|
response.verdict = ATTACHMENT_VERDICT_INSPECT;
|
|
break;
|
|
default:
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_WARNING,
|
|
"Unknown verdict %d",
|
|
ctx->session_data_p->verdict
|
|
);
|
|
response.verdict = ATTACHMENT_VERDICT_INSPECT;
|
|
break;
|
|
}
|
|
|
|
updateMetricField(attachment, INSPECTION_SUCCESSES_COUNT, 1);
|
|
|
|
write_dbg(
|
|
attachment,
|
|
response.session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Finalizing successful response to Session id: %d, verdict: %s",
|
|
response.session_id,
|
|
AttachmentVerdictToString(response.verdict)
|
|
);
|
|
return response;
|
|
}
|
|
|
|
///
|
|
/// @brief Finalizes an irrelevant response by setting the verdict to accept.
|
|
///
|
|
/// @param attachment Pointer to the NanoAttachment struct representing the attachment.
|
|
/// @param session_id The session ID associated with the attachment.
|
|
/// @return An AttachmentVerdictResponse struct containing the session ID and verdict.
|
|
///
|
|
static AttachmentVerdictResponse
|
|
FinalizeIrrelevantResponse(NanoAttachment *attachment, SessionID session_id)
|
|
{
|
|
AttachmentVerdictResponse response = {
|
|
.verdict = ATTACHMENT_VERDICT_ACCEPT,
|
|
.session_id = session_id,
|
|
.web_response_data = NULL,
|
|
.modifications = NULL
|
|
};
|
|
|
|
updateMetricField(attachment, IRRELEVANT_VERDICTS_COUNT, 1);
|
|
|
|
write_dbg(
|
|
attachment,
|
|
response.session_id,
|
|
DBG_LEVEL_TRACE,
|
|
"Finalizing irrelevant response to Session id: %d",
|
|
response.session_id
|
|
);
|
|
return response;
|
|
}
|
|
|
|
///
|
|
/// @brief Finalizes a failed response by determining the verdict
|
|
/// based on the fail mode verdict associated with the attachment.
|
|
///
|
|
/// @param attachment Pointer to the NanoAttachment struct representing the attachment.
|
|
/// @param session_id The session ID associated with the attachment.
|
|
/// @param ctx Pointer to the HttpEventThreadCtx struct containing the HTTP event context.
|
|
/// @return An AttachmentVerdictResponse struct containing the session ID and verdict.
|
|
///
|
|
static AttachmentVerdictResponse
|
|
FinalizeFailedResponse(NanoAttachment *attachment, SessionID session_id, HttpEventThreadCtx *ctx)
|
|
{
|
|
AttachmentVerdictResponse response = {
|
|
.session_id = session_id,
|
|
.web_response_data = NULL,
|
|
.modifications = NULL
|
|
};
|
|
|
|
if (attachment->fail_mode_verdict == NANO_OK) {
|
|
updateMetricField(attachment, INSPECTION_OPEN_FAILURES_COUNT, 1);
|
|
response.verdict = ATTACHMENT_VERDICT_ACCEPT;
|
|
ctx->session_data_p->verdict = TRAFFIC_VERDICT_ACCEPT;
|
|
} else {
|
|
updateMetricField(attachment, INSPECTION_CLOSE_FAILURES_COUNT, 1);
|
|
response.verdict = ATTACHMENT_VERDICT_DROP;
|
|
ctx->session_data_p->verdict = TRAFFIC_VERDICT_DROP;
|
|
response.web_response_data = CreateDefaultBlockPage(attachment, session_id);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
response.session_id,
|
|
DBG_LEVEL_TRACE,
|
|
"Handling Failure with fail %s mode",
|
|
response.verdict == ATTACHMENT_VERDICT_ACCEPT ? "open" : "close"
|
|
);
|
|
return response;
|
|
}
|
|
|
|
AttachmentVerdictResponse
|
|
SendRequestFilter(NanoAttachment *attachment, AttachmentData *data)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
HttpSessionData *session_data_p = data->session_data;
|
|
SessionID session_id = session_data_p->session_id;
|
|
int res;
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Request filter handling session ID: %d",
|
|
session_id
|
|
);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
return SendCorruptMemoryVerdict(attachment, session_data_p);
|
|
}
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendRequestFilterThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendRequestFilterThread,
|
|
(void *)&ctx,
|
|
attachment->req_header_thread_timeout_msec,
|
|
"SendRequestFilterThread",
|
|
REQUEST
|
|
);
|
|
|
|
if (!res) {
|
|
updateMetricField(attachment, REQ_METADATA_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendMetadataThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
|
|
if (ctx.res == NANO_DECLINED) {
|
|
return FinalizeIrrelevantResponse(attachment, session_id);
|
|
}
|
|
|
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
|
return FinalizeFailedResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
return FinalizeSuccessfulResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
AttachmentVerdictResponse
|
|
SendMetadata(NanoAttachment *attachment, AttachmentData *data)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
HttpSessionData *session_data_p = data->session_data;
|
|
SessionID session_id = session_data_p->session_id;
|
|
int res;
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Request start handling session ID: %d",
|
|
session_id
|
|
);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
return SendCorruptMemoryVerdict(attachment, session_data_p);
|
|
}
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendMetadataThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendMetadataThread,
|
|
(void *)&ctx,
|
|
attachment->req_start_thread_timeout_msec,
|
|
"SendMetadataThread",
|
|
REQUEST
|
|
);
|
|
|
|
if (!res) {
|
|
updateMetricField(attachment, REQ_METADATA_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendMetadataThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
|
|
if (ctx.res == NANO_DECLINED) {
|
|
return FinalizeIrrelevantResponse(attachment, session_id);
|
|
}
|
|
|
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
|
return FinalizeFailedResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
return FinalizeSuccessfulResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
AttachmentVerdictResponse
|
|
SendRequestHeaders(NanoAttachment *attachment, AttachmentData *data)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
HttpSessionData *session_data_p = data->session_data;
|
|
SessionID session_id = session_data_p->session_id;
|
|
int res;
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Request header handling session ID: %d",
|
|
session_id
|
|
);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
return SendCorruptMemoryVerdict(attachment, session_data_p);
|
|
}
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendRequestHeadersThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendRequestHeadersThread,
|
|
(void *)&ctx,
|
|
attachment->req_header_thread_timeout_msec,
|
|
"SendRequestHeadersThread",
|
|
REQUEST
|
|
);
|
|
|
|
if (!res) {
|
|
updateMetricField(attachment, REQ_HEADER_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendRequestHeadersThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
|
|
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendDelayedVerdictRequestThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendDelayedVerdictRequestThread,
|
|
(void *)&ctx,
|
|
attachment->waiting_for_verdict_thread_timeout_msec,
|
|
"SendDelayedVerdictRequestThread",
|
|
REQUEST
|
|
);
|
|
if (!res) {
|
|
updateMetricField(attachment, HOLD_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendDelayedVerdictRequestThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
}
|
|
|
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
|
return FinalizeFailedResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
return FinalizeSuccessfulResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
AttachmentVerdictResponse
|
|
SendResponseHeaders(NanoAttachment *attachment, AttachmentData *data)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
HttpSessionData *session_data_p = data->session_data;
|
|
SessionID session_id = session_data_p->session_id;
|
|
int res;
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Response header handling session ID: %d",
|
|
session_id
|
|
);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
return SendCorruptMemoryVerdict(attachment, session_data_p);
|
|
}
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendResponseHeadersThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendResponseHeadersThread,
|
|
(void *)&ctx,
|
|
attachment->res_header_thread_timeout_msec,
|
|
"SendResponseHeadersThread",
|
|
RESPONSE
|
|
);
|
|
|
|
if (!res) {
|
|
updateMetricField(attachment, RES_HEADER_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendResponseHeadersThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
|
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
|
return FinalizeFailedResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
return FinalizeSuccessfulResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
AttachmentVerdictResponse
|
|
SendRequestBody(NanoAttachment *attachment, AttachmentData *data)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
HttpSessionData *session_data_p = data->session_data;
|
|
SessionID session_id = session_data_p->session_id;
|
|
int res;
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "Request body handling session ID: %d", session_id);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
return SendCorruptMemoryVerdict(attachment, session_data_p);
|
|
}
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendRequestBodyThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendRequestBodyThread,
|
|
(void *)&ctx,
|
|
attachment->req_body_thread_timeout_msec,
|
|
"SendRequestBodyThread",
|
|
REQUEST
|
|
);
|
|
|
|
if (!res) {
|
|
updateMetricField(attachment, REQ_BODY_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendRequestBodyThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
|
|
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendDelayedVerdictRequestThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendDelayedVerdictRequestThread,
|
|
(void *)&ctx,
|
|
attachment->waiting_for_verdict_thread_timeout_msec,
|
|
"SendDelayedVerdictRequestThread",
|
|
REQUEST
|
|
);
|
|
if (!res) {
|
|
updateMetricField(attachment, HOLD_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendDelayedVerdictRequestThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
}
|
|
|
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
|
return FinalizeFailedResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
return FinalizeSuccessfulResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
AttachmentVerdictResponse
|
|
SendResponseBody(NanoAttachment *attachment, AttachmentData *data)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
HttpSessionData *session_data_p = data->session_data;
|
|
SessionID session_id = session_data_p->session_id;
|
|
int res;
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "Response body handling session ID: %d", session_id);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
return SendCorruptMemoryVerdict(attachment, session_data_p);
|
|
}
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendResponseBodyThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendResponseBodyThread,
|
|
(void *)&ctx,
|
|
attachment->res_body_thread_timeout_msec,
|
|
"SendResponseBodyThread",
|
|
RESPONSE
|
|
);
|
|
|
|
if (!res) {
|
|
updateMetricField(attachment, RES_BODY_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendResponseBodyThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
|
|
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendDelayedVerdictRequestThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendDelayedVerdictRequestThread,
|
|
(void *)&ctx,
|
|
attachment->waiting_for_verdict_thread_timeout_msec,
|
|
"SendDelayedVerdictRequestThread",
|
|
RESPONSE
|
|
);
|
|
if (!res) {
|
|
updateMetricField(attachment, HOLD_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendDelayedVerdictRequestThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
}
|
|
|
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
|
return FinalizeFailedResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
return FinalizeSuccessfulResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
AttachmentVerdictResponse
|
|
SendRequestEnd(NanoAttachment *attachment, AttachmentData *data)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
HttpSessionData *session_data_p = data->session_data;
|
|
SessionID session_id = session_data_p->session_id;
|
|
int res;
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Request end handling session ID: %d",
|
|
session_id
|
|
);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
return SendCorruptMemoryVerdict(attachment, session_data_p);
|
|
}
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendRequestEndThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendRequestEndThread,
|
|
(void *)&ctx,
|
|
attachment->req_header_thread_timeout_msec,
|
|
"SendRequestEndThread",
|
|
REQUEST
|
|
);
|
|
|
|
if (!res) {
|
|
updateMetricField(attachment, REQ_END_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendRequestEndThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
|
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
|
return FinalizeFailedResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
return FinalizeSuccessfulResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
AttachmentVerdictResponse
|
|
SendResponseEnd(NanoAttachment *attachment, AttachmentData *data)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
HttpSessionData *session_data_p = data->session_data;
|
|
SessionID session_id = session_data_p->session_id;
|
|
int res;
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"Response end handling session ID: %d",
|
|
session_id
|
|
);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
return SendCorruptMemoryVerdict(attachment, session_data_p);
|
|
}
|
|
|
|
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendResponseEndThread");
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
data,
|
|
SendResponseEndThread,
|
|
(void *)&ctx,
|
|
attachment->req_header_thread_timeout_msec,
|
|
"SendResponseEndThread",
|
|
RESPONSE
|
|
);
|
|
|
|
if (!res) {
|
|
updateMetricField(attachment, RES_END_THREAD_TIMEOUT, 1);
|
|
return SendThreadTimeoutVerdict(attachment, session_id, &ctx);
|
|
}
|
|
|
|
write_dbg(
|
|
attachment,
|
|
session_id,
|
|
DBG_LEVEL_DEBUG,
|
|
"finished SendResponseEndThread successfully. res=%d",
|
|
ctx.res
|
|
);
|
|
|
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
|
return FinalizeFailedResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
return FinalizeSuccessfulResponse(attachment, session_id, &ctx);
|
|
}
|
|
|
|
NanoCommunicationResult
|
|
SendMetricData(NanoAttachment *attachment)
|
|
{
|
|
HttpEventThreadCtx ctx;
|
|
int res;
|
|
|
|
write_dbg(
|
|
attachment,
|
|
0,
|
|
DBG_LEVEL_DEBUG,
|
|
"Sending metric data saved in worker ID: %d",
|
|
attachment->worker_id
|
|
);
|
|
|
|
if (handle_shmem_corruption(attachment) == NANO_ERROR) {
|
|
write_dbg(
|
|
attachment,
|
|
0,
|
|
DBG_LEVEL_DEBUG,
|
|
"Failed to send metric data, shmem corruption Worker ID: %d",
|
|
attachment->worker_id
|
|
);
|
|
return NANO_ERROR;
|
|
}
|
|
|
|
res = NanoRunInThreadTimeout(
|
|
attachment,
|
|
NULL,
|
|
SendMetricToServiceThread,
|
|
(void *)&ctx,
|
|
attachment->metric_timeout_timeout,
|
|
"SendMetricToServiceThread",
|
|
METRICS
|
|
);
|
|
|
|
if (!res) {
|
|
write_dbg(
|
|
attachment,
|
|
0,
|
|
DBG_LEVEL_DEBUG,
|
|
"Thread timeout while sending metric data from worker ID: %d",
|
|
attachment->worker_id
|
|
);
|
|
return NANO_ERROR;
|
|
}
|
|
|
|
return NANO_OK;
|
|
}
|