Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 34 additions & 4 deletions datadog-sidecar-ffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2064,7 +2064,7 @@ pub unsafe extern "C" fn ddog_sidecar_send_garbage(transport: &mut Box<SidecarTr
let _ = transport.send_garbage();
}

/// Raw AppSec response returned by `ddog_sidecar_send_appsec_message`.
/// Raw AppSec response returned by the AppSec message functions.
///
/// When `ptr` is non-null, the response must be freed by calling
/// `ddog_sidecar_appsec_response_drop`.
Expand Down Expand Up @@ -2092,7 +2092,37 @@ pub unsafe extern "C" fn ddog_sidecar_send_appsec_message(
client_id: u64,
data: ffi::CharSlice,
) -> 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<SidecarTransport>,
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<u8>, bool)>) -> AppsecCResponse {
match response {
Ok((bytes, disconnect)) => {
let mut bytes = std::mem::ManuallyDrop::new(bytes);
AppsecCResponse {
Expand All @@ -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<Vec> 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);
}
Expand Down
18 changes: 18 additions & 0 deletions datadog-sidecar/src/service/blocking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<u8>, 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))
Expand Down
Loading