0
0
mirror of https://github.com/cjdelisle/cjdns synced 2025-10-06 00:32:50 +02:00

Avoid FFI structures and functions going from Rust to C and back to Rust again by adopting a more fine-grained selection of CFFI functions. Also beginnings of Seeder structures

This commit is contained in:
Caleb James DeLisle
2024-09-16 15:28:55 +00:00
parent 5868ece215
commit 2414581590
28 changed files with 313 additions and 1234 deletions

View File

@@ -232,6 +232,10 @@ void Random_bytes(struct Random* rand, uint8_t* location, uint64_t count)
stir(rand);
}
}
void Random_bytes_fromRust(Random_t* rand, uint8_t* location, uint64_t count)
{
Random_bytes(rand, location, count);
}
void Random_base32(struct Random* rand, uint8_t* output, uint32_t length)
{

View File

@@ -27,6 +27,7 @@ Linker_require("crypto/random/Random.c")
typedef struct Random Random_t;
void Random_bytes(Random_t* rand, uint8_t* location, uint64_t count);
void Random_bytes_fromRust(Random_t* rand, uint8_t* location, uint64_t count);
/**
* Get random Base32 text, great for password material.

View File

@@ -28,7 +28,7 @@ void Iface_checkIdentity(struct Iface* iface)
}
// This needs to be in a C file in order to be accessible from Rust
Iface_DEFUN Iface_incomingFromRust(Message_t* message, struct Iface* thisInterface)
Iface_DEFUN Iface_incoming_fromRust(Message_t* message, struct Iface* thisInterface)
{
if (!thisInterface->connectedIf) {
return Error(message, "No connected interface");

View File

@@ -51,7 +51,7 @@ struct Iface
} /* Iface_t defined in RffiPrefix.h */;
// This needs to be in a C file in order to be accessible from Rust
Iface_DEFUN Iface_incomingFromRust(Message_t* message, struct Iface* thisInterface);
Iface_DEFUN Iface_incoming_fromRust(Message_t* message, struct Iface* thisInterface);
void Iface_setIdentity(struct Iface* iface);
void Iface_checkIdentity(struct Iface* iface);

View File

@@ -35,17 +35,17 @@ static int incomingCount = 0;
static int outgoingCount = 0;
static int dropped = 0;
void RustIface_gotIncoming()
void RustIface_gotIncoming_fromRust()
{
incomingCount++;
}
void RustIface_gotOutgoing()
void RustIface_gotOutgoing_fromRust()
{
outgoingCount++;
}
void RustIface_dropped()
void RustIface_dropped_fromRust()
{
dropped++;
}

View File

@@ -14,7 +14,7 @@
*/
#ifndef RUSTIFACE_H
#define RUSTIFACE_H
void RustIface_gotIncoming(void);
void RustIface_gotOutgoing(void);
void RustIface_dropped(void);
void RustIface_gotIncoming_fromRust(void);
void RustIface_gotOutgoing_fromRust(void);
void RustIface_dropped_fromRust(void);
#endif

View File

@@ -119,13 +119,15 @@ static bool PFChan_Pathfinder_sizeOk(enum PFChan_Pathfinder ev, int size)
return (size == 8);
case PFChan_Pathfinder_CTRL_SENDMSG:
return (size >= 8 + PFChan_CtrlMsg_MIN_SIZE);
case PFChan_Pathfinder_CONNECT_PEER:
return (size == 8 + sizeof(PFChan_Pathfinder_ConnectPeer_t));
default:;
}
Assert_failure("invalid event [%d]", ev);
}
// Forget to add the event here? :)
Assert_compileTime(PFChan_Pathfinder__TOO_LOW == 511);
Assert_compileTime(PFChan_Pathfinder__TOO_HIGH == 523);
Assert_compileTime(PFChan_Pathfinder__TOO_HIGH == 524);
static bool PFChan_Core_sizeOk(enum PFChan_Core ev, int size)
{

View File

@@ -114,7 +114,7 @@ fn main() -> Result<()> {
.collect::<Vec<PathBuf>>();
paths.sort();
for path in paths {
if !path.is_dir() && path.extension().unwrap() == "o" {
if !path.is_dir() && path.extension().is_some() && path.extension().unwrap() == "o" {
build.object(path);
}
}
@@ -123,6 +123,7 @@ fn main() -> Result<()> {
// Generate rust bindings from C
#[cfg(feature = "generate-cffi")]
{
println!("cargo:warn=Generating-cffi");
let out_path = PathBuf::from(env::var("OUT_DIR").unwrap());
bindgen::Builder::default()
.header(out_path.join("rust_cjdns_sys_cffi_h.i").to_str().unwrap())
@@ -135,8 +136,13 @@ fn main() -> Result<()> {
.raw_line("#![allow(dead_code)]")
.raw_line("#![allow(non_camel_case_types)]")
.raw_line("#![allow(clippy::enum_variant_names)]")
.whitelist_function(".*")
.raw_line("use crate::rtypes::*;")
// .whitelist_function(".*")
// .blacklist_function("Rffi_.*")
.whitelist_function(".*_fromRust")
.whitelist_type("RBindings_Whitelist")
.blacklist_type("Rffi_.*")
.blacklist_type("RTypes_.*")
.whitelist_var("Sockaddr_AF_INET")
.whitelist_var("Sockaddr_AF_INET6")
.generate()

View File

@@ -23,14 +23,14 @@
#include "crypto/random/test/DeterminentRandomSeed.h"
#include "util/platform/Sockaddr.h"
#include "util/version/Version.h"
#include "util/events/EventBase.h"
// #include "util/events/EventBase.h"
#include "wire/PFChan.h"
enum RBindings_Version {
RBindings_Version_CurrentProtocol = Version_CURRENT_PROTOCOL,
};
// This structure is guaranteed to be present in the generated rust code
// Also all functions in the above headers will be present.
// Any types which are not transitively included in either this structure
// or in one of the functions will not be generated. This prevents generating
// a bunch of platform-specific trash like uint_fast8_t etc.
@@ -42,4 +42,10 @@ struct RBindings_Whitelist {
Log_t* f;
enum RBindings_Version g;
Sockaddr_t h;
PFChan_FromPathfinder_t i;
enum Log_Level j;
Allocator_t* k;
struct Sockaddr_storage l;
struct Sockaddr m;
Random_t* n;
};

File diff suppressed because it is too large Load Diff

View File

@@ -90,7 +90,7 @@ impl log::Log for CjdnsLog {
}
let cmsg = CString::new(msg).unwrap();
unsafe {
cffi::Log_print0(
cffi::Log_print_fromRust(
*log,
lvl,
filebuf.as_ptr() as *const c_char,

View File

@@ -1693,59 +1693,10 @@ mod tests {
fn mk_msg(padding: usize, alloc: &mut Allocator) -> Message {
unsafe {
Message::from_c_message(cffi::Message_new(0, padding as u32, alloc.c()))
Message::from_c_message(cffi::Message_new_fromRust(0, padding as u32, alloc.c()))
}
}
#[test]
pub fn test_encrypt_decrypt_rnd_nonce() {
// The message
const TEST_STRING: &[u8] = b"Hello World";
const LEN: usize = TEST_STRING.len();
let mut alloc = allocator::new!();
let mut msg1 = mk_msg(128, &mut alloc);
let mut msg2 = mk_msg(128, &mut alloc);
msg1.push_bytes(TEST_STRING).unwrap();
msg2.push_bytes(TEST_STRING).unwrap();
let nonce = [42_u8; 24];
let secret = [142_u8; 32];
// Encrypt
super::encrypt_rnd_nonce(nonce, &mut msg1, secret);
unsafe {
cffi::CryptoAuth_encryptRndNonce(
nonce[..].as_ptr(),
msg2.as_c_message(),
secret[..].as_ptr(),
);
}
//println!("Rust: {}", hex::encode(msg1.bytes()));
//println!("C: {}", hex::encode(msg2.bytes()));
assert_eq!(msg1.bytes(), msg2.bytes(), "Encrypt results are different");
// Decrypt
let res = super::decrypt_rnd_nonce(nonce, &mut msg1, secret);
assert!(res.is_ok(), "Decrypt (Rust) failed");
let res = unsafe {
cffi::CryptoAuth_decryptRndNonce(
nonce[..].as_ptr(),
msg2.as_c_message(),
secret[..].as_ptr(),
)
};
assert_eq!(res, 0, "Decrypt (C) failed, err_code = {}", res);
//println!("Rust: {}", hex::encode(msg1.bytes()));
//println!("C: {}", hex::encode(msg2.bytes()));
assert_eq!(msg1.bytes(), msg2.bytes(), "Results are different");
// Ensure the message is the same
assert_eq!(msg1.len(), LEN);
assert_eq!(msg2.len(), LEN);
assert_eq!(msg1.pop_bytes(LEN).unwrap(), TEST_STRING);
assert_eq!(msg2.pop_bytes(LEN).unwrap(), TEST_STRING);
}
#[test]
pub fn test_encrypt_decrypt_without_auth() {
let keys_api = CJDNSKeysApi::new().unwrap();
@@ -1865,177 +1816,6 @@ mod tests {
assert_eq!(msg.bytes(), b"HelloWorld012345");
}
#[test]
pub fn test_cross_encrypt_decrypt_rust_to_c() {
let keys_api = CJDNSKeysApi::new().unwrap();
let my_keys = keys_api.key_pair();
let her_keys = keys_api.key_pair();
let mut alloc = allocator::new!();
let rust_session = {
let priv_key = my_keys.private_key.clone();
let pub_key = her_keys.public_key.clone();
let name = "bob";
let ca =
super::CryptoAuth::new(Some(priv_key),
EventBase {},
Random::Legacy(Protected::new(fake_random(&mut alloc))),
);
let ca = Arc::new(ca);
let res = ca.add_user_ipv6(
ByteString::from(name.to_string()),
Some(ByteString::from(name.to_string())),
None,
);
assert_eq!(res.err(), None);
let sess = super::Session::new(
ca,
pub_key,
false,
Some(format!("{}'s session", name)),
);
assert!(sess.is_ok());
sess.unwrap()
};
let mut msg = mk_msg(256, &mut alloc);
msg.push_bytes(b"HelloWorld012345").unwrap();
let orig_length = msg.len();
let res = rust_session.encrypt_msg(&mut msg);
assert!(res.is_ok());
assert_ne!(msg.len(), orig_length);
let c_session = {
let priv_key = her_keys.private_key;
let pub_key = my_keys.public_key;
let name = "alice";
let event_base = unsafe { cffi::EventBase_new(alloc.c()) };
let ca = unsafe {
cffi::CryptoAuth_new(
alloc.c(),
priv_key.as_ptr(),
event_base,
std::ptr::null_mut(),
fake_random(&mut alloc),
)
};
let res = unsafe {
let name = cffi::String_new(name.as_ptr() as *const i8, alloc.c());
cffi::CryptoAuth_addUser_ipv6(name, name, std::ptr::null_mut(), ca)
};
assert_eq!(res, 0, "CryptoAuth_addUser_ipv6() failed: {}", res);
unsafe {
cffi::CryptoAuth_newSession(
ca,
alloc.c(),
pub_key.as_ptr(),
false,
format!("{}'s session", name).as_mut_ptr() as *mut i8,
false,
)
}
};
let res = unsafe { cffi::CryptoAuth_decrypt(c_session, msg.as_c_message()) };
assert_eq!(res, cffi::CryptoAuth_DecryptErr::CryptoAuth_DecryptErr_NONE);
assert_eq!(msg.len(), orig_length);
assert_eq!(msg.bytes(), b"HelloWorld012345");
}
#[test]
pub fn test_cross_encrypt_decrypt_c_to_rust() {
let keys_api = CJDNSKeysApi::new().unwrap();
let my_keys = keys_api.key_pair();
let her_keys = keys_api.key_pair();
let mut alloc = allocator::new!();
let c_session = {
let priv_key = my_keys.private_key.clone();
let pub_key = her_keys.public_key.clone();
let name = "bob";
let event_base = unsafe { cffi::EventBase_new(alloc.c()) };
let ca = unsafe {
cffi::CryptoAuth_new(
alloc.c(),
priv_key.as_ptr(),
event_base,
std::ptr::null_mut(),
fake_random(&mut alloc),
)
};
let res = unsafe {
let name = cffi::String_new(name.as_ptr() as *const i8, alloc.c());
cffi::CryptoAuth_addUser_ipv6(name, name, std::ptr::null_mut(), ca)
};
assert_eq!(res, 0, "CryptoAuth_addUser_ipv6() failed: {}", res);
unsafe {
cffi::CryptoAuth_newSession(
ca,
alloc.c(),
pub_key.as_ptr(),
false,
format!("{}'s session", name).as_mut_ptr() as *mut i8,
false,
)
}
};
let mut msg = mk_msg(256, &mut alloc);
msg.push_bytes(b"HelloWorld012345").unwrap();
let orig_length = msg.len();
let res = unsafe { cffi::CryptoAuth_encrypt(c_session, msg.as_c_message()) };
assert_eq!(res, 0);
assert_ne!(msg.len(), orig_length);
let rust_session = {
let priv_key = her_keys.private_key;
let pub_key = my_keys.public_key;
let name = "alice";
let ca =
super::CryptoAuth::new(
Some(priv_key),
EventBase {},
Random::Legacy(Protected::new(fake_random(&mut alloc))),
);
let ca = Arc::new(ca);
let res = ca.add_user_ipv6(
ByteString::from(name.to_string()),
Some(ByteString::from(name.to_string())),
None,
);
assert_eq!(res.err(), None);
let sess = super::Session::new(
ca,
pub_key,
false,
Some(format!("{}'s session", name)),
);
assert!(sess.is_ok());
sess.unwrap()
};
let res = rust_session.decrypt_msg(&mut msg);
assert!(res.is_ok());
assert_eq!(msg.len(), orig_length);
assert_eq!(msg.bytes(), b"HelloWorld012345");
}
fn fake_random(alloc: &mut Allocator) -> *mut cffi::Random_t {
unsafe {
let fake_seed = cffi::DeterminentRandomSeed_new(alloc.c(), std::ptr::null_mut());

View File

@@ -3,13 +3,13 @@
pub use cjdns_crypto::random::DefaultRandom as SodiumRandom;
pub use cjdns_crypto::random::Random as Rand;
use crate::cffi::Random as CRandom;
use crate::cffi::Random_bytes;
use crate::cffi::Random_t;
use crate::cffi::Random_bytes_fromRust;
use crate::gcl::Protected;
pub enum Random {
Sodium(SodiumRandom),
Legacy(Protected<*mut CRandom>),
Legacy(Protected<*mut Random_t>),
#[cfg(test)]
Fake,
}
@@ -21,7 +21,7 @@ impl Random {
}
#[inline]
pub fn wrap_legacy(c_random: *mut CRandom) -> Self {
pub fn wrap_legacy(c_random: *mut Random_t) -> Self {
Random::Legacy(Protected::new(c_random))
}
@@ -40,9 +40,9 @@ impl Random {
}
#[inline]
fn c_random_bytes(rand: *mut CRandom, dest: &mut [u8]) {
fn c_random_bytes(rand: *mut Random_t, dest: &mut [u8]) {
unsafe {
Random_bytes(rand, dest.as_mut_ptr(), dest.len() as u64);
Random_bytes_fromRust(rand, dest.as_mut_ptr(), dest.len() as u64);
}
}

View File

@@ -22,7 +22,7 @@ impl IfRecv for CRecv {
let c_msg = m.as_c_message();
let cif = self.c_iface.lock();
unsafe {
(cffi::Iface_incomingFromRust(c_msg, *cif) as *mut RTypes_Error_t).as_mut()
(cffi::Iface_incoming_fromRust(c_msg, *cif) as *mut RTypes_Error_t).as_mut()
.map(|e|e.e.take())
.flatten()
.map(Err)
@@ -41,7 +41,7 @@ struct CIface {
dg: Arc<()>,
}
unsafe extern "C" fn from_c(msg: *mut cffi::Message, iface_p: *mut cffi::Iface) -> *mut cffi::RTypes_Error_t {
unsafe extern "C" fn from_c(msg: *mut cffi::Message, iface_p: *mut cffi::Iface) -> *mut RTypes_Error_t {
let iface = from_c!(iface_p as *mut CIface);
let alloc = (*msg)._alloc;
let msg = Message::from_c_message(msg);
@@ -50,7 +50,7 @@ unsafe extern "C" fn from_c(msg: *mut cffi::Message, iface_p: *mut cffi::Iface)
Ok(_) => std::ptr::null_mut(),
Err(e) => {
let e: *mut RTypes_Error_t = allocator::adopt(alloc, RTypes_Error_t { e: Some(e) });
e as *mut cffi::RTypes_Error_t
e as *mut RTypes_Error_t
}
}
}

View File

@@ -20,7 +20,7 @@ struct TestWrapperPvt {
impl Drop for TestWrapperPvt {
fn drop(&mut self) {
let _guard = GCL.lock();
unsafe { cffi::RustIface_dropped() };
unsafe { cffi::RustIface_dropped_fromRust() };
println!("TestWrapperPvt dropped");
}
}
@@ -34,7 +34,7 @@ impl IfRecv for TestWrapperInt {
{
let mut pvt_l = self.pvt.lock();
pvt_l.outgoing_count += 1;
unsafe { cffi::RustIface_gotOutgoing() };
unsafe { cffi::RustIface_gotOutgoing_fromRust() };
println!(
"Received outgoing message, total out {} in {}",
pvt_l.outgoing_count, pvt_l.incoming_count
@@ -46,7 +46,7 @@ impl IfRecv for TestWrapperInt {
impl Drop for TestWrapperInt {
fn drop(&mut self) {
let _guard = GCL.lock();
unsafe { cffi::RustIface_dropped() };
unsafe { cffi::RustIface_dropped_fromRust() };
println!("TestWrapperInt dropped");
}
}
@@ -60,7 +60,7 @@ impl IfRecv for TestWrapperExt {
{
let mut pvt_l = self.pvt.lock();
pvt_l.incoming_count += 1;
unsafe { cffi::RustIface_gotIncoming() };
unsafe { cffi::RustIface_gotIncoming_fromRust() };
println!(
"Received incoming message, total out {} in {}",
pvt_l.outgoing_count, pvt_l.incoming_count
@@ -72,7 +72,7 @@ impl IfRecv for TestWrapperExt {
impl Drop for TestWrapperExt {
fn drop(&mut self) {
let _guard = GCL.lock();
unsafe { cffi::RustIface_dropped() };
unsafe { cffi::RustIface_dropped_fromRust() };
println!("TestWrapperExt dropped");
}
}

View File

@@ -64,7 +64,7 @@ impl Message {
}
pub fn anew(padding: usize, alloc: &mut Allocator) -> Self {
unsafe { Message { msg: cffi::Message_new(0, padding as u32, alloc.c()), alloc: None } }
unsafe { Message { msg: cffi::Message_new_fromRust(0, padding as u32, alloc.c()), alloc: None } }
}
/// Create empty new message with the given amount of free space,
@@ -73,7 +73,7 @@ impl Message {
/// Note: this function does *NOT* clone original message,
/// the resulting message will be empty.
pub fn new_same_alloc(&self, padding: usize) -> Self {
unsafe { Message { msg: cffi::Message_new(0, padding as u32, (*self.msg)._alloc), alloc: None } }
unsafe { Message { msg: cffi::Message_new_fromRust(0, padding as u32, (*self.msg)._alloc), alloc: None } }
}
/// Construct a Rust `Message` by wrapping a pointer to C `Message`.
@@ -441,7 +441,7 @@ mod tests {
#[test]
fn test_message_bytes() {
let mut alloc = allocator::new!();
let c_msg = unsafe { cffi::Message_new(4, 5, alloc.c()) };
let c_msg = unsafe { cffi::Message_new_fromRust(4, 5, alloc.c()) };
let mut msg = Message::from_c_message(c_msg);
assert_eq!(msg.len(), 4);
assert_eq!(msg.pad(), 5);
@@ -467,7 +467,7 @@ mod tests {
#[test]
fn test_message_push_pop() {
let mut alloc = allocator::new!();
let c_msg = unsafe { cffi::Message_new(64, 64, alloc.c()) };
let c_msg = unsafe { cffi::Message_new_fromRust(64, 64, alloc.c()) };
let mut msg = Message::from_c_message(c_msg);
assert_eq!(msg.len(), 64);
assert_eq!(msg.push(0x12345678_u32), Ok(()));
@@ -482,7 +482,7 @@ mod tests {
#[test]
fn test_message_push_pop_unaligned() {
let mut alloc = allocator::new!();
let c_msg = unsafe { cffi::Message_new(64, 64, alloc.c()) };
let c_msg = unsafe { cffi::Message_new_fromRust(64, 64, alloc.c()) };
let mut msg = Message::from_c_message(c_msg);
assert_eq!(msg.len(), 64);

View File

@@ -1,3 +1,4 @@
use super::allocator::file_line;
use super::{cstr, strc};
use crate::bytestring::ByteString;
use crate::cffi::{self, Allocator_t, Random_t, String_t};
@@ -134,11 +135,7 @@ pub unsafe extern "C" fn Rffi_CryptoAuth2_tryHandshake(
Ok((code, sess)) => {
(*ret).code = code;
if let Some(sess) = sess {
let child = cffi::Allocator__child(
alloc,
b"rffi_tryHandshake\0".as_ptr() as *const c_char,
163,
);
let child = allocator::rs(alloc).child(file_line!());
(*ret).alloc = child;
(*ret).sess = wrap_session(sess, child)
}

View File

@@ -1,10 +1,10 @@
use tokio::io::Interest;
use tokio::io::unix::AsyncFd;
use crate::cffi::{Allocator_t, Allocator__onFree, Allocator_OnFreeJob};
use crate::cffi::Allocator_t;
use crate::gcl::Protected;
use crate::rffi::allocator;
use std::ffi::c_void;
use std::os::raw::{c_int, c_char};
use crate::rffi::allocator::{self, file_line};
use crate::util::identity::{from_c, Identity};
use std::os::raw::{c_char, c_int, c_void};
use std::sync::atomic::{AtomicBool, Ordering};
use std::sync::Arc;
@@ -13,11 +13,14 @@ struct FdReadable {
active: Arc<AtomicBool>,
}
pub struct Rffi_FdReadableTx(Arc<FdReadable>);
pub struct Rffi_FdReadableTx{
a: Arc<FdReadable>,
identity: Identity<Self>,
}
pub extern "C" fn fd_readable_on_free(j: *mut Allocator_OnFreeJob) {
let timer_tx = unsafe { &*((*j).userData as *mut Rffi_FdReadableTx) };
timer_tx.0.active.store(false, Ordering::Relaxed);
pub extern "C" fn fd_readable_on_free(j: *mut c_void) {
let timer_tx = unsafe { from_c!(j as *mut Rffi_FdReadableTx) };
timer_tx.a.active.store(false, Ordering::Relaxed);
}
#[no_mangle]
@@ -52,14 +55,16 @@ pub extern "C" fn Rffi_pollFdReadable(
let active = Arc::clone(&rtx.active);
unsafe {
let event_tx = allocator::adopt(alloc, Rffi_FdReadableTx(rtx));
let event_tx = allocator::adopt(alloc,
Rffi_FdReadableTx{ a:rtx, identity: Identity::default() }
);
// Note: we must close the event in the allocator onFree rather than in the drop
// because the drop only happens later, when Rust wants to.
Allocator__onFree(alloc,
Some(fd_readable_on_free),
allocator::rs(alloc).on_free(
fd_readable_on_free,
event_tx as *mut c_void,
("fd_readable.rs\0").as_bytes().as_ptr() as *const ::std::os::raw::c_char,
line!() as std::os::raw::c_int);
file_line!()
);
*out = event_tx;
}

View File

@@ -1,8 +1,8 @@
use super::Rffi_EventLoop;
use crate::cffi::{Allocator_t, Allocator__onFree, Allocator_OnFreeJob};
use crate::cffi::Allocator_t;
use crate::gcl::Protected;
use crate::rffi::allocator;
use crate::util::identity::from_c;
use crate::rffi::allocator::{self, file_line};
use crate::util::identity::{from_c, from_c_const, Identity};
use std::ffi::c_void;
use std::os::raw::{c_int, c_ulong};
use std::sync::atomic::{AtomicBool, Ordering};
@@ -17,7 +17,10 @@ enum TimerCommand {
}
/// The handle returned to C, used to talk to the timer task.
pub struct Rffi_TimerTx(Arc<TimerTx>);
pub struct Rffi_TimerTx{
a: Arc<TimerTx>,
identity: Identity<Self>,
}
/// Internal struct, which we keep weak references to.
pub struct TimerTx {
@@ -25,10 +28,10 @@ pub struct TimerTx {
active: Arc<AtomicBool>,
}
pub extern "C" fn timeout_on_free(j: *mut Allocator_OnFreeJob) {
let timer_tx = unsafe { &*((*j).userData as *mut Rffi_TimerTx) };
timer_tx.0.active.store(false, Ordering::Relaxed);
timer_tx.0.rffi_send(TimerCommand::Free);
pub extern "C" fn timeout_on_free(j: *mut c_void) {
let timer_tx = from_c!(j as *mut Rffi_TimerTx);
timer_tx.a.active.store(false, Ordering::Relaxed);
timer_tx.a.rffi_send(TimerCommand::Free);
}
/// Spawn a timer task for a timeout or interval, that calls some callback whenever it triggers.
@@ -59,14 +62,13 @@ pub extern "C" fn Rffi_setTimeout(
let is_active = rtx.active.clone();
unsafe {
let timer_tx = allocator::adopt(alloc, Rffi_TimerTx(rtx));
let timer_tx = allocator::adopt(alloc, Rffi_TimerTx{
a: rtx,
identity: Default::default(),
});
// Note: we must close the event in the allocator onFree rather than in the drop
// because the drop only happens later, when Rust wants to.
Allocator__onFree(alloc,
Some(timeout_on_free),
timer_tx as *mut c_void,
("timeout.rs\0").as_bytes().as_ptr() as *const ::std::os::raw::c_char,
line!() as std::os::raw::c_int);
allocator::rs(alloc).on_free(timeout_on_free, timer_tx as _, file_line!());
*out_timer_tx = timer_tx;
}
@@ -131,23 +133,23 @@ pub extern "C" fn Rffi_resetTimeout(
timer_tx: *const Rffi_TimerTx,
timeout_millis: c_ulong,
) -> c_int {
let timer_tx = unsafe { &*timer_tx };
timer_tx.0.rffi_send(TimerCommand::Reset(timeout_millis))
let timer_tx = from_c_const!(timer_tx);
timer_tx.a.rffi_send(TimerCommand::Reset(timeout_millis))
}
/// Cancel a timer task.
#[no_mangle]
pub extern "C" fn Rffi_clearTimeout(timer_tx: *const Rffi_TimerTx) -> c_int {
let timer_tx = unsafe { &*timer_tx };
timer_tx.0.active.store(false, Ordering::Relaxed);
timer_tx.0.rffi_send(TimerCommand::Cancel)
let timer_tx = from_c_const!(timer_tx);
timer_tx.a.active.store(false, Ordering::Relaxed);
timer_tx.a.rffi_send(TimerCommand::Cancel)
}
/// Return 1 if a timer task is still running, 0 otherwise.
#[no_mangle]
pub extern "C" fn Rffi_isTimeoutActive(timer_tx: *const Rffi_TimerTx) -> c_int {
let timer_tx = unsafe { &*timer_tx };
timer_tx.0.active.load(Ordering::Relaxed) as _
let timer_tx = from_c_const!(timer_tx);
timer_tx.a.active.load(Ordering::Relaxed) as _
}
/// Cancel all timer tasks.

View File

@@ -33,4 +33,18 @@ macro_rules! from_c {
}
};
}
pub(crate) use from_c;
pub(crate) use from_c;
macro_rules! from_c_const {
($obj:expr) => {
{
let o = $obj;
unsafe {
(*o).identity.check();
&(*o)
}
}
};
}
pub(crate) use from_c_const;

View File

@@ -94,18 +94,18 @@ impl From<*const cffi::Sockaddr> for Sockaddr {
}
}
impl From<&SocketAddr> for Sockaddr {
fn from(sa: &SocketAddr) -> Self {
fn from(sa: &SocketAddr) -> Self {
let mut out = Self{ss: unsafe { std::mem::zeroed::<cffi::Sockaddr_storage>() } };
match sa.ip() {
IpAddr::V4(v4) => unsafe {
cffi::Sockaddr_initFromBytes(
cffi::Sockaddr_initFromBytes_fromRust(
&mut out.ss as *mut _,
v4.octets()[..].as_ptr(),
cffi::Sockaddr_AF_INET,
);
}
IpAddr::V6(v6) => unsafe {
cffi::Sockaddr_initFromBytes(
cffi::Sockaddr_initFromBytes_fromRust(
&mut out.ss as *mut _,
v6.octets()[..].as_ptr(),
cffi::Sockaddr_AF_INET6,
@@ -113,7 +113,7 @@ impl From<&SocketAddr> for Sockaddr {
}
}
unsafe {
cffi::Sockaddr_setPort(&mut out.ss.addr as *mut _, sa.port());
cffi::Sockaddr_setPort_fromRust(&mut out.ss.addr as *mut _, sa.port());
}
out
}
@@ -123,10 +123,10 @@ impl TryFrom<&Sockaddr> for SocketAddr {
fn try_from(sa: &Sockaddr) -> anyhow::Result<Self> {
let mut ip = [0u8; 16];
let (port, is_ip6, is_handle) = unsafe {
cffi::Sockaddr_asIp6(&mut ip as *mut _, &sa.ss.addr as *const _);
cffi::Sockaddr_asIp6_fromRust(&mut ip as *mut _, &sa.ss.addr as *const _);
(
cffi::Sockaddr_getPort(&sa.ss.addr as *const _),
cffi::Sockaddr_getFamily(&sa.ss.addr as *const _) == cffi::Sockaddr_AF_INET6,
cffi::Sockaddr_getPort_fromRust(&sa.ss.addr as *const _),
cffi::Sockaddr_getFamily_fromRust(&sa.ss.addr as *const _) == cffi::Sockaddr_AF_INET6,
sa.ss.addr.type_ != 0
)
};

View File

@@ -32,7 +32,7 @@ void Log_print(struct Log* log,
va_end(args);
}
void Log_print0(struct Log* log, enum Log_Level lvl, const char* file, int line, const char* msg)
void Log_print_fromRust(struct Log* log, enum Log_Level lvl, const char* file, int line, const char* msg)
{
Log_print(log, lvl, file, line, "%s", msg);
}

View File

@@ -68,7 +68,7 @@ void Log_print(struct Log* log,
const char* format,
...);
void Log_print0(struct Log* log, enum Log_Level lvl, const char* file, int line, const char* msg);
void Log_print_fromRust(struct Log* log, enum Log_Level lvl, const char* file, int line, const char* msg);
#define Log_printf(log, level, ...) \
do { \

View File

@@ -257,6 +257,10 @@ int Sockaddr_getPort(const struct Sockaddr* sockaddr)
const uint16_t* pp = getPortPtr((struct Sockaddr*) sockaddr);
return (pp) ? Endian_bigEndianToHost16(*pp) : -1;
}
int Sockaddr_getPort_fromRust(const struct Sockaddr* sockaddr)
{
return Sockaddr_getPort(sockaddr);
}
int Sockaddr_setPort(struct Sockaddr* sockaddr, uint16_t port)
{
@@ -267,6 +271,10 @@ int Sockaddr_setPort(struct Sockaddr* sockaddr, uint16_t port)
}
return -1;
}
int Sockaddr_setPort_fromRust(struct Sockaddr* sockaddr, uint16_t port)
{
return Sockaddr_setPort(sockaddr, port);
}
int Sockaddr_getAddress(struct Sockaddr* sockaddr, void* addrPtr)
{
@@ -299,6 +307,11 @@ int Sockaddr_getFamily(const struct Sockaddr* sockaddr)
return sa->ss.ss_family;
}
int Sockaddr_getFamily_fromRust(const struct Sockaddr* sockaddr)
{
return Sockaddr_getFamily(sockaddr);
}
struct Sockaddr* Sockaddr_initFromBytes(struct Sockaddr_storage* out, const uint8_t* bytes, int addrFamily)
{
switch (addrFamily) {
@@ -323,6 +336,14 @@ struct Sockaddr* Sockaddr_initFromBytes(struct Sockaddr_storage* out, const uint
return &out->addr;
}
Sockaddr_t* Sockaddr_initFromBytes_fromRust(
struct Sockaddr_storage* out,
const uint8_t* bytes,
int addrFamily
) {
return Sockaddr_initFromBytes(out, bytes, addrFamily);
}
struct Sockaddr* Sockaddr_fromBytes(const uint8_t* bytes, int addrFamily, struct Allocator* alloc)
{
struct Sockaddr_storage ss;
@@ -383,6 +404,10 @@ void Sockaddr_asIp6(uint8_t addrOut[static 16], const struct Sockaddr* sockaddr)
}
}
}
void Sockaddr_asIp6_fromRust(uint8_t addrOut[static 16], const struct Sockaddr* sockaddr)
{
Sockaddr_asIp6(addrOut, sockaddr);
}
int Sockaddr_compare(const struct Sockaddr* a, const struct Sockaddr* b)
{

View File

@@ -99,6 +99,7 @@ char* Sockaddr_print(Sockaddr_t* addr, struct Allocator* alloc);
* @return the port number or -1 if not applicable to this sockaddr.
*/
int Sockaddr_getPort(const Sockaddr_t* sa);
int Sockaddr_getPort_fromRust(const struct Sockaddr* sockaddr);
/**
* Set the port for a sockaddr if applicable.
@@ -108,6 +109,7 @@ int Sockaddr_getPort(const Sockaddr_t* sa);
* @return 0 if all goes well, -1 if not applicable to this sockaddr.
*/
int Sockaddr_setPort(Sockaddr_t* sa, uint16_t port);
int Sockaddr_setPort_fromRust(struct Sockaddr* sockaddr, uint16_t port);
/**
* Get the address family for the address.
@@ -118,6 +120,7 @@ int Sockaddr_setPort(Sockaddr_t* sa, uint16_t port);
extern const int Sockaddr_AF_INET;
extern const int Sockaddr_AF_INET6;
int Sockaddr_getFamily(const Sockaddr_t* sa);
int Sockaddr_getFamily_fromRust(const struct Sockaddr* sockaddr);
/**
* Get the address stored in a sockaddr.
@@ -137,6 +140,7 @@ int Sockaddr_getAddress(Sockaddr_t* sa, void* addrPtr);
* Other addresses larger than 14 bytes are represented as ffff::<14 bytes of sha256 hash of address>
*/
void Sockaddr_asIp6(uint8_t addrOut[static 16], const Sockaddr_t* sockaddr);
void Sockaddr_asIp6_fromRust(uint8_t addrOut[static 16], const struct Sockaddr* sockaddr);
/**
* Output the native form of a sockaddr.
@@ -155,6 +159,11 @@ static inline void* Sockaddr_asNative(Sockaddr_t* sa)
* @return Sockaddr_t* which points to the memory of `out`
*/
Sockaddr_t* Sockaddr_initFromBytes(struct Sockaddr_storage* out, const uint8_t* bytes, int addrFamily);
Sockaddr_t* Sockaddr_initFromBytes_fromRust(
struct Sockaddr_storage* out,
const uint8_t* bytes,
int addrFamily
);
/**
* Sockaddr_fromBytes() takes

View File

@@ -29,6 +29,13 @@ Message_t* Message_new(uint32_t messageLength,
return out;
}
struct Message* Message_new_fromRust(uint32_t messageLength,
uint32_t amountOfPadding,
struct Allocator* alloc)
{
return Message_new(messageLength, amountOfPadding, alloc);
}
void Message_setAssociatedFd(Message_t* msg, int fd)
{
if (fd == -1) {

View File

@@ -98,6 +98,10 @@ struct Message* Message_new(uint32_t messageLength,
uint32_t amountOfPadding,
struct Allocator* alloc);
struct Message* Message_new_fromRust(uint32_t messageLength,
uint32_t amountOfPadding,
struct Allocator* alloc);
void Message_setAssociatedFd(struct Message* msg, int fd);
int Message_getAssociatedFd(struct Message* msg);

View File

@@ -96,6 +96,20 @@ struct PFChan_Pathfinder_Superiority
Assert_compileTime(
sizeof(struct PFChan_Pathfinder_Superiority) == PFChan_Pathfinder_Superiority_SIZE);
typedef struct PFChan_Pathfinder_ConnectPeer {
// If ::ffff:XXXX:XXXX then is 4 in 6
uint8_t ip[16];
// Public key of the peer
uint8_t pubkey[32];
// Null terminated, e.g. "AP_LOGIN: 65535\0"
uint8_t login[16];
// Null terminated, e.g. "AP_PASS: 4eqnmtOq/Mo\0"
uint8_t password[24];
// Protocol version of the peer
uint32_t version;
} PFChan_Pathfinder_ConnectPeer_t;
Assert_compileTime(sizeof(PFChan_Pathfinder_ConnectPeer_t) == 92);
enum PFChan_Pathfinder
{
/** Below the lowest valid value. */
@@ -173,10 +187,16 @@ enum PFChan_Pathfinder
*/
PFChan_Pathfinder_SNODE = 522,
PFChan_Pathfinder__TOO_HIGH = 523,
/**
* Send a peer setup request.
* (Received by: InterfaceController.c)
*/
PFChan_Pathfinder_CONNECT_PEER = 523,
PFChan_Pathfinder__TOO_HIGH = 524,
};
struct PFChan_FromPathfinder
typedef struct PFChan_FromPathfinder
{
enum PFChan_Pathfinder event_be;
@@ -190,9 +210,10 @@ struct PFChan_FromPathfinder
struct PFChan_Msg sendmsg;
struct PFChan_Ping ping;
struct PFChan_Ping pong;
PFChan_Pathfinder_ConnectPeer_t cp;
uint8_t bytes[1];
} content;
};
} PFChan_FromPathfinder_t;
//// ------------------------- Core Events ------------------------- ////