From 7884c711e2fec85b2336260e0f586834626129b6 Mon Sep 17 00:00:00 2001 From: Granyaa Date: Tue, 23 Dec 2025 16:01:46 +0200 Subject: [PATCH] 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. --- attachments/nano_attachment/nano_attachment.c | 2 + .../nano_attachment/nano_attachment_sender.c | 148 ++++++++---------- .../nano_attachment_util.cc | 12 ++ .../nano_attachment/nano_configuration.c | 6 + .../nano_attachment/nano_initializer.h | 2 + .../attachments/nano_attachment_util.h | 2 + 6 files changed, 92 insertions(+), 80 deletions(-) diff --git a/attachments/nano_attachment/nano_attachment.c b/attachments/nano_attachment/nano_attachment.c index 8e13cbf..dc4b240 100755 --- a/attachments/nano_attachment/nano_attachment.c +++ b/attachments/nano_attachment/nano_attachment.c @@ -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; diff --git a/attachments/nano_attachment/nano_attachment_sender.c b/attachments/nano_attachment/nano_attachment_sender.c index b9aa96d..f071674 100644 --- a/attachments/nano_attachment/nano_attachment_sender.c +++ b/attachments/nano_attachment/nano_attachment_sender.c @@ -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) { diff --git a/attachments/nano_attachment/nano_attachment_util/nano_attachment_util.cc b/attachments/nano_attachment/nano_attachment_util/nano_attachment_util.cc index a45afa5..4cf5d9e 100644 --- a/attachments/nano_attachment/nano_attachment_util/nano_attachment_util.cc +++ b/attachments/nano_attachment/nano_attachment_util/nano_attachment_util.cc @@ -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) { diff --git a/attachments/nano_attachment/nano_configuration.c b/attachments/nano_attachment/nano_configuration.c index 7f16cb6..05eb4e8 100644 --- a/attachments/nano_attachment/nano_configuration.c +++ b/attachments/nano_attachment/nano_configuration.c @@ -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 diff --git a/attachments/nano_attachment/nano_initializer.h b/attachments/nano_attachment/nano_initializer.h index f95030e..403c2ad 100644 --- a/attachments/nano_attachment/nano_initializer.h +++ b/attachments/nano_attachment/nano_initializer.h @@ -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. diff --git a/core/include/attachments/nano_attachment_util.h b/core/include/attachments/nano_attachment_util.h index 78135b8..942b5d2 100644 --- a/core/include/attachments/nano_attachment_util.h +++ b/core/include/attachments/nano_attachment_util.h @@ -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);