|
|
|
@ -1,19 +1,29 @@
|
|
|
|
|
use alloc::borrow::ToOwned; |
|
|
|
|
use std::net; |
|
|
|
|
use std::thread; |
|
|
|
|
use alloc::vec; |
|
|
|
|
use alloc::vec::Vec; |
|
|
|
|
use alloc::string::String; |
|
|
|
|
use alloc::string::{String, ToString}; |
|
|
|
|
use core::cmp::min; |
|
|
|
|
use core::ops::RangeInclusive; |
|
|
|
|
use core::str::from_utf8; |
|
|
|
|
use core::time::Duration; |
|
|
|
|
|
|
|
|
|
use crate::interface::{Interface, InterfaceRequirements, TargetingData}; |
|
|
|
|
use crate::message::MessageBytes; |
|
|
|
|
use crate::res::{IFError, IFResult}; |
|
|
|
|
use crate::res::IFError::General; |
|
|
|
|
use crate::std::io::{Read, Write}; |
|
|
|
|
use crate::std::println; |
|
|
|
|
|
|
|
|
|
const SOCKET_RANGE: RangeInclusive<i32> = 50000..=50010; |
|
|
|
|
|
|
|
|
|
/// Interface for interactions using tcp sockets
|
|
|
|
|
pub struct IPInterface { |
|
|
|
|
pub id: String, |
|
|
|
|
pub connections: Vec<net::TcpStream>, |
|
|
|
|
pub listener: net::TcpListener, |
|
|
|
|
id: String, |
|
|
|
|
connections: Vec<net::TcpStream>, |
|
|
|
|
listener: net::TcpListener, |
|
|
|
|
peers: Vec<net::IpAddr>, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
impl InterfaceRequirements for IPInterface {} |
|
|
|
@ -21,41 +31,35 @@ 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); |
|
|
|
|
self.connections.push(stream) |
|
|
|
|
} |
|
|
|
|
Err(e) => println!("couldn't get client: {:?}", e), |
|
|
|
|
Err(e) => return Err(IFError::General(String::from("No incoming connection"))), |
|
|
|
|
} |
|
|
|
|
// for stream in self.listener.incoming() {
|
|
|
|
|
// println!("Accepting stream...");
|
|
|
|
|
//
|
|
|
|
|
// match stream {
|
|
|
|
|
// Ok(stream) => {
|
|
|
|
|
// self.connections.push(stream);
|
|
|
|
|
// println!("Stream accepted");
|
|
|
|
|
// }
|
|
|
|
|
// Err(e) => { println!("Accepting failed"); return Err(IFError::General(String::from("Stream error"))); }
|
|
|
|
|
// }
|
|
|
|
|
// println!("End of cycle")
|
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
println!("Hello from mainloop"); |
|
|
|
|
for mut connection in &self.connections { |
|
|
|
|
let mut size_arr: [u8; 4] = [0, 0, 0, 0]; |
|
|
|
|
connection.read_exact(&mut size_arr)?; |
|
|
|
|
let mut size: u32 = 0; |
|
|
|
|
for size_byte in &size_arr { |
|
|
|
|
size = size * 256 + *size_byte as u32; |
|
|
|
|
} |
|
|
|
|
let mut size = bytes_to_size(size_arr) as u32; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let mut message_take = connection.take(size as u64); |
|
|
|
|
let mut message: Vec<u8> = vec![]; |
|
|
|
|
message_take.read_to_end(&mut message); |
|
|
|
|
println!("Size: {:?}", size); |
|
|
|
|
println!("Message: {:?}", from_utf8(&*message)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn has_blocking_main(&self) -> bool { |
|
|
|
|
true |
|
|
|
|
false |
|
|
|
|
} |
|
|
|
|
fn id(&self) -> &str { |
|
|
|
|
&*self.id |
|
|
|
@ -63,18 +67,31 @@ impl Interface for IPInterface {
|
|
|
|
|
fn send(&mut self, message: &[u8], interface_data: Option<TargetingData>) -> 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 connection"))) |
|
|
|
|
None => return Err(IFError::General(String::from("Not enough info to create connections"))) |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
println!("Connecting to {:?}", addr); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let index = match self.connections.iter().position(|connection| connection.peer_addr().ok() == Some(addr)) { |
|
|
|
|
None => { |
|
|
|
|
self.connections.push(net::TcpStream::connect(addr)?); |
|
|
|
|
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 |
|
|
|
|
} |
|
|
|
|
Some(i) => i |
|
|
|
|
}; |
|
|
|
|
println!("Sending message to {:?}", self.connections[index].peer_addr().unwrap()); |
|
|
|
|
|
|
|
|
|
self.connections[index].set_write_timeout(Some(Duration::new(1, 0)))?; |
|
|
|
|
|
|
|
|
|
self.connections[index].write_all(&size_to_bytes(message.len()))?; |
|
|
|
|
self.connections[index].write_all(message)?; |
|
|
|
|
println!("Sent message"); |
|
|
|
|
Ok(()) |
|
|
|
@ -82,49 +99,95 @@ impl Interface for IPInterface {
|
|
|
|
|
fn receive(&mut self) -> IFResult<Option<(MessageBytes, TargetingData)>> { todo!() } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
|
use alloc::vec; |
|
|
|
|
impl IPInterface { |
|
|
|
|
pub fn new() -> IFResult<Self> { |
|
|
|
|
let mut listener = match create_tcp_listener() { |
|
|
|
|
Some(listener) => listener, |
|
|
|
|
None => { |
|
|
|
|
return Err(IFError::General(String::from("Unable to open TCP listener"))); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
fn test_creating_connection() { |
|
|
|
|
let listener = match net::TcpListener::bind("0.0.0.0:60000") { |
|
|
|
|
Ok(tmp) => tmp, |
|
|
|
|
Err(_) => { return; } |
|
|
|
|
}; |
|
|
|
|
let mut interface1 = IPInterface { |
|
|
|
|
id: String::from("IP interface"), |
|
|
|
|
connections: vec![], |
|
|
|
|
listener, |
|
|
|
|
}; |
|
|
|
|
listener.set_nonblocking(true)?; |
|
|
|
|
|
|
|
|
|
let listener = match net::TcpListener::bind("0.0.0.0:50000") { |
|
|
|
|
Ok(tmp) => tmp, |
|
|
|
|
Err(_) => { return; } |
|
|
|
|
}; |
|
|
|
|
let mut interface2 = IPInterface { |
|
|
|
|
id: String::from("IP interface"), |
|
|
|
|
connections: vec![], |
|
|
|
|
listener, |
|
|
|
|
Ok(IPInterface { |
|
|
|
|
id: String::from("IP Interface"), |
|
|
|
|
connections: vec!(), |
|
|
|
|
listener, |
|
|
|
|
peers: vec!(), |
|
|
|
|
}) |
|
|
|
|
} |
|
|
|
|
pub fn dump(&self) -> IFResult<Vec<u8>> { |
|
|
|
|
Ok(serde_cbor::to_vec(&self.peers)?) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
pub fn load(&mut self, data: Vec<u8>) -> IFResult<()> { |
|
|
|
|
let peers: Vec<net::IpAddr> = serde_cbor::from_slice(&data)?; |
|
|
|
|
self.peers = peers; |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn create_tcp_listener() -> Option<net::TcpListener> { |
|
|
|
|
for port in SOCKET_RANGE { |
|
|
|
|
match net::TcpListener::bind("127.0.0.1:".to_owned() + &port.to_string()) { |
|
|
|
|
Ok(listener) => return Some(listener), |
|
|
|
|
Err(e) => {} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
None |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
fn size_to_bytes(mut a: usize) -> [u8; 4] { |
|
|
|
|
let mut arr: [u8; 4] = [0, 0, 0, 0]; |
|
|
|
|
for i in [3, 2, 1, 0] { |
|
|
|
|
arr[i] = (a % 256) as u8; |
|
|
|
|
a /= 256; |
|
|
|
|
} |
|
|
|
|
arr |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
fn bytes_to_size(arr: [u8; 4]) -> usize { |
|
|
|
|
let mut size = 0; |
|
|
|
|
for size_byte in &arr { |
|
|
|
|
size = size * 256 + *size_byte as u32; |
|
|
|
|
} |
|
|
|
|
size as usize |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[test] |
|
|
|
|
fn test_creating_connection() -> IFResult<()> { |
|
|
|
|
let message = *b"Hello world from iron forest"; |
|
|
|
|
|
|
|
|
|
let mut interface1 = IPInterface::new()?; |
|
|
|
|
let mut interface2 = IPInterface::new()?; |
|
|
|
|
|
|
|
|
|
let t1 = std::thread::spawn(move || { |
|
|
|
|
interface1.send(&[0, 0, 1, 1], Some(String::from("0.0.0.0:50000"))).unwrap(); |
|
|
|
|
interface1 |
|
|
|
|
interface1.send(&message, Some(String::from("127.0.0.1:50000"))) |
|
|
|
|
}); |
|
|
|
|
thread::sleep(Duration::from_millis(10)); |
|
|
|
|
let t2 = std::thread::spawn(move || { |
|
|
|
|
interface2.main_loop_iteration().unwrap(); |
|
|
|
|
interface2 |
|
|
|
|
interface2.main_loop_iteration() |
|
|
|
|
}); |
|
|
|
|
let res1 = t1.join(); |
|
|
|
|
match res1 { |
|
|
|
|
Ok(_) => println!("Ok"), |
|
|
|
|
Ok(res) => { |
|
|
|
|
println!("Thread Ok"); |
|
|
|
|
println!("interface1: {:?}", res) |
|
|
|
|
}, |
|
|
|
|
Err(e) => println!("{:?}", e) |
|
|
|
|
} |
|
|
|
|
let res2 = t2.join(); |
|
|
|
|
match res2 { |
|
|
|
|
Ok(_) => println!("Ok"), |
|
|
|
|
Ok(res) => { |
|
|
|
|
println!("Thread Ok"); |
|
|
|
|
println!("interface2: {:?}", res) |
|
|
|
|
}, |
|
|
|
|
Err(e) => println!("{:?}", e) |
|
|
|
|
} |
|
|
|
|
Ok(()) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#[cfg(test)] |
|
|
|
|