From de6e6a759897a1bbc4703c11f61fb09ffa01397a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gustavo=20Andr=C3=A9=20dos=20Santos=20Lopes?= Date: Tue, 8 Sep 2026 14:36:19 +0100 Subject: [PATCH] Add datadog_sidecar_send_appsec_message_without_reconnect --- datadog-sidecar-ffi/src/lib.rs | 38 ++++++++++++++++++++++--- datadog-sidecar/src/service/blocking.rs | 18 ++++++++++++ 2 files changed, 52 insertions(+), 4 deletions(-) diff --git a/datadog-sidecar-ffi/src/lib.rs b/datadog-sidecar-ffi/src/lib.rs index 589bcd0db1..d3f66ccf82 100644 --- a/datadog-sidecar-ffi/src/lib.rs +++ b/datadog-sidecar-ffi/src/lib.rs @@ -2064,7 +2064,7 @@ pub unsafe extern "C" fn ddog_sidecar_send_garbage(transport: &mut Box AppsecCResponse { - match blocking::send_appsec_message(transport, client_id, data.as_bytes()) { + appsec_c_response(blocking::send_appsec_message( + transport, + client_id, + data.as_bytes(), + )) +} + +/// Sends an AppSec message once, without reconnecting the sidecar on failure. +/// +/// The response is allocated by the sidecar and must be freed with +/// `ddog_sidecar_appsec_response_drop` when the caller is done with it. +/// +/// Returns a zeroed `ddog_AppsecCResponse` (null ptr) on transport errors. +#[cfg(unix)] +#[no_mangle] +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn datadog_sidecar_send_appsec_message_without_reconnect( + transport: &mut Box, + client_id: u64, + data: ffi::CharSlice, +) -> AppsecCResponse { + appsec_c_response(blocking::send_appsec_message_without_reconnect( + transport, + client_id, + data.as_bytes(), + )) +} + +#[cfg(unix)] +fn appsec_c_response(response: std::io::Result<(Vec, bool)>) -> AppsecCResponse { + match response { Ok((bytes, disconnect)) => { let mut bytes = std::mem::ManuallyDrop::new(bytes); AppsecCResponse { @@ -2111,13 +2141,13 @@ pub unsafe extern "C" fn ddog_sidecar_send_appsec_message( } } -/// Frees an `AppsecCResponse` that was returned by `ddog_sidecar_send_appsec_message`. +/// Frees an `AppsecCResponse` returned by an AppSec message function. #[cfg(unix)] #[no_mangle] pub extern "C" fn ddog_sidecar_appsec_response_drop(response: AppsecCResponse) { if !response.ptr.is_null() { // SAFETY: ptr/len/capacity were produced by ManuallyDrop in - // ddog_sidecar_send_appsec_message and use the sidecar's allocator. + // an AppSec message function and use the sidecar's allocator. unsafe { let _ = Vec::from_raw_parts(response.ptr, response.len, response.capacity); } diff --git a/datadog-sidecar/src/service/blocking.rs b/datadog-sidecar/src/service/blocking.rs index ccea36c241..a564417fb6 100644 --- a/datadog-sidecar/src/service/blocking.rs +++ b/datadog-sidecar/src/service/blocking.rs @@ -577,6 +577,24 @@ pub fn send_appsec_message( transport.with_retry(|s| s.send_appsec_message(&request).map_err(decode_error_to_io)) } +/// Forwards an AppSec message without reconnecting the sidecar on failure. +/// +/// Returns the response bytes from the helper and a disconnect flag. +pub fn send_appsec_message_without_reconnect( + transport: &mut SidecarTransport, + client_id: u64, + data: &[u8], +) -> io::Result<(Vec, bool)> { + let request = SidecarInterfaceClientRequest::SendAppsecMessage { client_id, data }; + let mut sender = transport + .inner + .lock() + .map_err(|error| io::Error::other(error.to_string()))?; + sender + .send_appsec_message(&request) + .map_err(decode_error_to_io) +} + /// Flushes traces/stats and/or telemetry, as specified by options. pub fn flush(transport: &mut SidecarTransport, options: SidecarFlushOptions) -> io::Result<()> { transport.with_retry(|s| s.flush(options))