Skip to main content

i2pd_sys/
lib.rs

1//! Raw, `bindgen`-generated FFI bindings to the `i2pd-sys/shim` C shim over `libi2pd`
2//! (PurpleI2P/i2pd) — a real I2P router built in-process, not a client for a separately-running
3//! `i2pd` daemon.
4//!
5//! # What's here
6//!
7//! Every symbol in this module is generated at build time from [`shim/shim.h`][shim-h] (the
8//! *only* header `bindgen` ever runs against — never `libi2pd`'s own C++ headers, which use
9//! `std::shared_ptr`/STL types with no stable C ABI). See that file for the fully documented API
10//! surface; the short version:
11//!
12//! | Group | Functions |
13//! |---|---|
14//! | Lifecycle | [`i2pd_init`], [`i2pd_start`], [`i2pd_stop`], [`i2pd_terminate`] |
15//! | Destinations | [`i2pd_create_transient_destination`], [`i2pd_generate_keys`], [`i2pd_create_persistent_destination`], [`i2pd_destroy_destination`], [`i2pd_destination_b32_address`], [`i2pd_destination_ident_hash`], [`i2pd_accept_stream`] |
16//! | Streams | [`i2pd_create_stream`], [`i2pd_stream_send`], [`i2pd_stream_receive`], [`i2pd_stream_is_open`], [`i2pd_stream_close`], [`i2pd_destroy_stream`] |
17//! | Memory | [`i2pd_free_buffer`], [`i2pd_free_string`] |
18//!
19//! [shim-h]: https://codeberg.org/hacer-bark/i2pd-sys/src/branch/main/shim/shim.h
20//!
21//! # Example
22//!
23//! ```rust,no_run
24//! use i2pd_sys::*;
25//! use std::ffi::CString;
26//!
27//! unsafe {
28//!     let app_name = CString::new("my-app").unwrap();
29//!     i2pd_init(app_name.as_ptr()); // exactly once, before anything else
30//!     i2pd_start();
31//!
32//!     let dest = i2pd_create_transient_destination();
33//!     assert!(!dest.is_null());
34//!
35//!     // ... i2pd_accept_stream / i2pd_create_stream / i2pd_stream_send / i2pd_stream_receive ...
36//!
37//!     i2pd_destroy_destination(dest);
38//!     i2pd_stop();
39//!     i2pd_terminate();
40//! }
41//! ```
42//!
43//! # Safety
44//!
45//! This is a raw C ABI with all the usual obligations: [`i2pd_init`] must be called exactly once
46//! before any other function; every `I2pdDestination`/`I2pdStream` pointer must be destroyed
47//! exactly once (via the matching `i2pd_destroy_*`) and never used afterwards; buffers returned
48//! by [`i2pd_generate_keys`]/[`i2pd_destination_b32_address`] must be freed with
49//! [`i2pd_free_buffer`]/[`i2pd_free_string`] respectively, exactly once.
50//!
51//! [`i2pd_stream_send`] and [`i2pd_stream_receive`] *are* safe to call concurrently from
52//! different threads on the same stream (one sending, one receiving) — each posts work onto
53//! i2pd's internal `io_service` and blocks the calling thread on a condition variable, the same
54//! pattern i2pd's own SAM/BOB bridges use. The callback registered via [`i2pd_accept_stream`]
55//! runs on i2pd's own internal thread and must return quickly without blocking, or it stalls the
56//! event loop for every destination sharing that router.
57//!
58//! Every shim function catches all C++ exceptions internally, so a C++ exception can never
59//! unwind across the `extern "C"` boundary (which would be undefined behavior) — failures
60//! surface as `NULL`/`0`/`-1` return values instead, not panics or aborts.
61//!
62//! # Crypto backend: `aws-lc` (default) vs `fips`
63//!
64//! `i2pd` needs an OpenSSL-API-compatible crypto library; this crate provides one via exactly
65//! one of two backends, chosen with a priority rule rather than a hard exclusivity check:
66//!
67//! - **`aws-lc`** (default): regular [AWS-LC](https://github.com/aws/aws-lc) via `aws-lc-sys`.
68//! - **`fips`**: the FIPS-validated [AWS-LC-FIPS](https://github.com/aws/aws-lc/tree/fips-2024-09-27)
69//!   module via `aws-lc-fips-sys` instead. **`fips` wins if both end up enabled** (e.g. because a
70//!   dependent crate's own default pulled in `aws-lc` while a workspace-wide `fips` flag also
71//!   reached in here) — `aws-lc-sys` may still get compiled in that case (as an unused, inert
72//!   dependency), but `build.rs` only ever emits link directives for the `fips` backend, and
73//!   `aws-lc`/`aws-lc-fips` link with per-version-prefixed symbol names (see their own `links`
74//!   metadata), so nothing actually collides at link time. See the "FIPS" section of `README.md`
75//!   for what this does (and does not) get you, and what it costs, before reaching for it to
76//!   satisfy a compliance requirement.
77#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals, dead_code)]
78
79#[cfg(not(any(feature = "aws-lc", feature = "fips")))]
80compile_error!(
81    "no crypto backend selected -- enable exactly one of the `aws-lc` (default) or `fips` \
82     features."
83);
84
85include!(concat!(env!("OUT_DIR"), "/bindings.rs"));