diff --git a/src/interfaces/ip.rs b/src/interfaces/ip.rs index a3cea9b..3063cd3 100644 --- a/src/interfaces/ip.rs +++ b/src/interfaces/ip.rs @@ -3,16 +3,15 @@ use alloc::string::{String, ToString}; use alloc::vec; use alloc::vec::Vec; use core::ops::RangeInclusive; +#[cfg(test)] +use core::str::FromStr; use core::time::Duration; use rayon::prelude::*; -use std::net; use std::net::TcpStream; -#[cfg(test)] -use std::thread; +use std::{format, net}; use crate::interface::{Interface, InterfaceRequirements, TargetingData}; use crate::message::MessageBytes; -use crate::res::IFError::General; use crate::res::{IFError, IFResult}; use crate::std::io::{Read, Write}; use crate::std::println; @@ -30,10 +29,10 @@ pub struct IPInterface { connections: Vec, listener: net::TcpListener, peers: Vec, - package_queue: Vec, + package_queue: Vec<(IPPackage, String /* from_peer */)>, } -#[derive(Debug)] +#[derive(Debug, Clone)] struct IPPackage { version: u8, package_type: MessageType, @@ -41,7 +40,7 @@ struct IPPackage { message: MessageBytes, } -#[derive(Debug)] +#[derive(Debug, Copy, Clone)] enum MessageType { Common, PeerRequest, @@ -58,7 +57,7 @@ impl MessageType { } } - fn to_u8(&self) -> u8 { + fn as_u8(&self) -> u8 { match self { MessageType::Common => 0, MessageType::PeerRequest => 1, @@ -71,28 +70,47 @@ impl InterfaceRequirements for IPInterface {} impl Interface for IPInterface { fn main_loop_iteration(&mut self) -> IFResult<()> { - println!("Mainloop {:?}", self.listener.local_addr()); - println!("Incoming connections: {:?}", self.listener.incoming()); - - match self.listener.accept() { - Ok((stream, addr)) => { - println!("New client: {:?}", addr); - if self.peers.iter().all(|(ip, _)| *ip != addr.ip()) { - self.peers.push((addr.ip(), addr.port())); + if let Some(conn) = self.listener.incoming().next() { + match conn { + Ok(stream) => { + stream.set_nonblocking(true)?; + let addr = stream.peer_addr()?; + println!( + "({:?}): New client: {:?}", + addr, + self.listener.local_addr().unwrap() + ); + if self.peers.iter().all(|(ip, _)| *ip != addr.ip()) { + self.peers.push((addr.ip(), addr.port())); + } + self.connections.push(stream) } - self.connections.push(stream) + Err(ref e) if e.kind() == std::io::ErrorKind::WouldBlock => {} + Err(e) => return Err(IFError::from(e)), } - Err(_e) => return Err(IFError::General(String::from("No incoming connection"))), } - - println!("Hello from mainloop"); let mut new_connections: Vec = vec![]; for connection in &mut self.connections { + connection.set_nonblocking(true)?; let mut header: [u8; 6] = [0, 0, 0, 0, 0, 0]; - connection.read_exact(&mut header)?; + match connection.read_exact(&mut header) { + Ok(_) => {} + Err(ref e) + if e.kind() == std::io::ErrorKind::WouldBlock + || e.kind() == std::io::ErrorKind::UnexpectedEof => + { + continue + } + Err(e) => { + println!("Error: {:?}", e); + continue; + } + }; let version = header[0]; let package_type = MessageType::from_u8(header[1])?; let size = bytes_to_size([header[2], header[3], header[4], header[5]]); + connection.set_nonblocking(false)?; + connection.set_read_timeout(Some(std::time::Duration::from_millis(500)))?; let mut message_take = connection.take(size as u64); let mut message: Vec = vec![]; @@ -110,7 +128,7 @@ impl Interface for IPInterface { connection, IPPackage { version, - package_type, + package_type: MessageType::PeersShared, size: message.len() as u32, message, }, @@ -123,7 +141,8 @@ impl Interface for IPInterface { size, message, }; - self.package_queue.push(package); + self.package_queue + .push((package, format!("{:?}", connection.peer_addr()?))); } MessageType::PeersShared => { let peers: Vec = serde_cbor::from_slice(message.as_slice())?; @@ -153,62 +172,57 @@ impl Interface for IPInterface { &*self.id } fn send(&mut self, message: &[u8], interface_data: Option) -> IFResult<()> { - let addr: net::SocketAddr = match interface_data { - Some(ip_string) => ip_string.parse().expect("Unable to parse address"), - None => { - return Err(IFError::General(String::from( - "Not enough info to create connections", - ))) - } - }; + println!( + "({:?}): Connecting to {:?} to send a message", + self.listener.local_addr().unwrap(), + interface_data + ); - println!("Connecting to {:?}", addr); + let package = IPPackage { + version: 0, + package_type: MessageType::Common, + size: message.len() as u32, + message: Vec::from(message), + }; - let index = match self - .connections - .iter() - .position(|connection| connection.peer_addr().ok() == Some(addr)) - { + match interface_data { + 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 => { - let connection = match net::TcpStream::connect_timeout(&addr, Duration::new(1, 0)) { - Ok(connection) => connection, - Err(_) => return Err(General(String::from("Can't connect to this port"))), - }; - self.connections.push(connection); - self.connections.len() - 1 + for conn in &mut self.connections { + IPInterface::send_package(conn, package.clone())?; + } } - Some(i) => i, }; - println!( - "Sending message to {:?}", - self.connections[index].peer_addr().unwrap() - ); - - self.connections[index].set_write_timeout(Some(Duration::new(1, 0)))?; - - IPInterface::send_package( - &mut self.connections[index], - IPPackage { - version: 0, - package_type: MessageType::Common, - size: message.len() as u32, - message: Vec::from(message), - }, - )?; println!("Sent message"); Ok(()) } fn receive(&mut self) -> IFResult> { + if !self.package_queue.is_empty() { + println!( + "({:?}): New message from {}", + self.listener.local_addr().unwrap(), + self.package_queue.last().unwrap().1 + ); + } match self.package_queue.pop() { - Some(ip_package) => Ok(Some((ip_package.message, "".to_string()))), + Some((ip_package, data)) => Ok(Some((ip_package.message, data))), None => Ok(None), } } } impl IPInterface { - pub fn new(peers: Vec) -> IFResult { - let listener = match create_tcp_listener() { + pub fn new(port: u16, peers: Vec) -> IFResult { + let listener = match create_tcp_listener(port) { Some(listener) => listener, None => { return Err(IFError::General(String::from( @@ -250,7 +264,10 @@ impl IPInterface { } fn send_package(stream: &mut net::TcpStream, package: IPPackage) -> IFResult<()> { - let mut header: Vec = vec![package.version, package.package_type.to_u8()]; + stream.set_write_timeout(Some(std::time::Duration::from_millis(700)))?; + #[cfg(test)] + stream.set_nonblocking(false)?; + let mut header: Vec = vec![package.version, package.package_type.as_u8()]; for byte in size_to_bytes(package.size) { header.push(byte); } @@ -280,22 +297,26 @@ impl IPInterface { Ok(()) } - fn obtain_connection(&mut self, addr: &Peer) -> IFResult<()> { - if self - .connections - .iter() - .any(|con| con.peer_addr().is_ok() && con.peer_addr().unwrap().ip() == addr.0) - { - return Ok(()); + fn obtain_connection(&mut self, addr: &Peer) -> IFResult { + fn compare_addrs(peer: &Peer, addr: net::SocketAddr) -> bool { + addr.ip() == peer.0 && addr.port() == peer.1 + } + + if let Some(pos) = self.connections.iter().position(|con| { + con.peer_addr().is_ok() && compare_addrs(addr, con.peer_addr().unwrap()) + }) { + return Ok(pos); } if let Some(conn) = Self::new_connection(addr)? { - self.connections.push(conn) + self.connections.push(conn); + Ok(self.connections.len() - 1) + } else { + Err(IFError::CouldNotConnect) } - Ok(()) } fn new_connection(addr: &Peer) -> IFResult> { - for port in addr.1 - 5..addr.1 + 5 { + for port in addr.1..addr.1 + 3 { match net::TcpStream::connect_timeout( &net::SocketAddr::new(addr.0, port as u16), Duration::from_millis(500), @@ -310,8 +331,8 @@ impl IPInterface { } } -fn create_tcp_listener() -> Option { - for port in SOCKET_RANGE { +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()) { Ok(listener) => return Some(listener), Err(_e) => {} @@ -348,22 +369,25 @@ fn bytes_to_size(arr: [u8; 4]) -> u32 { #[test] fn test_creating_connection() -> IFResult<()> { - let message = *b"Hello world from iron forest"; + let message = *b"Hello world from ironforest"; + let original_msg_copy = message; - let mut interface1 = IPInterface::new(vec![])?; - let mut interface2 = IPInterface::new(vec![])?; + let mut interface1 = IPInterface::new(50000, vec![])?; + let mut interface2 = IPInterface::new(50001, vec![])?; + let t2 = std::thread::spawn(move || { + for _ in 0..30 { + interface2.main_loop_iteration().unwrap(); + std::thread::sleep(std::time::Duration::from_millis(150)); + } + interface2 + }); let t1 = std::thread::spawn(move || { interface1 .send(&message, Some(String::from("127.0.0.1:50001"))) .unwrap(); interface1 }); - thread::sleep(Duration::from_millis(10)); - let t2 = std::thread::spawn(move || { - interface2.main_loop_iteration().unwrap(); - interface2 - }); let res1 = t1.join(); match res1 { Ok(_res) => { @@ -377,8 +401,14 @@ fn test_creating_connection() -> IFResult<()> { println!("Thread Ok"); match res.receive() { Ok(tmp) => match tmp { - Some((message, _metadata)) => println!("Received {:?}", message), - None => println!("None"), + Some((message, _metadata)) => { + println!("Received {:?}", message); + assert_eq!(message, original_msg_copy) + } + None => { + println!("None"); + panic!(); + } }, Err(e) => println!("{:?}", e), } @@ -389,4 +419,17 @@ fn test_creating_connection() -> IFResult<()> { } #[cfg(test)] -pub mod test_ip_interface {} +fn create_test_interfaces(n: usize) -> impl Iterator { + let ip_addr = std::net::IpAddr::from_str("127.0.0.1").unwrap(); + (0..n).map(move |i| { + IPInterface::new( + (5000 + 5 * i) as u16, + // (0..n) + // .filter(|j| *j != i) + // .map(|j| (ip_addr, (5000 + 5 * j) as u16)) + // .collect(), + vec![(ip_addr, (5000 + 5 * ((i + 5) % n)) as u16)], + ) + .unwrap() + }) +} diff --git a/src/ironforce.rs b/src/ironforce.rs index a836497..4e2a0df 100644 --- a/src/ironforce.rs +++ b/src/ironforce.rs @@ -3,8 +3,13 @@ use crate::message::{Message, MessageType, ServiceMessageType}; use crate::res::{IFError, IFResult}; use crate::transport::Transport; use crate::tunnel::{Tunnel, TunnelPublic}; +use alloc::collections::BTreeMap; use alloc::vec; use alloc::vec::Vec; +#[cfg(feature = "std")] +use std::println; + +const TUNNEL_MAX_REPEAT_COUNT: u32 = 3; /// Main worker pub struct IronForce { @@ -23,11 +28,19 @@ pub struct IronForce { /// Tunnels that has not been confirmed yet (no backward spread) /// /// `[(Tunnel, Optional target node, local peer ids)]` - tunnels_pending: Vec<(TunnelPublic, Option /* target node */, (u64, u64) /* local peer ids */)>, + tunnels_pending: Vec<( + TunnelPublic, + Option, /* target node */ + (u64, u64), /* local peer ids */ + )>, /// True if this instance has background thread has_background_worker: bool, /// Messages that were already processed (stored to avoid "echo chambers") processed_messages: Vec, + /// Counters of how many times the tunnel has passed through this node on its forward movement (so that we don't do a shitposting) + /// + /// Maps tunnel's first local_id to the number + tunnel_counters: BTreeMap, } impl IronForce { @@ -42,12 +55,19 @@ impl IronForce { tunnels_pending: vec![], has_background_worker: false, processed_messages: vec![], + tunnel_counters: Default::default(), } } /// 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() @@ -77,7 +97,16 @@ impl IronForce { mut message: Message, direction: Option, ) -> IFResult<()> { - let tunnel: Tunnel = if let Some(tun) = self.tunnels.iter().cloned().find(|t| t.id == Some(tunnel_id)) { tun } else { return Err(IFError::TunnelNotFound) }; + let tunnel: Tunnel = if let Some(tun) = self + .tunnels + .iter() + .cloned() + .find(|t| t.id == Some(tunnel_id)) + { + tun + } else { + return Err(IFError::TunnelNotFound); + }; message.tunnel_id = tunnel_id; let peer_ids = match (direction, tunnel.peer_ids) { (_, (x, 0)) => vec![x], @@ -120,79 +149,112 @@ 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) => match msg_type { - ServiceMessageType::TunnelBuildingForwardMovement(tunnel, sender_enc) => { - if message.check_recipient(&self.keys) { - let mut tunnel_pub = tunnel.clone(); - tunnel_pub.id = Some(rand::random()); - let sender = PublicKey::from_vec(self.keys.decrypt_data(sender_enc)?)?; - let tunnel = Tunnel { - id: tunnel_pub.id, - local_ids: tunnel_pub.local_ids.clone(), - peer_ids: (inc_peer, 0), - ttd: 0, - nodes_in_tunnel: None, - is_multicast: false, - target_node: Some(sender.clone()), - }; - self.tunnels.push(tunnel); - self.send_to_all( - Message::build() - .message_type(MessageType::Service( - ServiceMessageType::TunnelBuildingBackwardMovement(tunnel_pub.clone()), - )) - .tunnel(tunnel_pub.id.unwrap()) - .sign(&self.keys) - .build()? - )?; - } else { - let mut tunnel = tunnel.clone(); - tunnel.local_ids.push(rand::random()); - self.tunnels_pending.push((tunnel.clone(), None, (inc_peer, 0))); - self.send_to_all(message)?; - } - } - ServiceMessageType::TunnelBuildingBackwardMovement(tunnel_p) => { - match self - .tunnels_pending - .iter() - .find(|tun| tunnel_p.local_ids.contains(tun.0.local_ids.last().unwrap())) - { - // This doesn't concern us - None => {} - // This is a tunnel initialization proposed by us (and we got it back, yay) - Some((_, Some(target), peers)) => { - let tunnel = Tunnel { - id: tunnel_p.id, - local_ids: tunnel_p.local_ids.clone(), - peer_ids: (peers.0, inc_peer), - ttd: 0, - nodes_in_tunnel: None, - is_multicast: false, - target_node: Some(target.clone()), - }; - self.tunnels.push(tunnel); - // Send some initialization message or something + MessageType::Service(msg_type) => { + match msg_type { + ServiceMessageType::TunnelBuildingForwardMovement(tunnel, sender_enc) => { + let count = *self + .tunnel_counters + .get(&tunnel.local_ids[0]) + .unwrap_or(&0u32); + if count > TUNNEL_MAX_REPEAT_COUNT { + return Ok(()); } - // This is a tunnel initialization proposed by someone else that has passed through us on its forward movement - Some((_, None, peers)) => { + self.tunnel_counters.insert(tunnel.local_ids[0], count + 1); + if message.check_recipient(&self.keys) { + let mut tunnel_pub = tunnel.clone(); + tunnel_pub.id = Some(rand::random()); + let sender = PublicKey::from_vec(self.keys.decrypt_data(sender_enc)?)?; let tunnel = Tunnel { - id: tunnel_p.id, - local_ids: tunnel_p.local_ids.clone(), - peer_ids: (peers.0, inc_peer), + id: tunnel_pub.id, + local_ids: tunnel_pub.local_ids.clone(), + peer_ids: (inc_peer, 0), ttd: 0, nodes_in_tunnel: None, is_multicast: false, - target_node: None + target_node: Some(sender), }; + #[cfg(feature = "std")] + println!( + "[{}] Got an incoming tunnel for me! {:?}", + self.short_id(), + tunnel_pub + ); self.tunnels.push(tunnel); - self.transport.send_message(serde_cbor::to_vec(&message)?, Some(peers.0))?; + self.transport.send_message( + serde_cbor::to_vec( + &Message::build() + .message_type(MessageType::Service( + ServiceMessageType::TunnelBuildingBackwardMovement( + tunnel_pub.clone(), + ), + )) + .tunnel(tunnel_pub.id.unwrap()) + .sign(&self.keys) + .build()?, + )?, + Some(inc_peer), + )?; + } else { + let mut tunnel = tunnel.clone(); + tunnel.add_local_id(); + self.tunnels_pending + .push((tunnel.clone(), None, (inc_peer, 0))); + self.send_to_all(message)?; + } + } + 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()) + }) { + // This doesn't concern us + None => {} + // This is a tunnel initialization proposed by us (and we got it back, yay) + Some((_, Some(target), peers)) => { + let tunnel = Tunnel { + id: tunnel_p.id, + local_ids: tunnel_p.local_ids.clone(), + peer_ids: (peers.0, inc_peer), + ttd: 0, + nodes_in_tunnel: None, + is_multicast: false, + target_node: Some(target.clone()), + }; + self.tunnels.push(tunnel); + #[cfg(feature = "std")] + println!("[{}] Successfully created a new tunnel", self.short_id()); + // Send some initialization message or something + } + // This is a tunnel initialization proposed by someone else that has passed through us on its forward movement + Some((_, None, peers)) => { + let tunnel = Tunnel { + id: tunnel_p.id, + local_ids: tunnel_p.local_ids.clone(), + peer_ids: (peers.0, inc_peer), + ttd: 0, + nodes_in_tunnel: None, + is_multicast: false, + target_node: None, + }; + self.tunnels.push(tunnel); + #[cfg(feature = "std")] + println!("[{}] Successfully created a new tunnel", self.short_id()); + self.transport + .send_message(serde_cbor::to_vec(&message)?, Some(peers.0))?; + } } } } - }, + } MessageType::SingleCast | MessageType::Broadcast => self.messages.push(message), } Ok(()) @@ -210,6 +272,19 @@ impl IronForce { } Ok(()) } + + fn short_id(&self) -> alloc::string::String { + let vec_data = self.keys.get_public().to_vec(); + alloc::string::String::from_utf8( + vec_data + .iter() + .skip(90) + .take(5) + .map(|c| c % 26 + 97) + .collect::>(), + ) + .unwrap() + } } #[cfg(test)] @@ -217,12 +292,12 @@ mod if_testing { use crate::crypto::Keys; use crate::interface::test_interface::create_test_interfaces; use crate::ironforce::IronForce; + use crate::message::{Message, MessageType}; use crate::res::IFResult; use crate::transport::Transport; use alloc::boxed::Box; use alloc::vec; use alloc::vec::Vec; - use crate::message::{Message, MessageType}; fn create_test_network() -> Vec { let interfaces = create_test_interfaces(5); @@ -239,6 +314,7 @@ mod if_testing { tunnels_pending: vec![], has_background_worker: false, processed_messages: vec![], + tunnel_counters: Default::default(), }) .collect() } @@ -271,11 +347,119 @@ mod if_testing { .recipient(key_1.clone()) .content(b"hello".to_vec()) .build()?, - key_1)?; + key_1, + )?; network[1].main_loop_iteration()?; let msg = network[1].read_message(); assert!(msg.is_some()); - assert_eq!(msg.unwrap().get_decrypted(&network[1].keys).unwrap().as_slice(), b"hello"); + assert_eq!( + msg.unwrap() + .get_decrypted(&network[1].keys) + .unwrap() + .as_slice(), + b"hello" + ); + Ok(()) + } +} + +#[cfg(test)] +#[cfg(feature = "std")] +mod test_with_ip { + use crate::crypto::Keys; + use crate::interfaces::ip::IPInterface; + use crate::ironforce::IronForce; + use crate::res::IFResult; + use crate::transport::Transport; + use alloc::boxed::Box; + use alloc::vec; + use alloc::vec::Vec; + use core::str::FromStr; + use std::println; + + fn create_test_interfaces(n: usize) -> impl Iterator { + let ip_addr = std::net::IpAddr::from_str("127.0.0.1").unwrap(); + (0..n).map(move |i| { + IPInterface::new( + (5000 + 5 * i) as u16, + (0..n) + .filter(|j| *j != i) + .map(|j| (ip_addr, (5000 + 5 * j) as u16)) + .collect(), + ) + .unwrap() + }) + } + + fn create_test_network() -> Vec { + let interfaces = create_test_interfaces(4); + let transports = interfaces + .into_iter() + .map(|interface| Transport::new(vec![Box::new(interface)])); + transports + .map(|tr| IronForce { + keys: Keys::generate(), + transport: tr, + additional_modules: vec![], + tunnels: vec![], + messages: vec![], + tunnels_pending: vec![], + has_background_worker: false, + processed_messages: vec![], + tunnel_counters: Default::default() + }) + .collect() + } + + #[test] + fn test_creating_a_tunnel() -> IFResult<()> { + let mut network = create_test_network(); + let key_1 = network[1].keys.get_public(); + let (mut node0, mut node1) = (network.remove(0), network.remove(0)); + println!("node0 id: {}", node0.short_id()); + println!("node1 id: {}", node1.short_id()); + let (mut node2, mut node3) = (network.remove(0), network.remove(0)); + let t1 = std::thread::spawn(move || { + for _i in 0..5 { + // println!("Iteration {} (1)", i); + node0.main_loop_iteration().unwrap(); + } + node0 + }); + let t2 = std::thread::spawn(move || { + for _i in 0..15 { + // println!("Iteration {} (2)", i); + node1.main_loop_iteration().unwrap(); + } + node1 + }); + std::thread::spawn(move || loop { + node2.main_loop_iteration().unwrap(); + std::thread::sleep(std::time::Duration::from_secs(5)); + }); + std::thread::spawn(move || loop { + std::thread::sleep(std::time::Duration::from_secs(5)); + node3.main_loop_iteration().unwrap(); + }); + let mut node0 = t1.join().unwrap(); + node0.initialize_tunnel_creation(key_1)?; + let mut node1 = t2.join().unwrap(); + let t1 = std::thread::spawn(move || { + for _ in 0..18 { + node0.main_loop_iteration().unwrap(); + std::thread::sleep(std::time::Duration::from_millis(150)); + } + node0 + }); + let t2 = std::thread::spawn(move || { + for _ in 0..18 { + node1.main_loop_iteration().unwrap(); + } + node1 + }); + let node0 = t1.join().unwrap(); + t2.join().unwrap(); + assert!(!node0.tunnels.is_empty()); Ok(()) } } diff --git a/src/res.rs b/src/res.rs index 601039a..e2ef4cf 100644 --- a/src/res.rs +++ b/src/res.rs @@ -9,6 +9,8 @@ pub enum IFError { General(String), /// A tunnel satisfying some conditions has not been found TunnelNotFound, + /// Could not establish a connection + CouldNotConnect, /// Error during serialization SerializationError(String), /// Error in rsa diff --git a/src/tunnel.rs b/src/tunnel.rs index 07d52f8..8d02aa6 100644 --- a/src/tunnel.rs +++ b/src/tunnel.rs @@ -41,13 +41,15 @@ pub struct TunnelPublic { impl TunnelPublic { pub fn new_singlecast() -> Self { - Self { + let mut tun = Self { id: None, - local_ids: vec![rand::random()], + local_ids: vec![], ttd: 0, nodes_in_tunnel: None, is_multicast: false, - } + }; + tun.add_local_id(); + tun } /// Get the hash of the tunnel for verification @@ -67,6 +69,17 @@ impl TunnelPublic { is_multicast: true, } } + + pub fn add_local_id(&mut self) -> u64 { + let local_id = rand::random(); + // Add 0 to 7 random ids so it's impossible to get the length of the tunnel + // todo: enable it (after debug) + // for _ in 0..(rand::random() as u64 % 7) { + // self.local_ids.push(rand::random()) + // } + self.local_ids.push(local_id); + local_id + } } #[test]