From 622476c47d2d201b888f84e25be7bb273e40036b Mon Sep 17 00:00:00 2001 From: Philippe Antoine Date: Tue, 13 May 2025 15:11:57 +0200 Subject: [PATCH] http1: use a tx iterator Better performance than the defaut iterator as we do not need to read all first elements every time --- rust/htp/src/c_api/connection_parser.rs | 15 +++++++++++++ rust/htp/src/c_api/transaction.rs | 11 +++++++++ rust/htp/src/connection_parser.rs | 5 +++++ rust/htp/src/transactions.rs | 8 +++++++ src/app-layer-htp.c | 30 ++++++++++++++++++++++++- 5 files changed, 68 insertions(+), 1 deletion(-) diff --git a/rust/htp/src/c_api/connection_parser.rs b/rust/htp/src/c_api/connection_parser.rs index 017e67d5e7..5afcc18f05 100644 --- a/rust/htp/src/c_api/connection_parser.rs +++ b/rust/htp/src/c_api/connection_parser.rs @@ -219,6 +219,21 @@ pub unsafe extern "C" fn htp_connp_tx_size(connp: *const ConnectionParser) -> is .unwrap_or(-1) } +/// Get a transaction by its index for the iterator. +/// # Safety +/// When calling this method, you have to ensure that connp is either properly initialized or NULL +#[no_mangle] +pub unsafe extern "C" fn htp_connp_tx_index( + connp: *mut ConnectionParser, index: usize, +) -> *mut Transaction { + if let Some(tx) = connp.as_mut().unwrap().tx_index(index) { + if tx.is_started() { + return tx as *mut Transaction; + } + } + std::ptr::null_mut() +} + /// Get a transaction. /// /// Returns the transaction or NULL on error. diff --git a/rust/htp/src/c_api/transaction.rs b/rust/htp/src/c_api/transaction.rs index a06f4d556e..6b2511fbf1 100644 --- a/rust/htp/src/c_api/transaction.rs +++ b/rust/htp/src/c_api/transaction.rs @@ -437,6 +437,17 @@ pub unsafe extern "C" fn htp_tx_flags(tx: *const Transaction) -> u64 { tx.as_ref().map(|tx| tx.flags).unwrap_or(0) } +/// Get the transaction's index. +/// +/// tx: Transaction pointer. +/// +/// # Safety +/// When calling this method, you have to ensure that tx is either properly initialized or NULL +#[no_mangle] +pub unsafe extern "C" fn htp_tx_index(tx: *const Transaction) -> usize { + tx.as_ref().map(|tx| tx.index).unwrap_or(0) +} + /// Get the transaction's request progress. /// /// tx: Transaction pointer. diff --git a/rust/htp/src/connection_parser.rs b/rust/htp/src/connection_parser.rs index 90c172c225..d92ebe2b35 100644 --- a/rust/htp/src/connection_parser.rs +++ b/rust/htp/src/connection_parser.rs @@ -462,6 +462,11 @@ impl ConnectionParser { self.transactions.get(index) } + /// Get a specific transaction by its index + pub(crate) fn tx_index(&mut self, index: usize) -> Option<&mut Transaction> { + self.transactions.get_index(index) + } + /// Get a specific transaction pub(crate) fn tx_mut(&mut self, index: usize) -> Option<&mut Transaction> { self.transactions.get_mut(index) diff --git a/rust/htp/src/transactions.rs b/rust/htp/src/transactions.rs index 584644ffb3..f46824115c 100644 --- a/rust/htp/src/transactions.rs +++ b/rust/htp/src/transactions.rs @@ -148,4 +148,12 @@ impl Transactions { } None } + + /// Get the given transaction by index number + pub(crate) fn get_index(&mut self, index: usize) -> Option<&mut Transaction> { + if index < self.transactions.len() { + return Some(&mut self.transactions[index]); + } + None + } } diff --git a/src/app-layer-htp.c b/src/app-layer-htp.c index 9d6bdd83bc..288cd99a80 100644 --- a/src/app-layer-htp.c +++ b/src/app-layer-htp.c @@ -2482,6 +2482,34 @@ static void *HTPStateGetTx(void *alstate, uint64_t tx_id) return NULL; } +static AppLayerGetTxIterTuple HTPGetTxIterator(const uint8_t ipproto, const AppProto alproto, + void *alstate, uint64_t min_tx_id, uint64_t max_tx_id, AppLayerGetTxIterState *state) +{ + HtpState *http_state = (HtpState *)alstate; + uint64_t size = HTPStateGetTxCnt(alstate); + AppLayerGetTxIterTuple no_tuple = { NULL, 0, false }; + if (http_state) { + while (state->un.u64 < size) { + htp_tx_t *tx = htp_connp_tx_index(http_state->connp, state->un.u64); + if (!tx) { + return no_tuple; + } + uint64_t tx_id = htp_tx_index(tx); + if (tx_id < min_tx_id) { + state->un.u64++; + continue; + } + AppLayerGetTxIterTuple tuple = { + .tx_ptr = tx, + .tx_id = tx_id, + .has_next = state->un.u64 < size, + }; + return tuple; + } + } + return no_tuple; +} + void *HtpGetTxForH2(void *alstate) { // gets last transaction @@ -2612,7 +2640,7 @@ void RegisterHTPParsers(void) IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetAlstateProgress); AppLayerParserRegisterGetTxCnt(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetTxCnt); AppLayerParserRegisterGetTx(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetTx); - + AppLayerParserRegisterGetTxIterator(IPPROTO_TCP, ALPROTO_HTTP1, HTPGetTxIterator); AppLayerParserRegisterStateProgressCompletionStatus( ALPROTO_HTTP1, HTP_REQUEST_PROGRESS_COMPLETE, HTP_RESPONSE_PROGRESS_COMPLETE); AppLayerParserRegisterGetEventInfo(IPPROTO_TCP, ALPROTO_HTTP1, HTPStateGetEventInfo); -- 2.47.2