diff --git a/Cargo.lock b/Cargo.lock index 774888e..1858800 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -14,6 +14,12 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" +[[package]] +name = "base64" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" + [[package]] name = "base64ct" version = "1.1.1" @@ -229,6 +235,7 @@ dependencies = [ name = "ironforce" version = "0.1.0" dependencies = [ + "base64", "core-error", "rand", "rand_os", diff --git a/Cargo.toml b/Cargo.toml index 7ccac09..23997d2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,11 +22,11 @@ core-error = "0.0.1-rc4" serde_cbor = "0.11.2" serde_json = "1.0.72" spin = "0.9.2" +base64 = "0.13.0" [profile.dev.package.num-bigint-dig] opt-level = 3 [[bin]] name = "worker" -src = "src/worker.rs" required-features = ["std"] diff --git a/src/bin/worker.rs b/src/bin/worker.rs index 6a5f074..3ac8d1a 100644 --- a/src/bin/worker.rs +++ b/src/bin/worker.rs @@ -1,8 +1,57 @@ -use ironforce::IronForce; use ironforce::res::IFResult; +use ironforce::{IronForce, Message, MessageType, PublicKey}; fn main() -> IFResult<()> { - let ironforce = IronForce::new(); - let (thread, _) = ironforce.launch_main_loop(500); - thread.join().unwrap() -} \ No newline at end of file + let ironforce = IronForce::from_file("".to_string())?; + let if_keys = ironforce.keys.clone(); + println!( + "Our public key: {}", + base64::encode(if_keys.get_public().to_vec().as_slice()) + ); + let (_thread, if_mutex) = ironforce.launch_main_loop(100); + let stdin = std::io::stdin(); + let if_mutex_clone = if_mutex.clone(); + let if_keys_clone = if_keys.clone(); + std::thread::spawn(move || loop { + if let Some(msg) = if_mutex_clone.lock().unwrap().read_message() { + println!( + "New message: {}", + String::from_utf8(msg.get_decrypted(&if_keys_clone).unwrap()).unwrap() + ); + } + std::thread::sleep(std::time::Duration::from_millis(300)) + }); + loop { + let mut buf = String::new(); + stdin.read_line(&mut buf)?; + let msg_base = if buf.starts_with('>') { + let target_base64 = buf + .split(')') + .next() + .unwrap() + .trim_start_matches(">(") + .to_string(); + let target = if let Ok(res) = base64::decode(target_base64) { + res + } else { + println!("Wrong b64."); + continue; + }; + buf = buf + .split(')') + .skip(1) + .map(|s| s.to_string()) + .collect::>() + .join(")"); + Message::build() + .message_type(MessageType::SingleCast) + .recipient(&PublicKey::from_vec(target).unwrap()) + } else { + Message::build().message_type(MessageType::Broadcast) + }; + if_mutex + .lock() + .unwrap() + .send_to_all(msg_base.content(buf.into_bytes()).sign(&if_keys).build()?)?; + } +} diff --git a/src/interfaces/ip.rs b/src/interfaces/ip.rs index 6ae0176..95066ce 100644 --- a/src/interfaces/ip.rs +++ b/src/interfaces/ip.rs @@ -105,6 +105,11 @@ impl Interface for IPInterface { let mut new_connections: Vec = vec![]; for connection in &mut self.connections { connection.set_nonblocking(true)?; + let mut buf = [0u8; 6]; + let peek_res = connection.peek(&mut buf); + if peek_res.is_err() || peek_res.unwrap() < 6 { + continue + } let mut header: [u8; 6] = [0, 0, 0, 0, 0, 0]; match connection.read_exact(&mut header) { Ok(_) => {} @@ -215,11 +220,6 @@ impl Interface for IPInterface { &*self.id } fn send(&mut self, message: &[u8], interface_data: Option) -> IFResult<()> { - println!( - "({:?}): Connecting to {:?} to send a message", - self.listener.local_addr().unwrap(), - interface_data - ); let package = IPPackage { version: 0, @@ -232,11 +232,6 @@ impl Interface for IPInterface { Some(ip_string) => { let addr: net::SocketAddr = ip_string.parse().expect("Unable to parse address"); let index = self.obtain_connection(&(addr.ip(), addr.port()))?; - println!( - "({:?}): We have a connection to {:?}", - self.listener.local_addr().unwrap(), - self.connections[index].peer_addr().unwrap() - ); IPInterface::send_package(&mut self.connections[index], package)?; } None => { @@ -245,7 +240,6 @@ impl Interface for IPInterface { } } }; - println!("Sent message"); Ok(()) } fn receive(&mut self) -> IFResult> { @@ -302,6 +296,7 @@ impl IPInterface { .filter_map(|r| r.ok()) .filter_map(|r| r) .map(|mut c| -> IFResult { + println!("Requesting peers from {:?}", c.peer_addr().unwrap()); if do_peer_request { Self::request_peers(&mut c)?; } @@ -410,7 +405,7 @@ impl IPInterface { fn create_tcp_listener(port: u16) -> Option { for port in port..port + 5 { - match net::TcpListener::bind("127.0.0.1:".to_owned() + &port.to_string()) { + match net::TcpListener::bind("0.0.0.0:".to_owned() + &port.to_string()) { Ok(listener) => return Some(listener), Err(_e) => {} } @@ -461,7 +456,7 @@ fn test_creating_connection() -> IFResult<()> { }); let t1 = std::thread::spawn(move || { interface1 - .send(&message, Some(String::from("127.0.0.1:50001"))) + .send(&message, Some(String::from("0.0.0.0:50001"))) .unwrap(); interface1 }); @@ -497,7 +492,7 @@ fn test_creating_connection() -> IFResult<()> { #[cfg(test)] pub fn create_test_interfaces(n: usize) -> impl Iterator { - let ip_addr = std::net::IpAddr::from_str("127.0.0.1").unwrap(); + let ip_addr = std::net::IpAddr::from_str("0.0.0.0").unwrap(); (0..n).map(move |i| { IPInterface::new( (5000 + 5 * i) as u16, diff --git a/src/ironforce.rs b/src/ironforce.rs index 41e15cf..963dc41 100644 --- a/src/ironforce.rs +++ b/src/ironforce.rs @@ -14,12 +14,12 @@ use std::println; const TUNNEL_MAX_REPEAT_COUNT: u32 = 3; #[cfg(feature = "std")] -const DEFAULT_FILE: &str = ".if_data.json"; +pub const DEFAULT_FILE: &str = ".if_data.json"; /// Main worker pub struct IronForce { /// Keys for this instance - keys: Keys, + pub keys: Keys, /// the struct that manages communicating with neighbor nodes transport: Transport, /// Tunnels that are known to this node @@ -90,12 +90,6 @@ impl IronForce { /// Create a new tunnel to another node fn initialize_tunnel_creation(&mut self, destination: &PublicKey) -> IFResult<()> { let tunnel = TunnelPublic::new_singlecast(); - #[cfg(std)] - println!( - "[{}] Tunnel for initialization: {:?}", - self.short_id(), - tunnel - ); self.tunnels_pending .push((tunnel.clone(), Some(destination.clone()), (0, 0))); let message = Message::build() @@ -113,7 +107,7 @@ impl IronForce { } /// Send a multicast or broadcast message - fn send_to_all(&mut self, message: Message) -> IFResult<()> { + pub fn send_to_all(&mut self, message: Message) -> IFResult<()> { self.transport .send_message(serde_cbor::to_vec(&message)?, None) } @@ -177,8 +171,6 @@ impl IronForce { if self.processed_messages.contains(&message.message_id) { return Ok(()); } - #[cfg(feature = "std")] - println!("[{}] {:?}", self.short_id(), message); self.processed_messages.push(message.message_id); match &message.message_type { MessageType::Service(msg_type) => { @@ -229,12 +221,6 @@ impl IronForce { } } ServiceMessageType::TunnelBuildingBackwardMovement(tunnel_p) => { - #[cfg(feature = "std")] - println!( - "[{}] Pending tunnels: {:?}", - self.short_id(), - self.tunnels_pending - ); match self.tunnels_pending.iter().find(|tun| { tunnel_p.local_ids.contains(tun.0.local_ids.last().unwrap()) }) { @@ -278,6 +264,8 @@ impl IronForce { } } MessageType::SingleCast if message.check_recipient(&self.keys) => { + #[cfg(feature = "std")] + println!("New message: {:?}", message.get_decrypted(&self.keys)); self.messages.push(message.clone()) } MessageType::SingleCast => { @@ -355,7 +343,12 @@ impl IronForce { #[cfg(feature = "std")] pub fn from_file(filename: alloc::string::String) -> IFResult { - Self::from_serialization_data(serde_json::from_str(std::fs::read_to_string(filename)?.as_str())?) + let filename = if filename.is_empty() { DEFAULT_FILE.to_string() } else { filename }; + if std::path::Path::new(&filename).exists() { + Self::from_serialization_data(serde_json::from_str(std::fs::read_to_string(filename)?.as_str())?) + } else { + Ok(Self::new()) + } } #[cfg(feature = "std")] diff --git a/src/lib.rs b/src/lib.rs index b73191a..5e068c7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -23,7 +23,9 @@ pub mod res; mod tunnel; -pub use ironforce::IronForce; +pub use ironforce::{IronForce, DEFAULT_FILE}; +pub use message::{Message, MessageType}; +pub use crypto::{Keys, PublicKey}; #[cfg(test)] mod tests {