mirror of
https://github.com/threefoldtech/mycelium.git
synced 2026-10-23 14:02:21 +00:00
Add safety functions to exported FFI methods
Signed-off-by: Lee Smet <lee.smet@hotmail.com>
This commit is contained in:
1 parent
9466a61c4a
commit
672c6b6b4f
4 files changed
+473
-7
No files matched your search
+245
-3
@@ -216,82 +216,324 @@ const char *mycelium_last_error_message(void);
|
||||
Start a mycelium node. Returns an opaque handle on success, or NULL on
|
||||
failure — call `mycelium_last_error_message` for details. The returned
|
||||
handle must eventually be released with `mycelium_node_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`cfg` must point to a fully-initialised `mycelium_start_config_t`.
|
||||
Pointer fields inside (`peers`, `peer_discovery_mode`,
|
||||
`peer_discovery_interfaces`, `tun_name`) follow the conventions in the
|
||||
module-level safety docs. The struct and any strings it points at are
|
||||
not retained beyond the call — the caller may free them as soon as
|
||||
this function returns.
|
||||
*/
|
||||
struct mycelium_node_t *mycelium_start(const struct mycelium_start_config_t *cfg);
|
||||
|
||||
/*
|
||||
Halt the node and release its internal resources. The handle remains
|
||||
valid for `mycelium_is_running` queries (which will return false) until
|
||||
`mycelium_node_free` is called. No-op on a NULL or already-stopped node.
|
||||
`mycelium_node_free` is called. No-op on an already-stopped node.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be NULL or a live handle returned by `mycelium_start`.
|
||||
*/
|
||||
int32_t mycelium_stop(struct mycelium_node_t *node);
|
||||
|
||||
/*
|
||||
Write `true`/`false` into `out` reflecting whether the node is running.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
point to a writable, properly aligned `bool`.
|
||||
*/
|
||||
int32_t mycelium_is_running(struct mycelium_node_t *node, bool *out);
|
||||
|
||||
/*
|
||||
Populate `out` with the node's subnet and public key. The returned
|
||||
strings are owned by the caller and must be released with
|
||||
`mycelium_node_info_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
point to a writable, properly aligned `mycelium_node_info_t`. Any
|
||||
previous contents of `*out` are overwritten without being freed —
|
||||
callers must release prior contents first or pass a fresh struct.
|
||||
*/
|
||||
int32_t mycelium_get_node_info(struct mycelium_node_t *node, struct mycelium_node_info_t *out);
|
||||
|
||||
/*
|
||||
Look up the public key of the peer that owns the given mycelium IP.
|
||||
On success writes a newly-allocated string to `*out` (empty if no
|
||||
match); release with `mycelium_string_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `ip` must
|
||||
be a NUL-terminated C string. `out` must point to a writable
|
||||
`*mut c_char`.
|
||||
*/
|
||||
int32_t mycelium_get_public_key_from_ip(struct mycelium_node_t *node, const char *ip, char **out);
|
||||
|
||||
/*
|
||||
Populate `out` with one entry per known peer. Release the array with
|
||||
`mycelium_peer_info_array_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
point to a writable, properly aligned `mycelium_peer_info_array_t`;
|
||||
any previous contents are overwritten without being freed.
|
||||
*/
|
||||
int32_t mycelium_get_peers(struct mycelium_node_t *node, struct mycelium_peer_info_array_t *out);
|
||||
|
||||
/*
|
||||
Add a peer endpoint. Writes `true` to `*out` if the peer was newly
|
||||
added, `false` if it was already known.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `endpoint`
|
||||
must be a NUL-terminated C string. `out` must point to a writable
|
||||
`bool`.
|
||||
*/
|
||||
int32_t mycelium_add_peer(struct mycelium_node_t *node, const char *endpoint, bool *out);
|
||||
|
||||
/*
|
||||
Remove a peer endpoint. Writes `true` to `*out` if the peer existed
|
||||
and was removed, `false` if no such peer was registered.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `endpoint`
|
||||
must be a NUL-terminated C string. `out` must point to a writable
|
||||
`bool`.
|
||||
*/
|
||||
int32_t mycelium_remove_peer(struct mycelium_node_t *node, const char *endpoint, bool *out);
|
||||
|
||||
/*
|
||||
Populate `out` with the currently selected (in-use) routes. Release
|
||||
the array with `mycelium_route_array_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
point to a writable, properly aligned `mycelium_route_array_t`; any
|
||||
previous contents are overwritten without being freed.
|
||||
*/
|
||||
int32_t mycelium_get_selected_routes(struct mycelium_node_t *node,
|
||||
struct mycelium_route_array_t *out);
|
||||
|
||||
/*
|
||||
Populate `out` with the routing table's fallback (non-selected) routes.
|
||||
Release the array with `mycelium_route_array_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
point to a writable, properly aligned `mycelium_route_array_t`; any
|
||||
previous contents are overwritten without being freed.
|
||||
*/
|
||||
int32_t mycelium_get_fallback_routes(struct mycelium_node_t *node,
|
||||
struct mycelium_route_array_t *out);
|
||||
|
||||
/*
|
||||
Populate `out` with subnets the router is currently querying. Release
|
||||
the array with `mycelium_queried_subnet_array_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
point to a writable, properly aligned `mycelium_queried_subnet_array_t`;
|
||||
any previous contents are overwritten without being freed.
|
||||
*/
|
||||
int32_t mycelium_get_queried_subnets(struct mycelium_node_t *node,
|
||||
struct mycelium_queried_subnet_array_t *out);
|
||||
|
||||
/*
|
||||
Populate `out` with aggregated packet statistics. Release with
|
||||
`mycelium_packet_stats_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
point to a writable, properly aligned `mycelium_packet_stats_t`; any
|
||||
previous contents are overwritten without being freed.
|
||||
*/
|
||||
int32_t mycelium_get_packet_stats(struct mycelium_node_t *node,
|
||||
struct mycelium_packet_stats_t *out);
|
||||
|
||||
/*
|
||||
Generate a fresh 32-byte node secret key into `out`. Stateless — no
|
||||
node handle required.
|
||||
|
||||
# Safety
|
||||
|
||||
`out` must point to a writable, properly aligned
|
||||
`mycelium_secret_key_t`.
|
||||
*/
|
||||
int32_t mycelium_generate_secret_key(struct mycelium_secret_key_t *out);
|
||||
|
||||
/*
|
||||
Derive the mycelium address (text form) of the public key for the
|
||||
given secret key. Writes a newly-allocated string to `*out`; release
|
||||
with `mycelium_string_free`. Stateless — no node handle required.
|
||||
|
||||
# Safety
|
||||
|
||||
`key` must point to an initialised `mycelium_secret_key_t`. `out` must
|
||||
point to a writable `*mut c_char`.
|
||||
*/
|
||||
int32_t mycelium_address_from_secret_key(const struct mycelium_secret_key_t *key, char **out);
|
||||
|
||||
/*
|
||||
Begin the periodic SOCKS5 proxy probe scan.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`.
|
||||
*/
|
||||
int32_t mycelium_start_proxy_probe(struct mycelium_node_t *node);
|
||||
|
||||
/*
|
||||
Stop the periodic SOCKS5 proxy probe scan.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`.
|
||||
*/
|
||||
int32_t mycelium_stop_proxy_probe(struct mycelium_node_t *node);
|
||||
|
||||
/*
|
||||
List the currently known SOCKS5 proxy endpoints (formatted as
|
||||
`addr:port` strings). Release with `mycelium_string_array_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
point to a writable, properly aligned `mycelium_string_array_t`; any
|
||||
previous contents are overwritten without being freed.
|
||||
*/
|
||||
int32_t mycelium_list_proxies(struct mycelium_node_t *node, struct mycelium_string_array_t *out);
|
||||
|
||||
/*
|
||||
Connect to a remote SOCKS5 proxy. Writes the negotiated remote address
|
||||
to `*out` as a newly-allocated string; release with
|
||||
`mycelium_string_free`.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`. `remote`
|
||||
must be a NUL-terminated C string. `out` must point to a writable
|
||||
`*mut c_char`.
|
||||
*/
|
||||
int32_t mycelium_proxy_connect(struct mycelium_node_t *node, const char *remote, char **out);
|
||||
|
||||
/*
|
||||
Disconnect from the currently connected SOCKS5 proxy, if any.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be a live handle returned by `mycelium_start`.
|
||||
*/
|
||||
int32_t mycelium_proxy_disconnect(struct mycelium_node_t *node);
|
||||
|
||||
/*
|
||||
Release a node handle returned by `mycelium_start`. If the node is still
|
||||
running it is stopped first. Safe to call with NULL.
|
||||
|
||||
# Safety
|
||||
|
||||
`node` must be NULL or a pointer previously returned by `mycelium_start`
|
||||
that has not already been passed to this function. Double-free or
|
||||
use-after-free is undefined behaviour.
|
||||
*/
|
||||
void mycelium_node_free(struct mycelium_node_t *node);
|
||||
|
||||
/*
|
||||
Free a single C string returned by the library. Safe to call with NULL.
|
||||
|
||||
# Safety
|
||||
|
||||
`ptr` must be NULL or a value returned by a `mycelium_*` entry point
|
||||
that hands the caller ownership of a `char *` (e.g.
|
||||
`mycelium_get_public_key_from_ip`, `mycelium_address_from_secret_key`,
|
||||
`mycelium_proxy_connect`). Strings retrieved via `mycelium_last_error_message`
|
||||
are owned by the library and must NOT be passed here.
|
||||
*/
|
||||
void mycelium_string_free(char *ptr);
|
||||
|
||||
/*
|
||||
Free a string array returned by the library. The struct itself is
|
||||
caller-allocated; this releases the contents (each item plus the array).
|
||||
Free a string array returned by the library. The outer struct is
|
||||
caller-allocated; this releases the items and the backing storage, then
|
||||
resets `items` to NULL and `len` to 0.
|
||||
|
||||
# Safety
|
||||
|
||||
`arr` must be NULL or point to a `mycelium_string_array_t` populated by
|
||||
a successful library call (currently only `mycelium_list_proxies`).
|
||||
Calling this twice on the same struct is safe — the second call sees
|
||||
`items == NULL` and does nothing.
|
||||
*/
|
||||
void mycelium_string_array_free(struct mycelium_string_array_t *arr);
|
||||
|
||||
/*
|
||||
Free a `mycelium_node_info_t` populated by `mycelium_get_node_info`.
|
||||
Releases the inner `subnet` and `pubkey` strings and resets them to
|
||||
NULL.
|
||||
|
||||
# Safety
|
||||
|
||||
`info` must be NULL or point to a struct populated by a successful call
|
||||
to `mycelium_get_node_info`. Calling this twice on the same struct is
|
||||
safe — the second call sees the fields already NULL.
|
||||
*/
|
||||
void mycelium_node_info_free(struct mycelium_node_info_t *info);
|
||||
|
||||
/*
|
||||
Free a peer-info array populated by `mycelium_get_peers`. Releases each
|
||||
item's strings, then the backing array, then resets the struct.
|
||||
|
||||
# Safety
|
||||
|
||||
`arr` must be NULL or point to a `mycelium_peer_info_array_t` populated
|
||||
by a successful call to `mycelium_get_peers`. Idempotent.
|
||||
*/
|
||||
void mycelium_peer_info_array_free(struct mycelium_peer_info_array_t *arr);
|
||||
|
||||
/*
|
||||
Free a route array populated by `mycelium_get_selected_routes` or
|
||||
`mycelium_get_fallback_routes`.
|
||||
|
||||
# Safety
|
||||
|
||||
`arr` must be NULL or point to a `mycelium_route_array_t` populated by
|
||||
a successful call to one of those two functions. Idempotent.
|
||||
*/
|
||||
void mycelium_route_array_free(struct mycelium_route_array_t *arr);
|
||||
|
||||
/*
|
||||
Free a queried-subnet array populated by `mycelium_get_queried_subnets`.
|
||||
|
||||
# Safety
|
||||
|
||||
`arr` must be NULL or point to a `mycelium_queried_subnet_array_t`
|
||||
populated by a successful call to `mycelium_get_queried_subnets`.
|
||||
Idempotent.
|
||||
*/
|
||||
void mycelium_queried_subnet_array_free(struct mycelium_queried_subnet_array_t *arr);
|
||||
|
||||
/*
|
||||
Free a `mycelium_packet_stats_t` populated by
|
||||
`mycelium_get_packet_stats`. Releases both the by-source and
|
||||
by-destination arrays.
|
||||
|
||||
# Safety
|
||||
|
||||
`stats` must be NULL or point to a `mycelium_packet_stats_t` populated
|
||||
by a successful call to `mycelium_get_packet_stats`. Idempotent.
|
||||
*/
|
||||
void mycelium_packet_stats_free(struct mycelium_packet_stats_t *stats);
|
||||
|
||||
#endif /* MYCELIUM_H */
|
||||
+141
-2
@@ -11,7 +11,6 @@
|
||||
//! the out-parameter.
|
||||
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(clippy::missing_safety_doc)]
|
||||
|
||||
use core::ffi::c_char;
|
||||
use std::ffi::CStr;
|
||||
@@ -124,6 +123,15 @@ macro_rules! with_running_node {
|
||||
/// Start a mycelium node. Returns an opaque handle on success, or NULL on
|
||||
/// failure — call `mycelium_last_error_message` for details. The returned
|
||||
/// handle must eventually be released with `mycelium_node_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `cfg` must point to a fully-initialised `mycelium_start_config_t`.
|
||||
/// Pointer fields inside (`peers`, `peer_discovery_mode`,
|
||||
/// `peer_discovery_interfaces`, `tun_name`) follow the conventions in the
|
||||
/// module-level safety docs. The struct and any strings it points at are
|
||||
/// not retained beyond the call — the caller may free them as soon as
|
||||
/// this function returns.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_start(
|
||||
cfg: *const mycelium_start_config_t,
|
||||
@@ -231,7 +239,11 @@ pub unsafe extern "C" fn mycelium_start(
|
||||
|
||||
/// Halt the node and release its internal resources. The handle remains
|
||||
/// valid for `mycelium_is_running` queries (which will return false) until
|
||||
/// `mycelium_node_free` is called. No-op on a NULL or already-stopped node.
|
||||
/// `mycelium_node_free` is called. No-op on an already-stopped node.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be NULL or a live handle returned by `mycelium_start`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_stop(node: *mut mycelium_node_t) -> i32 {
|
||||
error::clear();
|
||||
@@ -257,6 +269,11 @@ pub unsafe extern "C" fn mycelium_stop(node: *mut mycelium_node_t) -> i32 {
|
||||
}
|
||||
|
||||
/// Write `true`/`false` into `out` reflecting whether the node is running.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
/// point to a writable, properly aligned `bool`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_is_running(node: *mut mycelium_node_t, out: *mut bool) -> i32 {
|
||||
error::clear();
|
||||
@@ -279,6 +296,16 @@ pub unsafe extern "C" fn mycelium_is_running(node: *mut mycelium_node_t, out: *m
|
||||
// Identity / introspection
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Populate `out` with the node's subnet and public key. The returned
|
||||
/// strings are owned by the caller and must be released with
|
||||
/// `mycelium_node_info_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
/// point to a writable, properly aligned `mycelium_node_info_t`. Any
|
||||
/// previous contents of `*out` are overwritten without being freed —
|
||||
/// callers must release prior contents first or pass a fresh struct.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_get_node_info(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -300,6 +327,15 @@ pub unsafe extern "C" fn mycelium_get_node_info(
|
||||
})
|
||||
}
|
||||
|
||||
/// Look up the public key of the peer that owns the given mycelium IP.
|
||||
/// On success writes a newly-allocated string to `*out` (empty if no
|
||||
/// match); release with `mycelium_string_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `ip` must
|
||||
/// be a NUL-terminated C string. `out` must point to a writable
|
||||
/// `*mut c_char`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_get_public_key_from_ip(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -339,6 +375,14 @@ pub unsafe extern "C" fn mycelium_get_public_key_from_ip(
|
||||
// Peers
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Populate `out` with one entry per known peer. Release the array with
|
||||
/// `mycelium_peer_info_array_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
/// point to a writable, properly aligned `mycelium_peer_info_array_t`;
|
||||
/// any previous contents are overwritten without being freed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_get_peers(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -365,6 +409,14 @@ pub unsafe extern "C" fn mycelium_get_peers(
|
||||
})
|
||||
}
|
||||
|
||||
/// Add a peer endpoint. Writes `true` to `*out` if the peer was newly
|
||||
/// added, `false` if it was already known.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `endpoint`
|
||||
/// must be a NUL-terminated C string. `out` must point to a writable
|
||||
/// `bool`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_add_peer(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -391,6 +443,14 @@ pub unsafe extern "C" fn mycelium_add_peer(
|
||||
})
|
||||
}
|
||||
|
||||
/// Remove a peer endpoint. Writes `true` to `*out` if the peer existed
|
||||
/// and was removed, `false` if no such peer was registered.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `endpoint`
|
||||
/// must be a NUL-terminated C string. `out` must point to a writable
|
||||
/// `bool`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_remove_peer(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -421,6 +481,14 @@ pub unsafe extern "C" fn mycelium_remove_peer(
|
||||
// Routes
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Populate `out` with the currently selected (in-use) routes. Release
|
||||
/// the array with `mycelium_route_array_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
/// point to a writable, properly aligned `mycelium_route_array_t`; any
|
||||
/// previous contents are overwritten without being freed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_get_selected_routes(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -447,6 +515,14 @@ pub unsafe extern "C" fn mycelium_get_selected_routes(
|
||||
})
|
||||
}
|
||||
|
||||
/// Populate `out` with the routing table's fallback (non-selected) routes.
|
||||
/// Release the array with `mycelium_route_array_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
/// point to a writable, properly aligned `mycelium_route_array_t`; any
|
||||
/// previous contents are overwritten without being freed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_get_fallback_routes(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -473,6 +549,14 @@ pub unsafe extern "C" fn mycelium_get_fallback_routes(
|
||||
})
|
||||
}
|
||||
|
||||
/// Populate `out` with subnets the router is currently querying. Release
|
||||
/// the array with `mycelium_queried_subnet_array_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
/// point to a writable, properly aligned `mycelium_queried_subnet_array_t`;
|
||||
/// any previous contents are overwritten without being freed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_get_queried_subnets(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -508,6 +592,14 @@ pub unsafe extern "C" fn mycelium_get_queried_subnets(
|
||||
// Packet statistics
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Populate `out` with aggregated packet statistics. Release with
|
||||
/// `mycelium_packet_stats_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
/// point to a writable, properly aligned `mycelium_packet_stats_t`; any
|
||||
/// previous contents are overwritten without being freed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_get_packet_stats(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -547,6 +639,13 @@ pub unsafe extern "C" fn mycelium_get_packet_stats(
|
||||
// Key utilities (no node required)
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Generate a fresh 32-byte node secret key into `out`. Stateless — no
|
||||
/// node handle required.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `out` must point to a writable, properly aligned
|
||||
/// `mycelium_secret_key_t`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_generate_secret_key(out: *mut mycelium_secret_key_t) -> i32 {
|
||||
error::clear();
|
||||
@@ -560,6 +659,14 @@ pub unsafe extern "C" fn mycelium_generate_secret_key(out: *mut mycelium_secret_
|
||||
MYCELIUM_OK
|
||||
}
|
||||
|
||||
/// Derive the mycelium address (text form) of the public key for the
|
||||
/// given secret key. Writes a newly-allocated string to `*out`; release
|
||||
/// with `mycelium_string_free`. Stateless — no node handle required.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `key` must point to an initialised `mycelium_secret_key_t`. `out` must
|
||||
/// point to a writable `*mut c_char`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_address_from_secret_key(
|
||||
key: *const mycelium_secret_key_t,
|
||||
@@ -583,6 +690,11 @@ pub unsafe extern "C" fn mycelium_address_from_secret_key(
|
||||
// Proxy
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
/// Begin the periodic SOCKS5 proxy probe scan.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_start_proxy_probe(node: *mut mycelium_node_t) -> i32 {
|
||||
error::clear();
|
||||
@@ -594,6 +706,11 @@ pub unsafe extern "C" fn mycelium_start_proxy_probe(node: *mut mycelium_node_t)
|
||||
})
|
||||
}
|
||||
|
||||
/// Stop the periodic SOCKS5 proxy probe scan.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_stop_proxy_probe(node: *mut mycelium_node_t) -> i32 {
|
||||
error::clear();
|
||||
@@ -605,6 +722,14 @@ pub unsafe extern "C" fn mycelium_stop_proxy_probe(node: *mut mycelium_node_t) -
|
||||
})
|
||||
}
|
||||
|
||||
/// List the currently known SOCKS5 proxy endpoints (formatted as
|
||||
/// `addr:port` strings). Release with `mycelium_string_array_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `out` must
|
||||
/// point to a writable, properly aligned `mycelium_string_array_t`; any
|
||||
/// previous contents are overwritten without being freed.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_list_proxies(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -634,6 +759,15 @@ pub unsafe extern "C" fn mycelium_list_proxies(
|
||||
})
|
||||
}
|
||||
|
||||
/// Connect to a remote SOCKS5 proxy. Writes the negotiated remote address
|
||||
/// to `*out` as a newly-allocated string; release with
|
||||
/// `mycelium_string_free`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`. `remote`
|
||||
/// must be a NUL-terminated C string. `out` must point to a writable
|
||||
/// `*mut c_char`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_proxy_connect(
|
||||
node: *mut mycelium_node_t,
|
||||
@@ -672,6 +806,11 @@ pub unsafe extern "C" fn mycelium_proxy_connect(
|
||||
})
|
||||
}
|
||||
|
||||
/// Disconnect from the currently connected SOCKS5 proxy, if any.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be a live handle returned by `mycelium_start`.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_proxy_disconnect(node: *mut mycelium_node_t) -> i32 {
|
||||
error::clear();
|
||||
|
||||
@@ -8,6 +8,31 @@
|
||||
//! `mycelium_node_t *` that the caller passes back into every other entry
|
||||
//! point. Lifecycle (singleton-or-not, lifetime, threading) is the
|
||||
//! consumer's choice, not ours.
|
||||
//!
|
||||
//! # Safety conventions
|
||||
//!
|
||||
//! Common to every `extern "C"` entry point in this module; per-function
|
||||
//! `# Safety` sections only document the bits that go beyond these:
|
||||
//!
|
||||
//! - Pointer arguments are either NULL (only where the per-function doc
|
||||
//! says NULL is accepted) or valid: properly aligned, non-dangling,
|
||||
//! pointing to an initialised value of the documented type.
|
||||
//! - C string inputs (`*const c_char`) must be NUL-terminated. UTF-8 is
|
||||
//! validated at runtime; invalid bytes yield `MYCELIUM_ERR_INVALID_ARG`
|
||||
//! rather than UB.
|
||||
//! - Out-pointers must point to writable, properly aligned memory of the
|
||||
//! right type. Writes happen only on success (return code 0, or non-NULL
|
||||
//! handle from `mycelium_start`).
|
||||
//! - `mycelium_node_t *` arguments must come from `mycelium_start` and
|
||||
//! must not have been passed to `mycelium_node_free`. Use-after-free,
|
||||
//! double-free, or freeing on one thread while another thread is using
|
||||
//! the same handle is undefined behaviour.
|
||||
//! - Strings and structs that the library hands back are owned by the
|
||||
//! caller and must be released with the matching `mycelium_*_free`
|
||||
//! function. Reading the contents from multiple threads is safe; freeing
|
||||
//! must not race with reads.
|
||||
//! - The library is not async-signal safe; do not call entry points from
|
||||
//! a signal handler.
|
||||
|
||||
mod conversions;
|
||||
mod error;
|
||||
|
||||
@@ -186,6 +186,12 @@ pub(super) unsafe fn drain_array<T>(ptr: *mut T, len: usize) -> Vec<T> {
|
||||
|
||||
/// Release a node handle returned by `mycelium_start`. If the node is still
|
||||
/// running it is stopped first. Safe to call with NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `node` must be NULL or a pointer previously returned by `mycelium_start`
|
||||
/// that has not already been passed to this function. Double-free or
|
||||
/// use-after-free is undefined behaviour.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_node_free(node: *mut mycelium_node_t) {
|
||||
if node.is_null() {
|
||||
@@ -195,13 +201,29 @@ pub unsafe extern "C" fn mycelium_node_free(node: *mut mycelium_node_t) {
|
||||
}
|
||||
|
||||
/// Free a single C string returned by the library. Safe to call with NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `ptr` must be NULL or a value returned by a `mycelium_*` entry point
|
||||
/// that hands the caller ownership of a `char *` (e.g.
|
||||
/// `mycelium_get_public_key_from_ip`, `mycelium_address_from_secret_key`,
|
||||
/// `mycelium_proxy_connect`). Strings retrieved via `mycelium_last_error_message`
|
||||
/// are owned by the library and must NOT be passed here.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_string_free(ptr: *mut c_char) {
|
||||
free_cstring(ptr);
|
||||
}
|
||||
|
||||
/// Free a string array returned by the library. The struct itself is
|
||||
/// caller-allocated; this releases the contents (each item plus the array).
|
||||
/// Free a string array returned by the library. The outer struct is
|
||||
/// caller-allocated; this releases the items and the backing storage, then
|
||||
/// resets `items` to NULL and `len` to 0.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `arr` must be NULL or point to a `mycelium_string_array_t` populated by
|
||||
/// a successful library call (currently only `mycelium_list_proxies`).
|
||||
/// Calling this twice on the same struct is safe — the second call sees
|
||||
/// `items == NULL` and does nothing.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_string_array_free(arr: *mut mycelium_string_array_t) {
|
||||
if arr.is_null() {
|
||||
@@ -215,6 +237,15 @@ pub unsafe extern "C" fn mycelium_string_array_free(arr: *mut mycelium_string_ar
|
||||
arr.len = 0;
|
||||
}
|
||||
|
||||
/// Free a `mycelium_node_info_t` populated by `mycelium_get_node_info`.
|
||||
/// Releases the inner `subnet` and `pubkey` strings and resets them to
|
||||
/// NULL.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `info` must be NULL or point to a struct populated by a successful call
|
||||
/// to `mycelium_get_node_info`. Calling this twice on the same struct is
|
||||
/// safe — the second call sees the fields already NULL.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_node_info_free(info: *mut mycelium_node_info_t) {
|
||||
if info.is_null() {
|
||||
@@ -227,6 +258,13 @@ pub unsafe extern "C" fn mycelium_node_info_free(info: *mut mycelium_node_info_t
|
||||
info.pubkey = std::ptr::null_mut();
|
||||
}
|
||||
|
||||
/// Free a peer-info array populated by `mycelium_get_peers`. Releases each
|
||||
/// item's strings, then the backing array, then resets the struct.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `arr` must be NULL or point to a `mycelium_peer_info_array_t` populated
|
||||
/// by a successful call to `mycelium_get_peers`. Idempotent.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_peer_info_array_free(arr: *mut mycelium_peer_info_array_t) {
|
||||
if arr.is_null() {
|
||||
@@ -243,6 +281,13 @@ pub unsafe extern "C" fn mycelium_peer_info_array_free(arr: *mut mycelium_peer_i
|
||||
arr.len = 0;
|
||||
}
|
||||
|
||||
/// Free a route array populated by `mycelium_get_selected_routes` or
|
||||
/// `mycelium_get_fallback_routes`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `arr` must be NULL or point to a `mycelium_route_array_t` populated by
|
||||
/// a successful call to one of those two functions. Idempotent.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_route_array_free(arr: *mut mycelium_route_array_t) {
|
||||
if arr.is_null() {
|
||||
@@ -257,6 +302,13 @@ pub unsafe extern "C" fn mycelium_route_array_free(arr: *mut mycelium_route_arra
|
||||
arr.len = 0;
|
||||
}
|
||||
|
||||
/// Free a queried-subnet array populated by `mycelium_get_queried_subnets`.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `arr` must be NULL or point to a `mycelium_queried_subnet_array_t`
|
||||
/// populated by a successful call to `mycelium_get_queried_subnets`.
|
||||
/// Idempotent.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_queried_subnet_array_free(
|
||||
arr: *mut mycelium_queried_subnet_array_t,
|
||||
@@ -278,6 +330,14 @@ unsafe fn free_packet_stat_entries(ptr: *mut mycelium_packet_stat_entry_t, len:
|
||||
}
|
||||
}
|
||||
|
||||
/// Free a `mycelium_packet_stats_t` populated by
|
||||
/// `mycelium_get_packet_stats`. Releases both the by-source and
|
||||
/// by-destination arrays.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// `stats` must be NULL or point to a `mycelium_packet_stats_t` populated
|
||||
/// by a successful call to `mycelium_get_packet_stats`. Idempotent.
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn mycelium_packet_stats_free(stats: *mut mycelium_packet_stats_t) {
|
||||
if stats.is_null() {
|
||||
|
||||
Reference in new issue
Block a user