Expand description
Raw bindgen-generated FFI bindings to a C shim over libi2pd (PurpleI2P/i2pd) — a real I2P
router built in-process, not a client for a separately-running i2pd daemon.
Everything here is generated from shim/shim.h, the only header bindgen runs against;
libi2pd’s own C++ headers use std::shared_ptr/STL types with no stable C ABI. That file
documents each function. README.md covers the build, the trimmed attack surface, network
participation, and the FIPS backend.
use i2pd_sys::*;
use std::ffi::CString;
unsafe {
let app_name = CString::new("my-app").unwrap();
i2pd_init(app_name.as_ptr()); // before anything else
i2pd_start();
let dest = i2pd_create_transient_destination();
assert!(!dest.is_null());
i2pd_destroy_destination(dest);
i2pd_stop();
i2pd_terminate();
}§Safety
i2pd_init must be called before anything else. Every I2pdDestination/I2pdStream pointer
must be destroyed exactly once via the matching i2pd_destroy_* and never used afterwards.
i2pd_free_buffer takes the length i2pd_generate_keys reported and wipes the buffer
first: it holds a private key, and plain free would leave the bytes readable in the heap.
The four lifecycle calls share one mutex held across the underlying libi2pd call, so a repeated
or out-of-order call is a no-op rather than a second pass over libi2pd’s non-reentrant globals,
and a racing caller blocks until the transition it observed has finished. terminate stops a
still-running router first.
i2pd_stream_send and i2pd_stream_receive are safe to call concurrently on the same
stream — each posts work onto i2pd’s io_service and blocks the calling thread on a condition
variable, as i2pd’s own SAM/BOB bridges do. The i2pd_accept_stream callback runs on i2pd’s
thread and must return quickly, or it stalls the event loop for every destination on the router.
Every shim function catches all C++ exceptions internally, including that callback, so nothing
unwinds across the extern "C" boundary. Failures surface as NULL/0/-1, not panics.
§Features
aws-lc (default) links AWS-LC; fips swaps in the
FIPS-validated module. fips wins if both end up enabled — build.rs emits link directives for
one backend only, and the two use per-version-prefixed symbol names, so the other is inert.
transit (default) carries other users’ tunnels. Building without it compiles the tunnel
build-request path out of libi2pd entirely, whatever the runtime settings say;
i2pd_accepts_transit reports what the build supports.
Structs§
Functions§
- i2pd_
accept_ ⚠stream - i2pd_
accepts_ ⚠transit - i2pd_
create_ ⚠persistent_ destination - i2pd_
create_ ⚠stream - i2pd_
create_ ⚠transient_ destination - i2pd_
destination_ ⚠b32_ address - i2pd_
destination_ ⚠ident_ hash - i2pd_
destroy_ ⚠destination - i2pd_
destroy_ ⚠stream - i2pd_
free_ ⚠buffer - i2pd_
free_ ⚠string - i2pd_
generate_ ⚠keys - i2pd_
init ⚠ - i2pd_
set_ ⚠accepts_ transit - i2pd_
set_ ⚠bandwidth_ limit - i2pd_
set_ ⚠floodfill - i2pd_
set_ ⚠max_ transit_ tunnels - i2pd_
set_ ⚠share_ percent - i2pd_
start ⚠ - i2pd_
stop ⚠ - i2pd_
stream_ ⚠close - i2pd_
stream_ ⚠is_ open - i2pd_
stream_ ⚠receive - i2pd_
stream_ ⚠send - i2pd_
terminate ⚠ - i2pd_
test_ ⚠mlkem_ roundtrip