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_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