use std::ffi::CString;
use std::time::Duration;
use libc::*;
use multiaddr::Multiaddr;
use serde::Deserialize;
use crate::general::{PeerId, ProtocolId, Result};
use crate::utils::{get_trampoline, handle_json_response, handle_no_response, handle_response};
pub fn waku_add_peers(address: &Multiaddr, protocol_id: ProtocolId) -> Result<PeerId> {
let address_ptr = CString::new(address.to_string())
.expect("CString should build properly from the address")
.into_raw();
let protocol_id_ptr = CString::new(protocol_id.to_string())
.expect("CString should build properly from the protocol id")
.into_raw();
let mut result: String = Default::default();
let result_cb = |v: &str| result = v.to_string();
let code = unsafe {
let mut closure = result_cb;
let cb = get_trampoline(&closure);
let out = waku_sys::waku_add_peer(
address_ptr,
protocol_id_ptr,
cb,
&mut closure as *mut _ as *mut c_void,
);
drop(CString::from_raw(address_ptr));
drop(CString::from_raw(protocol_id_ptr));
out
};
handle_response(code, &result)
}
pub fn waku_connect_peer_with_address(
address: &Multiaddr,
timeout: Option<Duration>,
) -> Result<()> {
let address_ptr = CString::new(address.to_string())
.expect("CString should build properly from multiaddress")
.into_raw();
let mut error: String = Default::default();
let error_cb = |v: &str| error = v.to_string();
let code = unsafe {
let mut closure = error_cb;
let cb = get_trampoline(&closure);
let out = waku_sys::waku_connect(
address_ptr,
timeout
.map(|duration| duration.as_millis().try_into().unwrap_or(i32::MAX))
.unwrap_or(0),
cb,
&mut closure as *mut _ as *mut c_void,
);
drop(CString::from_raw(address_ptr));
out
};
handle_no_response(code, &error)
}
pub fn waku_connect_peer_with_id(peer_id: &PeerId, timeout: Option<Duration>) -> Result<()> {
let peer_id_ptr = CString::new(peer_id.as_bytes())
.expect("CString should build properly from peer id")
.into_raw();
let mut error: String = Default::default();
let error_cb = |v: &str| error = v.to_string();
let code = unsafe {
let mut closure = error_cb;
let cb = get_trampoline(&closure);
let out = waku_sys::waku_connect_peerid(
peer_id_ptr,
timeout
.map(|duration| duration.as_millis().try_into().unwrap_or(i32::MAX))
.unwrap_or(0),
cb,
&mut closure as *mut _ as *mut c_void,
);
drop(CString::from_raw(peer_id_ptr));
out
};
handle_no_response(code, &error)
}
pub fn waku_disconnect_peer_with_id(peer_id: &PeerId) -> Result<()> {
let peer_id_ptr = CString::new(peer_id.as_bytes())
.expect("CString should build properly from peer id")
.into_raw();
let mut error: String = Default::default();
let error_cb = |v: &str| error = v.to_string();
let code = unsafe {
let mut closure = error_cb;
let cb = get_trampoline(&closure);
let out = waku_sys::waku_disconnect(peer_id_ptr, cb, &mut closure as *mut _ as *mut c_void);
drop(CString::from_raw(peer_id_ptr));
out
};
handle_no_response(code, &error)
}
pub fn waku_peer_count() -> Result<usize> {
let mut result: String = Default::default();
let result_cb = |v: &str| result = v.to_string();
let code = unsafe {
let mut closure = result_cb;
let cb = get_trampoline(&closure);
waku_sys::waku_peer_cnt(cb, &mut closure as *mut _ as *mut c_void)
};
handle_response(code, &result)
}
pub type Protocol = String;
#[derive(Deserialize, Clone, Debug)]
#[serde(rename_all = "camelCase")]
pub struct WakuPeerData {
#[serde(alias = "peerID")]
peer_id: PeerId,
protocols: Vec<Protocol>,
#[serde(alias = "addrs")]
addresses: Vec<Multiaddr>,
connected: bool,
}
impl WakuPeerData {
pub fn peer_id(&self) -> &PeerId {
&self.peer_id
}
pub fn protocols(&self) -> &[Protocol] {
&self.protocols
}
pub fn addresses(&self) -> &[Multiaddr] {
&self.addresses
}
pub fn connected(&self) -> bool {
self.connected
}
}
pub type WakuPeers = Vec<WakuPeerData>;
pub fn waku_peers() -> Result<WakuPeers> {
let mut result: String = Default::default();
let result_cb = |v: &str| result = v.to_string();
let code = unsafe {
let mut closure = result_cb;
let cb = get_trampoline(&closure);
waku_sys::waku_peers(cb, &mut closure as *mut _ as *mut c_void)
};
handle_json_response(code, &result)
}
#[cfg(test)]
mod tests {
use crate::node::peers::WakuPeerData;
#[test]
fn deserialize_waku_peer_data() {
let json_str = r#"{
"peerID": "16Uiu2HAmJb2e28qLXxT5kZxVUUoJt72EMzNGXB47RedcBafeDCBA",
"protocols": [
"/ipfs/id/1.0.0",
"/vac/waku/relay/2.0.0",
"/ipfs/ping/1.0.0"
],
"addrs": [
"/ip4/1.2.3.4/tcp/30303"
],
"connected": true
}"#;
let _: WakuPeerData = serde_json::from_str(json_str).unwrap();
}
}