Skip to main content

i2pd_sys/
lib.rs

1//! Raw `bindgen`-generated FFI bindings to a C shim over `libi2pd` (PurpleI2P/i2pd) — a real I2P
2//! router built in-process, not a client for a separately-running `i2pd` daemon.
3//!
4//! Everything here is generated from [`shim/shim.h`][shim-h], the only header bindgen runs against;
5//! libi2pd's own C++ headers use `std::shared_ptr`/STL types with no stable C ABI. That file
6//! documents each function. README.md covers the build, the trimmed attack surface, network
7//! participation, and the FIPS backend.
8//!
9//! [shim-h]: https://github.com/tachyon-web/i2pd-sys/blob/main/shim/shim.h
10//!
11//! ```rust,no_run
12//! use i2pd_sys::*;
13//! use std::ffi::CString;
14//!
15//! unsafe {
16//!     let app_name = CString::new("my-app").unwrap();
17//!     i2pd_init(app_name.as_ptr()); // before anything else
18//!     i2pd_start();
19//!
20//!     let dest = i2pd_create_transient_destination();
21//!     assert!(!dest.is_null());
22//!
23//!     i2pd_destroy_destination(dest);
24//!     i2pd_stop();
25//!     i2pd_terminate();
26//! }
27//! ```
28//!
29//! # Safety
30//!
31//! [`i2pd_init`] must be called before anything else. Every `I2pdDestination`/`I2pdStream` pointer
32//! must be destroyed exactly once via the matching `i2pd_destroy_*` and never used afterwards.
33//! [`i2pd_free_buffer`] takes the length [`i2pd_generate_keys`] reported and wipes the buffer
34//! first: it holds a private key, and plain `free` would leave the bytes readable in the heap.
35//!
36//! The four lifecycle calls share one mutex held across the underlying libi2pd call, so a repeated
37//! or out-of-order call is a no-op rather than a second pass over libi2pd's non-reentrant globals,
38//! and a racing caller blocks until the transition it observed has finished. `terminate` stops a
39//! still-running router first.
40//!
41//! [`i2pd_stream_send`] and [`i2pd_stream_receive`] *are* safe to call concurrently on the same
42//! stream — each posts work onto i2pd's `io_service` and blocks the calling thread on a condition
43//! variable, as i2pd's own SAM/BOB bridges do. The [`i2pd_accept_stream`] callback runs on i2pd's
44//! thread and must return quickly, or it stalls the event loop for every destination on the router.
45//!
46//! Every shim function catches all C++ exceptions internally, including that callback, so nothing
47//! unwinds across the `extern "C"` boundary. Failures surface as `NULL`/`0`/`-1`, not panics.
48//!
49//! # Features
50//!
51//! `aws-lc` (default) links [AWS-LC](https://github.com/aws/aws-lc); `fips` swaps in the
52//! FIPS-validated module. `fips` wins if both end up enabled — `build.rs` emits link directives for
53//! one backend only, and the two use per-version-prefixed symbol names, so the other is inert.
54//!
55//! `transit` (default) carries other users' tunnels. Building without it compiles the tunnel
56//! build-request path out of libi2pd entirely, whatever the runtime settings say;
57//! [`i2pd_accepts_transit`] reports what the build supports.
58#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals, dead_code)]
59
60#[cfg(not(any(feature = "aws-lc", feature = "fips")))]
61compile_error!(
62    "no crypto backend selected -- enable exactly one of the `aws-lc` (default) or `fips` \
63     features."
64);
65
66include!(concat!(env!("OUT_DIR"), "/bindings.rs"));