Browse Source

sender node base; file accept|reject base

master
Gitea 2 years ago
parent
commit
f8c83c05be
  1. 2
      PROTOCOL
  2. 21
      src/main.rs
  3. 35
      src/nodes/recv_node.rs
  4. 145
      src/nodes/send_node.rs
  5. 4
      src/protocol/packets.rs
  6. 4
      src/protocol/specs.rs

2
PROTOCOL

@ -30,6 +30,8 @@ The next 1 byte - number that represents this packet's type (ID) where:
4: TEXT PACKET 4: TEXT PACKET
5: FILEINFO PACKET 5: FILEINFO PACKET
6: FILEDATA PACKET 6: FILEDATA PACKET
7: FILE ACCEPT PACKET
8: FILE REJECT PACKET
Then the internal structure varies from one packet type to the other, Then the internal structure varies from one packet type to the other,
but the content-types are encoded as follows: but the content-types are encoded as follows:

21
src/main.rs

@ -23,6 +23,8 @@ mod nodes;
use protocol::specs::RunMode; use protocol::specs::RunMode;
use args::parser::Args; use args::parser::Args;
use nodes::recv_node::RecvOptions; use nodes::recv_node::RecvOptions;
use nodes::send_node::SendOptions;
const VERSION: &str = "v0.1.0"; const VERSION: &str = "v0.1.0";
const HELP_MESSAGE: &str = const HELP_MESSAGE: &str =
@ -85,8 +87,8 @@ fn main() {
RunMode::RECEIVE => { RunMode::RECEIVE => {
match nodes::recv_node::start( match nodes::recv_node::start(
RecvOptions::new(format!("0.0.0.0:{}", DEFAULT_PORT), args.save_directory), args.verbose_output) { RecvOptions::new(format!("0.0.0.0:{}", DEFAULT_PORT), args.save_directory), args.verbose_output) {
None => {} Ok(_) => {}
Some(error) => { Err(error) => {
println!("Error receiving: {}", error.text); println!("Error receiving: {}", error.text);
return; return;
} }
@ -94,7 +96,20 @@ fn main() {
} }
RunMode::SEND => { RunMode::SEND => {
// match nodes::send_node::start(options: SendOptions, verbose_output: bool); match nodes::send_node::start(
SendOptions::new(
args.address_str,
args.send_type,
args.text_to_send,
args.send_path,
), args.verbose_output) {
Ok(_) => {}
Err(error) => {
println!("Error sending: {}", error.text);
return;
}
}
} }
RunMode::DAEMON => { RunMode::DAEMON => {

35
src/nodes/recv_node.rs

@ -39,14 +39,14 @@ impl RecvOptions {
} }
pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> { pub fn start(options: RecvOptions, verbose_output: bool) -> Result<(), Error> {
let listener: net::TcpListener; let listener: net::TcpListener;
match net::TcpListener::bind(options.listen_address) { match net::TcpListener::bind(options.listen_address) {
Ok(l) => { Ok(l) => {
listener = l; listener = l;
} }
Err(error) => { Err(error) => {
return Some(Error::new(format!("could not create TCP listener: {}", error).as_str())); return Err(Error::new(format!("could not create TCP listener: {}", error).as_str()));
} }
} }
@ -63,7 +63,7 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
address = a; address = a;
} }
Err(error) => { Err(error) => {
return Some(Error::new(format!("error accepting a new incoming connection: {}", error).as_str())); return Err(Error::new(format!("error accepting a new incoming connection: {}", error).as_str()));
} }
} }
@ -83,7 +83,7 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
if verbose_output { if verbose_output {
println!("{} did not provide valid handshake packet. Dropping connection...", address); println!("{} did not provide valid handshake packet. Dropping connection...", address);
} }
connection.shutdown(net::Shutdown::Both); packets::close_connection(&mut connection);
continue; continue;
} }
} }
@ -92,7 +92,9 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
PacketType::Handshake => { PacketType::Handshake => {
match handshake.from_bytes(incoming_packet.as_bytes()) { match handshake.from_bytes(incoming_packet.as_bytes()) {
Some(error) => { Some(error) => {
return Some( packets::close_connection(&mut connection);
return Err(
Error::new( Error::new(
format!("error constructing handshake from {}: {}", address, error.text).as_str() format!("error constructing handshake from {}: {}", address, error.text).as_str()
)); ));
@ -108,7 +110,9 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
match send_packet(&mut connection, &packets::HandshakeAccept{}) { match send_packet(&mut connection, &packets::HandshakeAccept{}) {
Ok(()) => {} Ok(()) => {}
Err(error) => { Err(error) => {
return Some( packets::close_connection(&mut connection);
return Err(
Error::new(format!("error accepting handshake from {}: {}", address, error.text).as_str()) Error::new(format!("error accepting handshake from {}: {}", address, error.text).as_str())
); );
} }
@ -122,7 +126,7 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
if verbose_output { if verbose_output {
println!("{} didn't send a handshake packet, but {:?} packet instead. Dropping connection...", address, incoming_packet.get_type()); println!("{} didn't send a handshake packet, but {:?} packet instead. Dropping connection...", address, incoming_packet.get_type());
} }
connection.shutdown(net::Shutdown::Both); packets::close_connection(&mut connection);
continue; continue;
} }
} }
@ -140,7 +144,9 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
} }
Err(_) => { Err(_) => {
return Some( packets::close_connection(&mut connection);
return Err(
Error::new("could not clone connection") Error::new("could not clone connection")
); );
} }
@ -177,7 +183,9 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
} }
Err(error) => { Err(error) => {
return Some(Error::new( packets::close_connection(&mut connection);
return Err(Error::new(
format!("error receiving a new packet from listener thread: {}", error).as_str() format!("error receiving a new packet from listener thread: {}", error).as_str()
)); ));
} }
@ -188,7 +196,7 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
if verbose_output { if verbose_output {
println!("{} shuts down the connection", address); println!("{} shuts down the connection", address);
} }
connection.shutdown(net::Shutdown::Both); packets::close_connection(&mut connection);
break; break;
} }
@ -203,10 +211,9 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
Some(error) => { Some(error) => {
// close connection and exit // close connection and exit
send_packet(&mut connection, &packets::ConnectionShutdown{}); packets::close_connection(&mut connection);
connection.shutdown(net::Shutdown::Both);
return Some( return Err(
Error::new(format!("could not get text packet: {}", error.text).as_str()) Error::new(format!("could not get text packet: {}", error.text).as_str())
); );
} }
@ -217,5 +224,5 @@ pub fn start(options: RecvOptions, verbose_output: bool) -> Option<Error> {
} }
} }
return None; return Ok(());
} }

145
src/nodes/send_node.rs

@ -13,7 +13,17 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details. GNU Affero General Public License for more details.
*/ */
use crate::util::error::Error;
use crate::args::parser::DataType; use crate::args::parser::DataType;
use crate::crypt;
use crate::protocol::packets;
use crate::protocol::packets::{send_packet, read_next_packet};
use crate::protocol::specs::PacketType;
use crate::protocol::specs;
use crate::protocol::specs::Packet;
use std::thread;
use std::sync::mpsc::{Sender, Receiver};
use std::sync::mpsc;
use std::net; use std::net;
use std::path; use std::path;
@ -24,6 +34,139 @@ pub struct SendOptions {
pub source_path: path::PathBuf, pub source_path: path::PathBuf,
} }
pub fn start(options: SendOptions, verbose_output: bool) { impl SendOptions {
pub fn new(addr: String, send_t: DataType, txt_to_send: String, src_path: path::PathBuf) -> SendOptions {
return SendOptions{
address: addr,
send_type: send_t,
text_to_send: txt_to_send,
source_path: src_path,
};
}
}
pub fn start(options: SendOptions, verbose_output: bool) -> Result<(), Error> {
let mut connection: net::TcpStream;
match net::TcpStream::connect(options.address) {
Ok(conn) => {
connection = conn;
}
Err(error) => {
return Err(
Error::new(format!("connection error: {}", error).as_str())
);
}
}
// send handshake
let handshake: packets::Handshake = packets::Handshake{
protocol_version: specs::PROTOCOL_VERSION_1,
encryption_type: specs::ECRYPTION_XOR,
encryption_key: vec!(crypt::keys::Key8bit::new_random().k),
};
match send_packet(&mut connection, &handshake) {
Ok(_) => {}
Err(error) => {
packets::close_connection(&mut connection);
return Err(
Error::new(format!("could not send handshake: {}", error.text).as_str())
);
}
}
// see if the handshake has been accepted
match read_next_packet(&mut connection) {
Ok(packet) => {
if packet.get_type() != PacketType::HandshakeAccept {
// not approved or entirely not according to the protocol
packets::close_connection(&mut connection);
return Err(
Error::new(format!("handshake hasn't been approved").as_str())
);
}
}
Err(error) => {
packets::close_connection(&mut connection);
return Err(
Error::new(format!("could not receive potential handshake approval: {}", error.text).as_str())
);
}
}
// launch a new packet reading thread
let (ch_send, ch_recv): (Sender<Box<dyn Packet + Send>>, Receiver<Box<dyn Packet + Send>>) = mpsc::channel();
let mut cloned_connection: net::TcpStream;
match connection.try_clone() {
Ok(cc) => {
cloned_connection = cc;
}
Err(_) => {
packets::close_connection(&mut connection);
return Err(
Error::new("could not clone connection")
);
}
}
thread::spawn(move || {
loop {
match read_next_packet(&mut cloned_connection) {
Ok(packet) => {
if let Err(_) = ch_send.send(packet) {
// the channel has been hung up
// return from this thread
return;
}
}
Err(error) => {
if verbose_output {
println!("Could not read packet: {}", error.text);
}
continue;
}
}
}
});
// handle incoming packets
loop {
let incoming_packet: Box<dyn Packet>;
match ch_recv.recv() {
Ok(p) => {
incoming_packet = p;
}
Err(error) => {
packets::close_connection(&mut connection);
return Err(Error::new(
format!("error receiving a new packet from listener thread: {}", error).as_str()
));
}
}
match incoming_packet.get_type() {
PacketType::ConnectionShutdown => {
if verbose_output {
println!("Connection has been shut down");
}
packets::close_connection(&mut connection);
break;
}
_ => {}
}
}
return Ok(());
} }

4
src/protocol/packets.rs

@ -123,6 +123,10 @@ pub fn read_next_packet(conn: &mut net::TcpStream) -> Result<Box<dyn Packet + Se
} }
} }
pub fn close_connection(connection: &mut net::TcpStream) {
send_packet(connection, &ConnectionShutdown{});
connection.shutdown(net::Shutdown::Both);
}
pub struct Text { pub struct Text {
pub text: String, pub text: String,

4
src/protocol/specs.rs

@ -26,6 +26,8 @@ pub const CONNECTION_SHUTDOWN_PACKET_ID: u8 = 3;
pub const TEXT_PACKET_ID: u8 = 4; pub const TEXT_PACKET_ID: u8 = 4;
pub const FILEINFO_PACKET_ID: u8 = 5; pub const FILEINFO_PACKET_ID: u8 = 5;
pub const FILEDATA_PACKET_ID: u8 = 6; pub const FILEDATA_PACKET_ID: u8 = 6;
pub const FILE_ACCEPT_PACKET_ID: u8 = 7;
pub const FILE_REJECT_PACKET_ID: u8 = 8;
// File chunk size // File chunk size
pub const CHUNK_SIZE: usize = 262_144; // 256 KB pub const CHUNK_SIZE: usize = 262_144; // 256 KB
@ -50,6 +52,8 @@ pub enum PacketType {
FileData, FileData,
Handshake, Handshake,
HandshakeAccept, HandshakeAccept,
FileAccept,
FileReject,
} }
pub trait Packet : Send { pub trait Packet : Send {

Loading…
Cancel
Save