mirror of
https://github.com/openappsec/attachment.git
synced 2025-12-31 05:39:07 +03:00
Refactor delayed verdict handling and add configurable retries
Extract HandleDelayedVerdict() to eliminate duplication and make retry count and polling time configurable. Add delayed verdict handling to SendRequestEnd with unit tests.
This commit is contained in:
@@ -89,6 +89,8 @@ InitNanoAttachment(uint8_t attachment_type, int worker_id, int num_of_workers, i
|
|||||||
attachment->res_header_thread_timeout_msec = 100;
|
attachment->res_header_thread_timeout_msec = 100;
|
||||||
attachment->res_body_thread_timeout_msec = 150;
|
attachment->res_body_thread_timeout_msec = 150;
|
||||||
attachment->waiting_for_verdict_thread_timeout_msec = 150;
|
attachment->waiting_for_verdict_thread_timeout_msec = 150;
|
||||||
|
attachment->hold_verdict_retries = 10;
|
||||||
|
attachment->hold_verdict_polling_time = 1;
|
||||||
attachment->metric_timeout_timeout = 100;
|
attachment->metric_timeout_timeout = 100;
|
||||||
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;
|
||||||
|
|||||||
@@ -291,6 +291,70 @@ FinalizeFailedResponse(NanoAttachment *attachment, SessionID session_id, HttpEve
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// @brief Handles delayed verdict by spawning SendDelayedVerdictRequestThread and waiting for the verdict.
|
||||||
|
///
|
||||||
|
/// @param attachment Pointer to the NanoAttachment struct representing the attachment.
|
||||||
|
/// @param data Pointer to the AttachmentData struct containing the attachment data.
|
||||||
|
/// @param session_id The session ID associated with the attachment.
|
||||||
|
/// @param ctx Pointer to the HttpEventThreadCtx struct containing the HTTP event context.
|
||||||
|
/// @param transaction_type The transaction type (REQUEST or RESPONSE).
|
||||||
|
/// @return 1 if timeout occurred (caller should handle timeout response), 0 if successful (continue processing).
|
||||||
|
///
|
||||||
|
static int
|
||||||
|
HandleDelayedVerdict(
|
||||||
|
NanoAttachment *attachment,
|
||||||
|
AttachmentData *data,
|
||||||
|
SessionID session_id,
|
||||||
|
HttpEventThreadCtx *ctx,
|
||||||
|
TransactionType transaction_type
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
for (i = 0; i < attachment->hold_verdict_retries; i++) {
|
||||||
|
sleep(attachment->hold_verdict_polling_time);
|
||||||
|
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",
|
||||||
|
transaction_type
|
||||||
|
);
|
||||||
|
if (!res) {
|
||||||
|
updateMetricField(attachment, HOLD_THREAD_TIMEOUT, 1);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
write_dbg(
|
||||||
|
attachment,
|
||||||
|
session_id,
|
||||||
|
DBG_LEVEL_DEBUG,
|
||||||
|
"finished SendDelayedVerdictRequestThread successfully. res=%d",
|
||||||
|
ctx->res
|
||||||
|
);
|
||||||
|
|
||||||
|
if (ctx->session_data_p->verdict != TRAFFIC_VERDICT_DELAYED) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
write_dbg(
|
||||||
|
attachment,
|
||||||
|
session_id,
|
||||||
|
DBG_LEVEL_WARNING,
|
||||||
|
"SendDelayedVerdictRequestThread timed out after %d retries",
|
||||||
|
attachment->hold_verdict_retries
|
||||||
|
);
|
||||||
|
|
||||||
|
ctx->res = NANO_ERROR;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
AttachmentVerdictResponse
|
AttachmentVerdictResponse
|
||||||
SendRequestFilter(NanoAttachment *attachment, AttachmentData *data)
|
SendRequestFilter(NanoAttachment *attachment, AttachmentData *data)
|
||||||
{
|
{
|
||||||
@@ -446,28 +510,9 @@ SendRequestHeaders(NanoAttachment *attachment, AttachmentData *data)
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
||||||
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendDelayedVerdictRequestThread");
|
if (HandleDelayedVerdict(attachment, data, session_id, &ctx, REQUEST)) {
|
||||||
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);
|
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) {
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
||||||
@@ -567,28 +612,9 @@ SendRequestBody(NanoAttachment *attachment, AttachmentData *data)
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
||||||
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendDelayedVerdictRequestThread");
|
if (HandleDelayedVerdict(attachment, data, session_id, &ctx, REQUEST)) {
|
||||||
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);
|
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) {
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
||||||
@@ -637,28 +663,9 @@ SendResponseBody(NanoAttachment *attachment, AttachmentData *data)
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
||||||
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendDelayedVerdictRequestThread");
|
if (HandleDelayedVerdict(attachment, data, session_id, &ctx, RESPONSE)) {
|
||||||
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);
|
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) {
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
||||||
@@ -713,28 +720,9 @@ SendRequestEnd(NanoAttachment *attachment, AttachmentData *data)
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
if (session_data_p->verdict == TRAFFIC_VERDICT_DELAYED) {
|
||||||
write_dbg(attachment, session_id, DBG_LEVEL_DEBUG, "spawn SendDelayedVerdictRequestThread");
|
if (HandleDelayedVerdict(attachment, data, session_id, &ctx, REQUEST)) {
|
||||||
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);
|
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) {
|
if (ctx.res != NANO_HTTP_FORBIDDEN && ctx.res != NANO_OK) {
|
||||||
|
|||||||
@@ -155,6 +155,18 @@ getWaitingForVerdictThreadTimeout()
|
|||||||
return conf_data.getNumericalValue("waiting_for_verdict_thread_timeout_msec");
|
return conf_data.getNumericalValue("waiting_for_verdict_thread_timeout_msec");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
getHoldVerdictRetries()
|
||||||
|
{
|
||||||
|
return conf_data.getNumericalValue("hold_verdict_retries");
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int
|
||||||
|
getHoldVerdictPollingTime()
|
||||||
|
{
|
||||||
|
return conf_data.getNumericalValue("hold_verdict_polling_time");
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
isIPAddress(c_str ip_str)
|
isIPAddress(c_str ip_str)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ init_attachment_config(NanoAttachment *attachment, const char *conf_path)
|
|||||||
attachment->res_header_thread_timeout_msec = getResHeaderThreadTimeout();
|
attachment->res_header_thread_timeout_msec = getResHeaderThreadTimeout();
|
||||||
attachment->res_body_thread_timeout_msec = getResBodyThreadTimeout();
|
attachment->res_body_thread_timeout_msec = getResBodyThreadTimeout();
|
||||||
attachment->waiting_for_verdict_thread_timeout_msec = getWaitingForVerdictThreadTimeout();
|
attachment->waiting_for_verdict_thread_timeout_msec = getWaitingForVerdictThreadTimeout();
|
||||||
|
attachment->hold_verdict_retries = getHoldVerdictRetries();
|
||||||
|
attachment->hold_verdict_polling_time = getHoldVerdictPollingTime();
|
||||||
|
|
||||||
attachment->num_of_nano_ipc_elements = getNumOfNginxIpcElements();
|
attachment->num_of_nano_ipc_elements = getNumOfNginxIpcElements();
|
||||||
attachment->keep_alive_interval_msec = getKeepAliveIntervalMsec();
|
attachment->keep_alive_interval_msec = getKeepAliveIntervalMsec();
|
||||||
@@ -105,6 +107,8 @@ init_attachment_config(NanoAttachment *attachment, const char *conf_path)
|
|||||||
"res header thread timeout: %u msec, "
|
"res header thread timeout: %u msec, "
|
||||||
"res body thread timeout: %u msec, "
|
"res body thread timeout: %u msec, "
|
||||||
"delayed thread timeout: %u msec, "
|
"delayed thread timeout: %u msec, "
|
||||||
|
"hold verdict retries: %u, "
|
||||||
|
"hold verdict polling time: %u msec, "
|
||||||
"static resources path: %s, "
|
"static resources path: %s, "
|
||||||
"num of nginx ipc elements: %u, "
|
"num of nginx ipc elements: %u, "
|
||||||
"keep alive interval msec: %u msec",
|
"keep alive interval msec: %u msec",
|
||||||
@@ -125,6 +129,8 @@ init_attachment_config(NanoAttachment *attachment, const char *conf_path)
|
|||||||
attachment->res_header_thread_timeout_msec,
|
attachment->res_header_thread_timeout_msec,
|
||||||
attachment->res_body_thread_timeout_msec,
|
attachment->res_body_thread_timeout_msec,
|
||||||
attachment->waiting_for_verdict_thread_timeout_msec,
|
attachment->waiting_for_verdict_thread_timeout_msec,
|
||||||
|
attachment->hold_verdict_retries,
|
||||||
|
attachment->hold_verdict_polling_time,
|
||||||
getStaticResourcesPath(),
|
getStaticResourcesPath(),
|
||||||
attachment->num_of_nano_ipc_elements,
|
attachment->num_of_nano_ipc_elements,
|
||||||
attachment->keep_alive_interval_msec
|
attachment->keep_alive_interval_msec
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ typedef struct NanoAttachment {
|
|||||||
unsigned int res_header_thread_timeout_msec; ///< Response header processing timeout in milliseconds.
|
unsigned int res_header_thread_timeout_msec; ///< Response header processing timeout in milliseconds.
|
||||||
unsigned int res_body_thread_timeout_msec; ///< Response body processing timeout in milliseconds.
|
unsigned int res_body_thread_timeout_msec; ///< Response body processing timeout in milliseconds.
|
||||||
unsigned int waiting_for_verdict_thread_timeout_msec; ///< Wait thread processing timeout in milliseconds.
|
unsigned int waiting_for_verdict_thread_timeout_msec; ///< Wait thread processing timeout in milliseconds.
|
||||||
|
unsigned int hold_verdict_retries; ///< Number of retries when handling delayed verdict.
|
||||||
|
unsigned int hold_verdict_polling_time; ///< Polling time in milliseconds between retries when handling delayed verdict.
|
||||||
unsigned int metric_timeout_timeout; ///< Metric timeout in milliseconds.
|
unsigned int metric_timeout_timeout; ///< Metric timeout in milliseconds.
|
||||||
NanoHttpInspectionMode inspection_mode; ///< Default inspection mode.
|
NanoHttpInspectionMode inspection_mode; ///< Default inspection mode.
|
||||||
unsigned int num_of_nano_ipc_elements; ///< Number of NANO IPC elements.
|
unsigned int num_of_nano_ipc_elements; ///< Number of NANO IPC elements.
|
||||||
|
|||||||
@@ -56,6 +56,8 @@ unsigned int getResHeaderThreadTimeout();
|
|||||||
unsigned int getResBodyThreadTimeout();
|
unsigned int getResBodyThreadTimeout();
|
||||||
|
|
||||||
unsigned int getWaitingForVerdictThreadTimeout();
|
unsigned int getWaitingForVerdictThreadTimeout();
|
||||||
|
unsigned int getHoldVerdictRetries();
|
||||||
|
unsigned int getHoldVerdictPollingTime();
|
||||||
|
|
||||||
int isIPAddress(c_str ip_str);
|
int isIPAddress(c_str ip_str);
|
||||||
int isSkipSource(c_str ip_str);
|
int isSkipSource(c_str ip_str);
|
||||||
|
|||||||
Reference in New Issue
Block a user