Expand description
§rustp2p-c-ffi - C FFI Bindings for rustp2p
This crate provides C-compatible Foreign Function Interface (FFI) bindings for the rustp2p
library, enabling integration with C, C++, and other languages that support C FFI.
§Features
- C-Compatible API: Simple, pointer-based API for C/C++ integration
- Builder Pattern: Fluent API for configuration
- Error Handling: Clear error codes for all operations
- Memory Safety: Proper ownership and cleanup functions
- Cross-Platform: Works on Windows, Linux, and macOS
§Building
This crate produces both a static library and a dynamic library:
cargo build --releaseOutput files:
librustp2p_c_ffi.a/rustp2p_c_ffi.lib(static)librustp2p_c_ffi.so/rustp2p_c_ffi.dll/librustp2p_c_ffi.dylib(dynamic)
§C Usage Example
§Basic Setup
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Create and configure a node
Rustp2pBuilder* builder = rustp2p_builder_new();
rustp2p_builder_node_id(builder, "10.0.0.1");
rustp2p_builder_udp_port(builder, 8080);
rustp2p_builder_group_code(builder, "12345");
// Build the endpoint
Rustp2pEndpoint* endpoint = rustp2p_builder_build(builder);
if (!endpoint) {
fprintf(stderr, "Failed to build endpoint\n");
return -1;
}§Sending Data
const char* message = "Hello, peer!";
int result = rustp2p_endpoint_send_to(
endpoint,
"10.0.0.2",
(const uint8_t*)message,
strlen(message)
);
if (result == RUSTP2P_OK) {
printf("Message sent successfully\n");
}§Receiving Data
// Blocking receive
Rustp2pRecvData* recv_data = rustp2p_endpoint_recv_from(endpoint);
if (recv_data) {
const uint8_t* data;
size_t len;
rustp2p_recv_data_get_payload(recv_data, &data, &len);
char src_id[16];
rustp2p_recv_data_get_src_id(recv_data, src_id, sizeof(src_id));
printf("Received %zu bytes from %s\n", len, src_id);
rustp2p_recv_data_free(recv_data);
}§Cleanup
rustp2p_endpoint_free(endpoint);§Error Codes
The library uses the following error codes:
RUSTP2P_OK(0): SuccessRUSTP2P_ERROR(-1): General errorRUSTP2P_ERROR_NULL_PTR(-2): NULL pointer providedRUSTP2P_ERROR_INVALID_STR(-3): Invalid stringRUSTP2P_ERROR_INVALID_IP(-4): Invalid IP addressRUSTP2P_ERROR_BUILD_FAILED(-5): Failed to build endpointRUSTP2P_ERROR_WOULD_BLOCK(-6): Operation would blockRUSTP2P_ERROR_EOF(-7): End of file / connection closed
§Complete C Example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
void* receive_thread(void* arg) {
Rustp2pEndpoint* endpoint = (Rustp2pEndpoint*)arg;
while (1) {
Rustp2pRecvData* recv_data = rustp2p_endpoint_recv_from(endpoint);
if (!recv_data) {
break;
}
const uint8_t* data;
size_t len;
rustp2p_recv_data_get_payload(recv_data, &data, &len);
char src_id[16];
rustp2p_recv_data_get_src_id(recv_data, src_id, sizeof(src_id));
printf("Received %zu bytes from %s: %.*s\n", len, src_id, (int)len, data);
rustp2p_recv_data_free(recv_data);
}
return NULL;
}
int main() {
// Create builder
Rustp2pBuilder* builder = rustp2p_builder_new();
if (!builder) {
return -1;
}
// Configure
rustp2p_builder_node_id(builder, "10.0.0.1");
rustp2p_builder_udp_port(builder, 8080);
rustp2p_builder_tcp_port(builder, 8080);
rustp2p_builder_group_code(builder, "12345");
rustp2p_builder_add_peer(builder, "udp://192.168.1.100:9090");
// Build endpoint
Rustp2pEndpoint* endpoint = rustp2p_builder_build(builder);
if (!endpoint) {
fprintf(stderr, "Failed to build endpoint\n");
return -1;
}
// Start receive thread
pthread_t thread;
pthread_create(&thread, NULL, receive_thread, endpoint);
// Send messages
const char* message = "Hello from C!";
rustp2p_endpoint_send_to(endpoint, "10.0.0.2",
(const uint8_t*)message, strlen(message));
// Wait for thread
pthread_join(thread, NULL);
// Cleanup
rustp2p_endpoint_free(endpoint);
return 0;
}§C++ Integration
For C++ projects, wrap the C API in RAII classes:
class Rustp2pEndpointWrapper {
Rustp2pEndpoint* endpoint_;
public:
Rustp2pEndpointWrapper(Rustp2pEndpoint* ep) : endpoint_(ep) {}
~Rustp2pEndpointWrapper() {
if (endpoint_) {
rustp2p_endpoint_free(endpoint_);
}
}
// Prevent copying
Rustp2pEndpointWrapper(const Rustp2pEndpointWrapper&) = delete;
Rustp2pEndpointWrapper& operator=(const Rustp2pEndpointWrapper&) = delete;
Rustp2pEndpoint* get() { return endpoint_; }
};§JavaScript/TypeScript Integration
See JAVASCRIPT.md
for details on using these bindings with Node.js via node-ffi-napi.
§Thread Safety
- All functions are thread-safe
- Multiple threads can call send/receive operations simultaneously
- The Tokio runtime is managed internally
§Memory Management
- Always call the corresponding
_freefunction for allocated resources - Do not use pointers after calling
_free - Received data pointers are valid only until
rustp2p_recv_data_freeis called
§See Also
rustp2p- The main Rust library- GitHub Repository
Structs§
- Rustp2p
Builder - Builder handle for configuring a rustp2p endpoint.
- Rustp2p
Endpoint - Endpoint handle for sending and receiving P2P data.
- Rustp2p
Recv Data - Received data handle containing both payload and metadata.
Constants§
- RUST
P2P_ ERROR - General error occurred.
- RUST
P2P_ ERROR_ BUILD_ FAILED - Failed to build endpoint (e.g., port in use, invalid config).
- RUST
P2P_ ERROR_ EOF - End of file / connection closed.
- RUST
P2P_ ERROR_ INVALID_ IP - Invalid IP address format.
- RUST
P2P_ ERROR_ INVALID_ STR - Invalid string format or encoding.
- RUST
P2P_ ERROR_ NULL_ PTR - NULL pointer was provided where a valid pointer was expected.
- RUST
P2P_ ERROR_ WOULD_ BLOCK - Operation would block (for non-blocking operations).
- RUST
P2P_ OK - Operation completed successfully.
Functions§
- rustp2p_
builder_ add_ peer - Add a peer address (e.g., “udp://127.0.0.1:9090” or “tcp://192.168.1.1:8080”)
- rustp2p_
builder_ build - Build the endpoint
- rustp2p_
builder_ encryption - Set encryption algorithm algorithm: 0 = AesGcm, 1 = ChaCha20Poly1305 (if available) password: the encryption password
- rustp2p_
builder_ free - Free/destroy the builder
- rustp2p_
builder_ group_ code - Set group code from string (e.g., “mygroup” or “12345”)
- rustp2p_
builder_ new - Create a new builder
- rustp2p_
builder_ node_ id - Set node ID from IPv4 address string (e.g., “10.0.0.1”)
- rustp2p_
builder_ tcp_ port - Set TCP port
- rustp2p_
builder_ udp_ port - Set UDP port
- rustp2p_
endpoint_ free - Free/destroy the endpoint
- rustp2p_
endpoint_ recv_ from - Receive data from peers (blocking)
- rustp2p_
endpoint_ send_ to - Send data to a peer
- rustp2p_
endpoint_ try_ recv_ from - Try to receive data from peers (non-blocking) Returns pointer to received data structure, or NULL if no data available or on error Caller must free the returned pointer with rustp2p_recv_data_free
- rustp2p_
endpoint_ try_ send_ to - Try to send data to a peer (non-blocking)
- rustp2p_
recv_ data_ free - Free received data
- rustp2p_
recv_ data_ get_ dest_ id - Get destination node ID from received data as IPv4 string
- rustp2p_
recv_ data_ get_ payload - Get payload data from received data out_data: output pointer to data (borrowed, don’t free) out_len: output length
- rustp2p_
recv_ data_ get_ src_ id - Get source node ID from received data as IPv4 string buffer: output buffer for IP string buffer_len: size of buffer (should be at least 16 bytes for “xxx.xxx.xxx.xxx\0”)
- rustp2p_
recv_ data_ is_ relay - Check if the received data was relayed