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 (#52)
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_body_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->inspection_mode = NON_BLOCKING_THREAD;
|
||||
attachment->num_of_nano_ipc_elements = 200;
|
||||
|
||||
@@ -291,6 +291,70 @@ FinalizeFailedResponse(NanoAttachment *attachment, SessionID session_id, HttpEve
|
||||
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
|
||||
SendRequestFilter(NanoAttachment *attachment, AttachmentData *data)
|
||||
{
|
||||
@@ -446,28 +510,9 @@ SendRequestHeaders(NanoAttachment *attachment, AttachmentData *data)
|
||||
);
|
||||
|
||||
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);
|
||||
if (HandleDelayedVerdict(attachment, data, session_id, &ctx, REQUEST)) {
|
||||
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) {
|
||||
@@ -567,28 +612,9 @@ SendRequestBody(NanoAttachment *attachment, AttachmentData *data)
|
||||
);
|
||||
|
||||
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);
|
||||
if (HandleDelayedVerdict(attachment, data, session_id, &ctx, REQUEST)) {
|
||||
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) {
|
||||
@@ -637,28 +663,9 @@ SendResponseBody(NanoAttachment *attachment, AttachmentData *data)
|
||||
);
|
||||
|
||||
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);
|
||||
if (HandleDelayedVerdict(attachment, data, session_id, &ctx, RESPONSE)) {
|
||||
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) {
|
||||
@@ -713,28 +720,9 @@ SendRequestEnd(NanoAttachment *attachment, AttachmentData *data)
|
||||
);
|
||||
|
||||
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);
|
||||
if (HandleDelayedVerdict(attachment, data, session_id, &ctx, REQUEST)) {
|
||||
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) {
|
||||
|
||||
@@ -155,6 +155,18 @@ getWaitingForVerdictThreadTimeout()
|
||||
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
|
||||
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_body_thread_timeout_msec = getResBodyThreadTimeout();
|
||||
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->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 body thread timeout: %u msec, "
|
||||
"delayed thread timeout: %u msec, "
|
||||
"hold verdict retries: %u, "
|
||||
"hold verdict polling time: %u msec, "
|
||||
"static resources path: %s, "
|
||||
"num of nginx ipc elements: %u, "
|
||||
"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_body_thread_timeout_msec,
|
||||
attachment->waiting_for_verdict_thread_timeout_msec,
|
||||
attachment->hold_verdict_retries,
|
||||
attachment->hold_verdict_polling_time,
|
||||
getStaticResourcesPath(),
|
||||
attachment->num_of_nano_ipc_elements,
|
||||
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_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 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.
|
||||
NanoHttpInspectionMode inspection_mode; ///< Default inspection mode.
|
||||
unsigned int num_of_nano_ipc_elements; ///< Number of NANO IPC elements.
|
||||
|
||||
@@ -56,6 +56,8 @@ unsigned int getResHeaderThreadTimeout();
|
||||
unsigned int getResBodyThreadTimeout();
|
||||
|
||||
unsigned int getWaitingForVerdictThreadTimeout();
|
||||
unsigned int getHoldVerdictRetries();
|
||||
unsigned int getHoldVerdictPollingTime();
|
||||
|
||||
int isIPAddress(c_str ip_str);
|
||||
int isSkipSource(c_str ip_str);
|
||||
|
||||
Reference in New Issue
Block a user