mirror of
https://github.com/Astatin3/unshell-nodes-rs.git
synced 2026-06-09 00:28:00 -06:00
Work on,making streams
This commit is contained in:
+81
-39
@@ -1,8 +1,14 @@
|
|||||||
use std::time::Instant;
|
use std::{
|
||||||
|
io::{Read, Write, stdin, stdout},
|
||||||
|
thread,
|
||||||
|
};
|
||||||
|
|
||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use portable_pty::{PtySize, native_pty_system};
|
use unshell_rs_lib::{
|
||||||
use unshell_rs_lib::{C2Packet, Error, nodes::NodeContainer};
|
Error,
|
||||||
|
networkers::Connection,
|
||||||
|
nodes::{NodeContainer, Stream},
|
||||||
|
};
|
||||||
|
|
||||||
use crate::client::cli::{Cli, CommandHolder};
|
use crate::client::cli::{Cli, CommandHolder};
|
||||||
|
|
||||||
@@ -17,8 +23,10 @@ pub enum NodeCliCommands {
|
|||||||
Nodes,
|
Nodes,
|
||||||
/// Send a ping to a remote node
|
/// Send a ping to a remote node
|
||||||
Ping { n: usize },
|
Ping { n: usize },
|
||||||
|
// /// Attempt to create a shell at a remote node
|
||||||
|
// Sh { n: usize },
|
||||||
/// Attempt to create a shell at a remote node
|
/// Attempt to create a shell at a remote node
|
||||||
Sh { n: usize },
|
Stream { n: usize },
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Cli for NodeCli {
|
impl Cli for NodeCli {
|
||||||
@@ -40,46 +48,50 @@ impl Cli for NodeCli {
|
|||||||
info!("[{}] {}", i + 1, node);
|
info!("[{}] {}", i + 1, node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NodeCliCommands::Ping { n } => {
|
NodeCliCommands::Ping { .. } => {
|
||||||
// if split.count().clone() <= 1 {
|
// if split.count().clone() <= 1 {
|
||||||
// warn!("You must specify an option");
|
// warn!("You must specify an option");
|
||||||
// continue;
|
// continue;
|
||||||
// }
|
// }
|
||||||
|
|
||||||
if n <= 0 {
|
// if n <= 0 {
|
||||||
warn!("Node id must be greater than zero");
|
// warn!("Node id must be greater than zero");
|
||||||
} else if n > node_ids.len() {
|
// } else if n > node_ids.len() {
|
||||||
warn!("Node id {} is out of maximum range {}", n, node_ids.len());
|
// warn!("Node id {} is out of maximum range {}", n, node_ids.len());
|
||||||
} else {
|
// } else {
|
||||||
let start = Instant::now();
|
// let start = Instant::now();
|
||||||
let node = node_ids.get(n - 1).unwrap().clone();
|
// let node = node_ids.get(n - 1).unwrap().clone();
|
||||||
self.node.send_unrouted(&node, &C2Packet::Ping).unwrap();
|
// self.node.send_unrouted(&node, &C2Packet::Ping).unwrap();
|
||||||
info!("Sent ping...");
|
// info!("Sent ping...");
|
||||||
|
|
||||||
let (_, packet) = self.node.read_packet()?;
|
// let (_, packet) = self.node.read()?;
|
||||||
match packet {
|
// match packet {
|
||||||
C2Packet::Pong => {
|
// C2Packet::Pong => {
|
||||||
// if src != nod
|
// // if src != nod
|
||||||
info!(
|
// info!(
|
||||||
"Pong! Latency: {}ms",
|
// "Pong! Latency: {}ms",
|
||||||
(start.elapsed().as_micros() as f32) / 1000.
|
// (start.elapsed().as_micros() as f32) / 1000.
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
_ => {
|
// _ => {
|
||||||
error!("Got incorrect packet: {:?}", packet);
|
// error!("Got incorrect packet: {:?}", packet);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
// node_state = self.node.state.lock().unwrap();
|
// // node_state = self.node.state.lock().unwrap();
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
}
|
NodeCliCommands::Stream { n } => {
|
||||||
NodeCliCommands::Sh { n } => {
|
|
||||||
if n <= 0 {
|
if n <= 0 {
|
||||||
warn!("Node id must be greater than zero");
|
warn!("Node id must be greater than zero");
|
||||||
} else if n > node_ids.len() {
|
} else if n > node_ids.len() {
|
||||||
warn!("Node id {} is out of maximum range {}", n, node_ids.len());
|
warn!("Node id {} is out of maximum range {}", n, node_ids.len());
|
||||||
} else {
|
} else {
|
||||||
let node_id = node_ids.get(n - 1).unwrap().clone();
|
let node_id = node_ids.get(n - 1).unwrap().clone();
|
||||||
|
|
||||||
|
let stream = self.node.create_stream_block(node_id)?;
|
||||||
|
|
||||||
|
self.run_pty(stream)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,17 +108,47 @@ impl NodeCli {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn run_pty(&mut self) -> Result<(), Error> {
|
pub fn run_pty(&mut self, mut stream: Stream) -> Result<(), Error> {
|
||||||
let pty_system = native_pty_system();
|
let mut stream_clone = stream.try_clone()?;
|
||||||
let pty_pair = pty_system.openpty(PtySize {
|
|
||||||
rows: 24,
|
// Thread to read from stdin and write to TCP stream
|
||||||
cols: 80,
|
let stdin_to_tcp = thread::spawn(move || {
|
||||||
pixel_width: 0,
|
let mut stdin = stdin();
|
||||||
pixel_height: 0,
|
let mut buffer = [0u8; 1024];
|
||||||
})?;
|
loop {
|
||||||
|
match stdin.read(&mut buffer) {
|
||||||
|
Ok(0) => break, // EOF
|
||||||
|
Ok(n) => {
|
||||||
|
if stream.write(&buffer[..n]).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => {
|
||||||
|
error!("Error reading from stdin: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Thread to read from TCP stream and write to stdout
|
||||||
|
let tcp_to_stdout = thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
let data = stream_clone.read().unwrap();
|
||||||
|
if stdout().write_all(&data).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
stdout().flush().ok();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for either thread to finish
|
||||||
|
let _ = stdin_to_tcp.join();
|
||||||
|
let _ = tcp_to_stdout.join();
|
||||||
|
|
||||||
|
error!("Disconnected from server");
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
||||||
// pty_pair.Ok(())
|
// pty_pair.Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+84
-11
@@ -1,7 +1,9 @@
|
|||||||
use std::net::SocketAddr;
|
use std::{net::SocketAddr, thread};
|
||||||
|
|
||||||
|
use portable_pty::{CommandBuilder, PtySize, native_pty_system};
|
||||||
use unshell_rs_lib::{
|
use unshell_rs_lib::{
|
||||||
C2Packet, Error,
|
Error,
|
||||||
|
networkers::Connection,
|
||||||
nodes::{ConnectionConfig, NodeContainer},
|
nodes::{ConnectionConfig, NodeContainer},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -15,18 +17,89 @@ pub fn run_endpoint(socket: SocketAddr) -> Result<(), Error> {
|
|||||||
}],
|
}],
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
let mut stream = node.recv_stream()?;
|
||||||
|
|
||||||
|
let pty_system = native_pty_system();
|
||||||
|
let pty_pair = pty_system.openpty(PtySize {
|
||||||
|
rows: 24,
|
||||||
|
cols: 80,
|
||||||
|
pixel_width: 0,
|
||||||
|
pixel_height: 0,
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let mut cmd = CommandBuilder::new("bash");
|
||||||
|
cmd.env("TERM", "xterm-256color");
|
||||||
|
// pty_pair.
|
||||||
|
|
||||||
|
let child = pty_pair.slave.spawn_command(cmd)?;
|
||||||
|
|
||||||
|
// Get the master PTY for reading/writing
|
||||||
|
let master = pty_pair.master;
|
||||||
|
|
||||||
|
let mut master_reader = master.try_clone_reader()?;
|
||||||
|
let mut master_writer = master.take_writer()?;
|
||||||
|
|
||||||
|
// Clone stream for bidirectional communication
|
||||||
|
let mut stream_clone = stream.try_clone()?;
|
||||||
|
|
||||||
|
// Thread to read from PTY and write to TCP stream
|
||||||
|
let pty_to_tcp = thread::spawn(move || {
|
||||||
|
let mut buffer = [0u8; 1024];
|
||||||
loop {
|
loop {
|
||||||
let (src, packet) = node.read_packet()?;
|
match master_reader.read(&mut buffer) {
|
||||||
match packet {
|
Ok(0) => break, // EOF
|
||||||
C2Packet::Ping => {
|
Ok(n) => {
|
||||||
info!("Ping from {}!", src);
|
if stream.write(&buffer[..n]).is_err() {
|
||||||
node.send_unrouted(&src, &C2Packet::Pong)?;
|
break;
|
||||||
// (&mut node.state.lock().unwrap()).send_unrouted(src, &C2Packet::Pong)?;
|
|
||||||
}
|
}
|
||||||
C2Packet::Pong => {
|
// stream.flush().ok();
|
||||||
info!("Pong!");
|
|
||||||
}
|
}
|
||||||
_ => {}
|
Err(e) => {
|
||||||
|
error!("Error reading from PTY: {}", e);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
println!("stopped!");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Thread to read from TCP stream and write to PTY
|
||||||
|
let tcp_to_pty = thread::spawn(move || {
|
||||||
|
// let mut buffer = [0u8; 1024];
|
||||||
|
loop {
|
||||||
|
let data = stream_clone.read().unwrap();
|
||||||
|
if master_writer.write(&data).is_err() {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println!("stopped!");
|
||||||
|
});
|
||||||
|
|
||||||
|
// Wait for either thread to finish
|
||||||
|
let _ = pty_to_tcp.join();
|
||||||
|
let _ = tcp_to_pty.join();
|
||||||
|
|
||||||
|
// Clean up the child process
|
||||||
|
// let _ = child.kill();
|
||||||
|
// let _ = child.wait();
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
|
||||||
|
// loop {
|
||||||
|
// let data = stream.read()?;
|
||||||
|
// println!("DATA: {:?}", data);
|
||||||
|
|
||||||
|
// let (src, packet) = node()?;
|
||||||
|
// match packet {
|
||||||
|
// C2Packet::Ping => {
|
||||||
|
// info!("Ping from {}!", src);
|
||||||
|
// // node.send_unrouted(&src, &C2Packet::Pong)?;
|
||||||
|
// // (&mut node.state.lock().unwrap()).send_unrouted(src, &C2Packet::Pong)?;
|
||||||
|
// }
|
||||||
|
// C2Packet::Pong => {
|
||||||
|
// info!("Pong!");
|
||||||
|
// }
|
||||||
|
// _ => {}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,15 +1,13 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
fmt::Debug,
|
fmt::Debug,
|
||||||
sync::{
|
sync::{Arc, Mutex, MutexGuard},
|
||||||
Arc, Mutex,
|
|
||||||
mpsc::{self, Receiver, Sender},
|
|
||||||
},
|
|
||||||
thread,
|
thread,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
use bincode::{Decode, Encode};
|
use bincode::{Decode, Encode};
|
||||||
|
use crossbeam_channel::{Receiver, RecvError, Sender};
|
||||||
// use std:::{Receiver, Sender};
|
// use std:::{Receiver, Sender};
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
use rand::{seq::IndexedRandom, thread_rng};
|
use rand::{seq::IndexedRandom, thread_rng};
|
||||||
@@ -37,7 +35,8 @@ where
|
|||||||
P: Encode + Decode<()> + Debug + Clone + 'static,
|
P: Encode + Decode<()> + Debug + Clone + 'static,
|
||||||
{
|
{
|
||||||
pub state: Arc<Mutex<NodeState<P>>>,
|
pub state: Arc<Mutex<NodeState<P>>>,
|
||||||
pub rx: Receiver<(String, P)>,
|
rx: Receiver<(String, P)>,
|
||||||
|
disconnect_rx: Receiver<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> Node<P>
|
impl<P> Node<P>
|
||||||
@@ -54,13 +53,15 @@ where
|
|||||||
{
|
{
|
||||||
// let mut parent = build_client(TCPClient::connect(&parent.socket)?, parent.layers)?;
|
// let mut parent = build_client(TCPClient::connect(&parent.socket)?, parent.layers)?;
|
||||||
|
|
||||||
let (tx, rx) = mpsc::channel();
|
let (tx, rx) = crossbeam_channel::unbounded();
|
||||||
|
let (disconnect_tx, disconnect_rx) = crossbeam_channel::unbounded();
|
||||||
|
|
||||||
let state = Arc::new(Mutex::new(NodeState::<P> {
|
let state = Arc::new(Mutex::new(NodeState::<P> {
|
||||||
id: id, //Uuid::new_v4().to_string(), //TODO: Calling an OS RNG can pose a problem for security;
|
id: id, //Uuid::new_v4().to_string(), //TODO: Calling an OS RNG can pose a problem for security;
|
||||||
connections: HashMap::new(),
|
connections: HashMap::new(),
|
||||||
map: HashMap::new(),
|
map: HashMap::new(),
|
||||||
packet_listener: tx,
|
packet_listener: tx,
|
||||||
|
disconnect_listener: disconnect_tx,
|
||||||
}));
|
}));
|
||||||
|
|
||||||
for listener in listeners {
|
for listener in listeners {
|
||||||
@@ -85,7 +86,11 @@ where
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Self { state, rx })
|
Ok(Self {
|
||||||
|
state,
|
||||||
|
rx,
|
||||||
|
disconnect_rx,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn run_client(client: ConnectionConfig, state: &Arc<Mutex<NodeState<P>>>) -> Result<(), Error> {
|
fn run_client(client: ConnectionConfig, state: &Arc<Mutex<NodeState<P>>>) -> Result<(), Error> {
|
||||||
@@ -191,6 +196,30 @@ where
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn recv(&self) -> Result<(String, P), RecvError> {
|
||||||
|
self.rx.recv()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn state(&self) -> MutexGuard<'_, NodeState<P>> {
|
||||||
|
self.state.lock().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn try_clone(&self) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
state: Arc::clone(&self.state),
|
||||||
|
rx: self.rx.clone(),
|
||||||
|
disconnect_rx: self.disconnect_rx.clone(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn send_unrouted(&self, dest: String, data: &P) -> Result<(), Error> {
|
||||||
|
self.state().send_unrouted(dest, data)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_disconnect_rx(&self) -> Receiver<String> {
|
||||||
|
self.disconnect_rx.clone()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct NodeState<P>
|
pub struct NodeState<P>
|
||||||
@@ -201,6 +230,7 @@ where
|
|||||||
connections: HashMap<String, Box<dyn Connection + Send>>,
|
connections: HashMap<String, Box<dyn Connection + Send>>,
|
||||||
map: HashMap<String, Vec<String>>,
|
map: HashMap<String, Vec<String>>,
|
||||||
packet_listener: Sender<(String, P)>,
|
packet_listener: Sender<(String, P)>,
|
||||||
|
disconnect_listener: Sender<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<P> NodeState<P>
|
impl<P> NodeState<P>
|
||||||
@@ -309,6 +339,8 @@ where
|
|||||||
if direct { "direct" } else { "indirect" }
|
if direct { "direct" } else { "indirect" }
|
||||||
);
|
);
|
||||||
|
|
||||||
|
self.disconnect_listener.send(remove_uuid.clone()).unwrap();
|
||||||
|
|
||||||
for (uuid, route) in self.map.iter_mut() {
|
for (uuid, route) in self.map.iter_mut() {
|
||||||
if route.contains(&remove_uuid) {
|
if route.contains(&remove_uuid) {
|
||||||
let index = route.iter().position(|r| r == &remove_uuid).unwrap();
|
let index = route.iter().position(|r| r == &remove_uuid).unwrap();
|
||||||
@@ -396,12 +428,16 @@ where
|
|||||||
fn route_packet(&mut self, src: String, dest: String, data: Vec<u8>) -> Result<(), Error> {
|
fn route_packet(&mut self, src: String, dest: String, data: Vec<u8>) -> Result<(), Error> {
|
||||||
if dest == self.id {
|
if dest == self.id {
|
||||||
self.packet_listener.send((src, decode_vec::<P>(&data)?))?;
|
self.packet_listener.send((src, decode_vec::<P>(&data)?))?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
} else {
|
} else {
|
||||||
if self.connections.contains_key(&dest) {
|
if self.connections.contains_key(&dest) {
|
||||||
write(
|
write(
|
||||||
self.connections.get_mut(&dest).unwrap(),
|
self.connections.get_mut(&dest).unwrap(),
|
||||||
Packets::DataUnrouted { src, dest, data },
|
Packets::DataUnrouted { src, dest, data },
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
} else if self.map.contains_key(&dest) {
|
} else if self.map.contains_key(&dest) {
|
||||||
#[allow(deprecated)]
|
#[allow(deprecated)]
|
||||||
let next_uuid = self
|
let next_uuid = self
|
||||||
@@ -416,12 +452,12 @@ where
|
|||||||
self.connections.get_mut(&next_uuid).unwrap(),
|
self.connections.get_mut(&next_uuid).unwrap(),
|
||||||
Packets::DataUnrouted { src, dest, data },
|
Packets::DataUnrouted { src, dest, data },
|
||||||
)?;
|
)?;
|
||||||
} else {
|
|
||||||
error!("Could not find route from {} to {}!", src, dest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
} else {
|
||||||
|
Err::<(), Error>(format!("Could not find route from {} to {}!", src, dest).into())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_unrouted(&mut self, dest: String, data: &P) -> Result<(), Error> {
|
pub fn send_unrouted(&mut self, dest: String, data: &P) -> Result<(), Error> {
|
||||||
|
|||||||
@@ -7,21 +7,19 @@ use std::{
|
|||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
C2Packet, Error,
|
Error,
|
||||||
nodes::{
|
nodes::{ConnectionConfig, Node, Stream, stream::StreamHandle},
|
||||||
ConnectionConfig, Node, Stream,
|
|
||||||
node::NodeState,
|
|
||||||
packets::{decode_vec, encode_vec},
|
|
||||||
},
|
|
||||||
packets::TransportLayerPacket,
|
packets::TransportLayerPacket,
|
||||||
};
|
};
|
||||||
|
|
||||||
type Streams = Arc<Mutex<HashMap<(usize, String), Option<(Stream, Sender<Vec<u8>>)>>>>;
|
type Streams = Arc<Mutex<HashMap<(usize, String), StreamHandle>>>;
|
||||||
|
|
||||||
pub struct NodeContainer {
|
pub struct NodeContainer {
|
||||||
streams: Streams,
|
streams: Streams,
|
||||||
state: Arc<Mutex<NodeState<TransportLayerPacket>>>,
|
node: Node<TransportLayerPacket>,
|
||||||
spontanious_rx: Receiver<(String, C2Packet)>,
|
on_stream_rx: Receiver<Stream>,
|
||||||
|
// state: Arc<Mutex<NodeState<TransportLayerPacket>>>,
|
||||||
|
// spontanious_rx: Receiver<(String, C2Packet)>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeContainer {
|
impl NodeContainer {
|
||||||
@@ -30,20 +28,38 @@ impl NodeContainer {
|
|||||||
clients: Vec<ConnectionConfig>,
|
clients: Vec<ConnectionConfig>,
|
||||||
listeners: Vec<ConnectionConfig>,
|
listeners: Vec<ConnectionConfig>,
|
||||||
) -> Result<Self, Error> {
|
) -> Result<Self, Error> {
|
||||||
let node = Node::run_node(id, clients, listeners)?;
|
let node = Node::<TransportLayerPacket>::run_node(id, clients, listeners)?;
|
||||||
let streams = Arc::new(Mutex::new(HashMap::new()));
|
let streams = Arc::new(Mutex::new(HashMap::new()));
|
||||||
let (spontanious_tx, spontanious_rx) = crossbeam_channel::unbounded();
|
// let (spontanious_tx, spontanious_rx) = crossbeam_channel::unbounded();
|
||||||
|
let (on_stream_tx, on_stream_rx) = crossbeam_channel::unbounded();
|
||||||
|
|
||||||
let s = Self {
|
let s = Self {
|
||||||
streams: Arc::clone(&streams),
|
streams: Arc::clone(&streams),
|
||||||
state: Arc::clone(&node.state),
|
node: node.try_clone()?,
|
||||||
spontanious_rx,
|
on_stream_rx,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let close_rx = node.get_disconnect_rx();
|
||||||
|
let stream_clone = Arc::clone(&streams);
|
||||||
|
thread::spawn(move || {
|
||||||
|
loop {
|
||||||
|
let close_uuid = close_rx.recv().unwrap();
|
||||||
|
let stream = stream_clone.lock().unwrap();
|
||||||
|
let keys = stream.keys();
|
||||||
|
for key in keys {
|
||||||
|
if key.1 == close_uuid {
|
||||||
|
warn!("Stream ({}, {}) disconnected!", key.0, key.1);
|
||||||
|
let handle = (&mut stream_clone.lock().unwrap()).remove(key).unwrap();
|
||||||
|
handle.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Start node listening thread
|
// Start node listening thread
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
loop {
|
loop {
|
||||||
if let Err(e) = Self::node_listening_thread(&node, &streams, &spontanious_tx) {
|
if let Err(e) = Self::node_listening_thread(&node, &streams, &on_stream_tx) {
|
||||||
error!("Got error: {}", e);
|
error!("Got error: {}", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -55,97 +71,113 @@ impl NodeContainer {
|
|||||||
fn node_listening_thread(
|
fn node_listening_thread(
|
||||||
node: &Node<TransportLayerPacket>,
|
node: &Node<TransportLayerPacket>,
|
||||||
streams: &Streams,
|
streams: &Streams,
|
||||||
spontanious_tx: &Sender<(String, C2Packet)>,
|
on_stream_tx: &Sender<Stream>, // spontanious_tx: &Sender<(String, C2Packet)>,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let (src, packet) = node.rx.recv()?;
|
// info!("Loop");
|
||||||
|
let (src, packet) = node.recv()?;
|
||||||
|
info!("Packet: {:?}", packet);
|
||||||
|
|
||||||
match packet {
|
match packet {
|
||||||
TransportLayerPacket::RequestStreamUnrouted { stream_id } => {
|
TransportLayerPacket::RequestStreamUnrouted {
|
||||||
|
stream_id: remote_stream_id,
|
||||||
|
} => {
|
||||||
|
// Create stream ID
|
||||||
let local_stream_id = streams.lock().unwrap().keys().len();
|
let local_stream_id = streams.lock().unwrap().keys().len();
|
||||||
streams
|
// Send response to server including local id and remoe ID
|
||||||
.lock()
|
Stream::respond_create(src.clone(), local_stream_id, remote_stream_id, node)?;
|
||||||
.unwrap()
|
|
||||||
.insert((local_stream_id, src.clone()), None);
|
|
||||||
(&mut node.state.lock().unwrap()).send_unrouted(
|
|
||||||
src,
|
|
||||||
&TransportLayerPacket::AckStreamUnrouted {
|
|
||||||
local_stream_id,
|
|
||||||
remote_stream_id: stream_id,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
|
Self::create_handle_thread(
|
||||||
|
on_stream_tx,
|
||||||
|
streams,
|
||||||
|
node,
|
||||||
|
src,
|
||||||
|
local_stream_id,
|
||||||
|
remote_stream_id,
|
||||||
|
)?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
TransportLayerPacket::AckStreamUnrouted {
|
TransportLayerPacket::AckStreamUnrouted {
|
||||||
local_stream_id,
|
ack_stream_id,
|
||||||
remote_stream_id,
|
stream_id,
|
||||||
} => {
|
} => {
|
||||||
let key = &(remote_stream_id, src);
|
Self::create_handle_thread(
|
||||||
if let Some(stream_mut) = streams.lock().unwrap().get_mut(&key) {
|
on_stream_tx,
|
||||||
if stream_mut.is_none() {
|
streams,
|
||||||
let stream = Self::create_stream(local_stream_id, node, src, stream_mut)?;
|
node,
|
||||||
Ok(())
|
src,
|
||||||
} else {
|
ack_stream_id,
|
||||||
Err(format!("Stream {:?} already exists!", key).into())
|
stream_id,
|
||||||
}
|
)?;
|
||||||
} else {
|
|
||||||
Err(format!("Could not find stream id by {:?}", key).into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
TransportLayerPacket::StreamDataUnrouted { stream_id, data } => todo!(),
|
|
||||||
TransportLayerPacket::SpontaniousDataUnrouted { data } => {
|
|
||||||
spontanious_tx.send((src, decode_vec::<C2Packet>(&data)?))?;
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
TransportLayerPacket::StreamDataUnrouted { stream_id, data } => {
|
||||||
|
match streams.lock().unwrap().get(&(stream_id, src.clone())) {
|
||||||
|
Some(handle) => Ok(handle.send(data).unwrap()),
|
||||||
|
// Some(_) => Err(format!(
|
||||||
|
// "Stream {}, {} has not been initilized!",
|
||||||
|
// stream_id, src
|
||||||
|
// )
|
||||||
|
// .into()),
|
||||||
|
None => Err(format!("Stream {}, {} does not exist!", stream_id, src).into()),
|
||||||
|
}
|
||||||
|
} // _ => Err(format!("Unsupported packet: {:?}", packet).into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn create_stream(
|
fn create_handle_thread(
|
||||||
remote_stream_id: usize,
|
on_stream_tx: &Sender<Stream>,
|
||||||
dest: String,
|
streams: &Streams,
|
||||||
node: &Node<TransportLayerPacket>,
|
node: &Node<TransportLayerPacket>,
|
||||||
stream_mut: &mut Option<(Stream, Sender<Vec<u8>>)>,
|
src: String,
|
||||||
|
local_stream_id: usize,
|
||||||
|
remote_stream_id: usize,
|
||||||
) -> Result<(), Error> {
|
) -> Result<(), Error> {
|
||||||
let (recv_tx, recv_rx) = crossbeam_channel::unbounded();
|
info!("Local: {}, Remote: {}", local_stream_id, remote_stream_id);
|
||||||
let (send_tx, send_rx) = crossbeam_channel::unbounded();
|
|
||||||
|
|
||||||
let stream = Stream::new(send_tx, recv_rx);
|
// Create stream from local and remote stream handles
|
||||||
|
let (stream, handle) =
|
||||||
|
Stream::create_handle(src.clone(), local_stream_id, remote_stream_id)?;
|
||||||
|
|
||||||
let _ = stream_mut.insert((stream, recv_tx));
|
on_stream_tx.send(stream)?;
|
||||||
|
|
||||||
|
// Add the local stream to map
|
||||||
|
streams
|
||||||
|
.lock()
|
||||||
|
.unwrap()
|
||||||
|
.insert((local_stream_id, src.clone()), handle.clone()?);
|
||||||
|
|
||||||
|
let node_clone = node.try_clone()?;
|
||||||
thread::spawn(move || {
|
thread::spawn(move || {
|
||||||
loop {
|
loop {
|
||||||
let packet = send_rx.recv().unwrap();
|
let data = handle.recv().unwrap();
|
||||||
(&mut node.state.lock().unwrap())
|
if let Err(e) = node_clone.state().send_unrouted(
|
||||||
.send_unrouted(
|
src.clone(),
|
||||||
dest,
|
|
||||||
&TransportLayerPacket::StreamDataUnrouted {
|
&TransportLayerPacket::StreamDataUnrouted {
|
||||||
stream_id: remote_stream_id,
|
stream_id: remote_stream_id,
|
||||||
data: packet,
|
data,
|
||||||
},
|
},
|
||||||
)
|
) {
|
||||||
.unwrap();
|
error!("Got error: {}", e);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn create_stream_block(&self, dest: String) -> Result<Stream, Error> {
|
||||||
|
let local_stream_id = self.streams.lock().unwrap().keys().len();
|
||||||
|
Stream::ask_create(dest.clone(), local_stream_id, &self.node)?;
|
||||||
|
Ok(self.on_stream_rx.recv()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn recv_stream(&self) -> Result<Stream, Error> {
|
||||||
|
Ok(self.on_stream_rx.recv()?)
|
||||||
|
}
|
||||||
|
|
||||||
pub fn get_nodes(&self) -> Vec<String> {
|
pub fn get_nodes(&self) -> Vec<String> {
|
||||||
self.state.lock().unwrap().get_all_nodes()
|
self.node.state().get_all_nodes()
|
||||||
}
|
// self.state.lock().unwrap().get_all_nodes()
|
||||||
|
|
||||||
pub fn send_unrouted(&self, dest: &String, data: &C2Packet) -> Result<(), Error> {
|
|
||||||
(&mut self.state.lock().unwrap()).send_unrouted(
|
|
||||||
dest.clone(),
|
|
||||||
&TransportLayerPacket::SpontaniousDataUnrouted {
|
|
||||||
data: encode_vec(data)?,
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn read_packet(&self) -> Result<(String, C2Packet), Error> {
|
|
||||||
Ok(self.spontanious_rx.recv()?)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,16 @@
|
|||||||
|
use std::sync::{
|
||||||
|
Arc,
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
};
|
||||||
|
|
||||||
use crossbeam_channel::{Receiver, Sender};
|
use crossbeam_channel::{Receiver, Sender};
|
||||||
|
|
||||||
use crate::networkers::Connection;
|
use crate::{Error, networkers::Connection, nodes::Node, packets::TransportLayerPacket};
|
||||||
|
|
||||||
pub struct Stream {
|
pub struct Stream {
|
||||||
tx: Sender<Vec<u8>>,
|
tx: Sender<Vec<u8>>,
|
||||||
rx: Receiver<Vec<u8>>,
|
rx: Receiver<Vec<u8>>,
|
||||||
|
closed: Arc<AtomicBool>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Connection for Stream {
|
impl Connection for Stream {
|
||||||
@@ -13,24 +19,137 @@ impl Connection for Stream {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn is_alive(&self) -> bool {
|
fn is_alive(&self) -> bool {
|
||||||
true
|
self.closed.load(Ordering::Relaxed)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn read(&mut self) -> Result<Vec<u8>, crate::Error> {
|
fn read(&mut self) -> Result<Vec<u8>, crate::Error> {
|
||||||
|
if self.closed.load(Ordering::Relaxed) {
|
||||||
|
Err("Connection closed".into())
|
||||||
|
} else {
|
||||||
Ok(self.rx.recv()?)
|
Ok(self.rx.recv()?)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn write(&mut self, data: &[u8]) -> Result<(), crate::Error> {
|
fn write(&mut self, data: &[u8]) -> Result<(), crate::Error> {
|
||||||
|
if self.closed.load(Ordering::Relaxed) {
|
||||||
|
Err("Connection closed".into())
|
||||||
|
} else {
|
||||||
Ok(self.tx.send(data.to_vec())?)
|
Ok(self.tx.send(data.to_vec())?)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn try_clone(&self) -> Result<Box<dyn Connection + Send + Sync>, crate::Error> {
|
fn try_clone(&self) -> Result<Box<dyn Connection + Send + Sync>, crate::Error> {
|
||||||
todo!()
|
Ok(Box::new(Self {
|
||||||
|
tx: self.tx.clone(),
|
||||||
|
rx: self.rx.clone(),
|
||||||
|
closed: Arc::clone(&self.closed),
|
||||||
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Stream {
|
impl Stream {
|
||||||
pub fn new(tx: Sender<Vec<u8>>, rx: Receiver<Vec<u8>>) -> Self {
|
pub fn ask_create(
|
||||||
Self { tx, rx }
|
dest: String,
|
||||||
|
local_stream_id: usize,
|
||||||
|
node: &Node<TransportLayerPacket>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
info!("Sent to {}", dest);
|
||||||
|
node.send_unrouted(
|
||||||
|
dest.clone(),
|
||||||
|
&TransportLayerPacket::RequestStreamUnrouted {
|
||||||
|
stream_id: local_stream_id,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
|
||||||
|
// Self::create_handle(dest, local_stream_id, remote_stream_id, node)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn respond_create(
|
||||||
|
dest: String,
|
||||||
|
local_stream_id: usize,
|
||||||
|
remote_stream_id: usize,
|
||||||
|
node: &Node<TransportLayerPacket>,
|
||||||
|
) -> Result<(), Error> {
|
||||||
|
node.send_unrouted(
|
||||||
|
dest.clone(),
|
||||||
|
&&TransportLayerPacket::AckStreamUnrouted {
|
||||||
|
ack_stream_id: remote_stream_id,
|
||||||
|
stream_id: local_stream_id,
|
||||||
|
},
|
||||||
|
)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create_handle(
|
||||||
|
dest: String,
|
||||||
|
local_stream_id: usize,
|
||||||
|
remote_stream_id: usize,
|
||||||
|
) -> Result<(Self, StreamHandle), Error> {
|
||||||
|
let (recv_tx, recv_rx) = crossbeam_channel::unbounded();
|
||||||
|
let (send_tx, send_rx) = crossbeam_channel::unbounded();
|
||||||
|
|
||||||
|
let closed = Arc::new(AtomicBool::new(false));
|
||||||
|
|
||||||
|
let handle = StreamHandle {
|
||||||
|
dest,
|
||||||
|
tx: recv_tx,
|
||||||
|
rx: send_rx,
|
||||||
|
local_stream_id,
|
||||||
|
remote_stream_id,
|
||||||
|
closed: Arc::clone(&closed),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((
|
||||||
|
Self {
|
||||||
|
tx: send_tx,
|
||||||
|
rx: recv_rx,
|
||||||
|
closed,
|
||||||
|
},
|
||||||
|
handle,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
// pub fn new(tx: Sender<Vec<u8>>, rx: Receiver<Vec<u8>>) -> Self {
|
||||||
|
// Self { tx, rx }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct StreamHandle {
|
||||||
|
pub dest: String,
|
||||||
|
pub local_stream_id: usize,
|
||||||
|
pub remote_stream_id: usize,
|
||||||
|
|
||||||
|
tx: Sender<Vec<u8>>,
|
||||||
|
rx: Receiver<Vec<u8>>,
|
||||||
|
closed: Arc<AtomicBool>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StreamHandle {
|
||||||
|
pub fn send(&self, data: Vec<u8>) -> Result<(), Error> {
|
||||||
|
Ok(self.tx.send(data)?)
|
||||||
|
}
|
||||||
|
pub fn has_content(&self) -> bool {
|
||||||
|
self.rx.len() > 0
|
||||||
|
}
|
||||||
|
pub fn recv(&self) -> Result<Vec<u8>, Error> {
|
||||||
|
Ok(self.rx.recv()?)
|
||||||
|
}
|
||||||
|
pub fn clone(&self) -> Result<Self, Error> {
|
||||||
|
Ok(Self {
|
||||||
|
dest: self.dest.clone(),
|
||||||
|
local_stream_id: self.local_stream_id.clone(),
|
||||||
|
remote_stream_id: self.remote_stream_id.clone(),
|
||||||
|
tx: self.tx.clone(),
|
||||||
|
rx: self.rx.clone(),
|
||||||
|
closed: Arc::clone(&self.closed),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
pub fn close(self) {
|
||||||
|
drop(self.tx);
|
||||||
|
drop(self.rx);
|
||||||
|
self.closed.store(false, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,17 +7,16 @@ pub enum TransportLayerPacket {
|
|||||||
stream_id: usize,
|
stream_id: usize,
|
||||||
},
|
},
|
||||||
AckStreamUnrouted {
|
AckStreamUnrouted {
|
||||||
local_stream_id: usize,
|
ack_stream_id: usize,
|
||||||
remote_stream_id: usize,
|
stream_id: usize,
|
||||||
},
|
},
|
||||||
StreamDataUnrouted {
|
StreamDataUnrouted {
|
||||||
stream_id: usize,
|
stream_id: usize,
|
||||||
data: Vec<u8>,
|
data: Vec<u8>,
|
||||||
},
|
},
|
||||||
|
// SpontaniousDataUnrouted {
|
||||||
SpontaniousDataUnrouted {
|
// data: Vec<u8>,
|
||||||
data: Vec<u8>,
|
// },
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Encode, Decode, Clone)]
|
#[derive(Debug, Encode, Decode, Clone)]
|
||||||
|
|||||||
Reference in New Issue
Block a user