🚧 wip: messing with UDP multicast

main
_ 2022-10-18 01:53:55 +00:00
parent 2de0c5d6a7
commit 7b4eeea12c
3 changed files with 160 additions and 9 deletions

11
Cargo.lock generated
View File

@ -636,9 +636,9 @@ dependencies = [
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.5.1" version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904"
[[package]] [[package]]
name = "httpdate" name = "httpdate"
@ -648,9 +648,9 @@ checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.13" version = "0.14.20"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" checksum = "02c929dc5c39e335a03c405292728118860721b10190d98c2a0f0efd5baafbac"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -661,7 +661,7 @@ dependencies = [
"http-body", "http-body",
"httparse", "httparse",
"httpdate", "httpdate",
"itoa 0.4.8", "itoa 1.0.1",
"pin-project-lite", "pin-project-lite",
"socket2", "socket2",
"tokio", "tokio",
@ -721,6 +721,7 @@ dependencies = [
name = "insecure_chat" name = "insecure_chat"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"hyper",
"mac_address", "mac_address",
"nix 0.25.0", "nix 0.25.0",
"ptth_diceware", "ptth_diceware",

View File

@ -6,6 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies] [dependencies]
hyper = { version = "0.14.20", features = ["http1", "server", "tcp"] }
mac_address = "1.1.4" mac_address = "1.1.4"
nix = "0.25.0" nix = "0.25.0"
ptth_diceware = { path = "../ptth_diceware" } ptth_diceware = { path = "../ptth_diceware" }

View File

@ -1,9 +1,28 @@
use std::{ use std::{
collections::*,
net::{ net::{
Ipv4Addr, Ipv4Addr,
SocketAddrV4, SocketAddrV4,
UdpSocket,
}, },
sync::Arc,
};
use hyper::{
Body,
Method,
Request,
Response,
Server,
StatusCode,
service::{
make_service_fn,
service_fn,
},
};
use tokio::{
net::UdpSocket,
sync::RwLock,
}; };
mod ip; mod ip;
@ -25,6 +44,14 @@ fn main () -> Result <(), Error>
if arg == "--name" { if arg == "--name" {
name = args.next ().unwrap ().to_string (); name = args.next ().unwrap ().to_string ();
} }
else if arg == "peer" {
subcommand = Some (Subcommand::Peer);
subcommand_count += 1;
}
else if arg == "receiver" {
subcommand = Some (Subcommand::Receiver);
subcommand_count += 1;
}
else if arg == "sender" { else if arg == "sender" {
subcommand = Some (Subcommand::Sender); subcommand = Some (Subcommand::Sender);
subcommand_count += 1; subcommand_count += 1;
@ -57,6 +84,8 @@ fn main () -> Result <(), Error>
rt.block_on (async { rt.block_on (async {
if let Some (cmd) = subcommand { if let Some (cmd) = subcommand {
return match cmd { return match cmd {
Subcommand::Peer => peer (params).await,
Subcommand::Receiver => receiver (params).await,
Subcommand::Sender => sender (params).await, Subcommand::Sender => sender (params).await,
Subcommand::Spy => spy (params), Subcommand::Spy => spy (params),
}; };
@ -71,6 +100,8 @@ fn main () -> Result <(), Error>
} }
enum Subcommand { enum Subcommand {
Peer,
Receiver,
Sender, Sender,
Spy, Spy,
} }
@ -89,11 +120,125 @@ impl Default for Params {
} }
} }
async fn peer (params: Params) -> Result <(), Error>
{
let (multicast_addr, multicast_port) = params.multicast_group;
let socket = tokio::net::UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, multicast_port)).await?;
socket.join_multicast_v4 (multicast_addr, Ipv4Addr::UNSPECIFIED)?;
eprintln! ("Multicast group is {:?}", params.multicast_group);
eprintln! ("Local addr is {}", socket.local_addr ()?);
let peer = Peer {
outbox: Outbox {
index: 1000,
messages: Default::default (),
}.into (),
params,
socket,
};
let state = Arc::new (peer);
let make_svc = make_service_fn (|_conn| {
let state = state.clone ();
async {
Ok::<_, String> (service_fn (move |req| {
let state = state.clone ();
peer_handle_all (req, state)
}))
}
});
let addr = std::net::SocketAddr::from (([127, 0, 0, 1], multicast_port));
let server = Server::bind (&addr)
.serve (make_svc);
eprintln! ("Local UI on {}", addr);
server.await?;
Ok (())
}
struct Peer {
outbox: RwLock <Outbox>,
params: Params,
socket: UdpSocket,
}
struct Outbox {
index: u32,
messages: VecDeque <SentMessage>,
}
struct SentMessage {
index: u32,
body: Vec <u8>,
}
async fn peer_handle_all (req: Request <Body>, state: Arc <Peer>)
-> Result <Response <Body>, Error>
{
if req.method () == Method::POST {
if req.uri () == "/paste" {
let body = hyper::body::to_bytes (req.into_body ()).await?;
if body.len () > 1024 {
let resp = Response::builder ()
.status (StatusCode::BAD_REQUEST)
.body (Body::from ("Message body must be <= 1024 bytes"))?;
return Ok (resp);
}
let body = body.to_vec ();
let msg_index;
{
let mut outbox = state.outbox.write ().await;
let msg = SentMessage {
index: outbox.index,
body: body.clone (),
};
msg_index = msg.index;
outbox.messages.push_back (msg);
if outbox.messages.len () > 10 {
outbox.messages.pop_front ();
}
outbox.index += 1;
}
state.socket.send_to (&body, state.params.multicast_group).await?;
return Ok (Response::new (format! ("Pasted message {}\n", msg_index).into ()));
}
}
Ok (Response::new (":V\n".into ()))
}
async fn receiver (params: Params) -> Result <(), Error>
{
let (multicast_addr, multicast_port) = params.multicast_group;
let socket = tokio::net::UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, multicast_port)).await?;
socket.join_multicast_v4 (multicast_addr, Ipv4Addr::UNSPECIFIED)?;
eprintln! ("Multicast group is {:?}", params.multicast_group);
eprintln! ("Local addr is {}", socket.local_addr ()?);
loop {
let mut buf = vec! [0u8; 2048];
let (bytes_recved, remote_addr) = socket.recv_from (&mut buf).await?;
buf.truncate (bytes_recved);
println! ("Received {} bytes from {}", bytes_recved, remote_addr);
}
}
async fn sender (params: Params) -> Result <(), Error> async fn sender (params: Params) -> Result <(), Error>
{ {
let socket = tokio::net::UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, 0)).await?;
let (multicast_addr, multicast_port) = params.multicast_group; let (multicast_addr, multicast_port) = params.multicast_group;
let socket = tokio::net::UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, 0)).await?;
socket.join_multicast_v4 (multicast_addr, Ipv4Addr::UNSPECIFIED)?; socket.join_multicast_v4 (multicast_addr, Ipv4Addr::UNSPECIFIED)?;
eprintln! ("Multicast group is {:?}", params.multicast_group); eprintln! ("Multicast group is {:?}", params.multicast_group);
@ -108,7 +253,7 @@ fn spy (params: Params) -> Result <(), Error>
{ {
let (multicast_addr, multicast_port) = params.multicast_group; let (multicast_addr, multicast_port) = params.multicast_group;
let socket = match UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, multicast_port)) { let socket = match std::net::UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, multicast_port)) {
Ok (x) => x, Ok (x) => x,
Err (e) => if e.kind () == std::io::ErrorKind::AddrInUse { Err (e) => if e.kind () == std::io::ErrorKind::AddrInUse {
eprintln! ("Address in use. You can only run 1 instance of Insecure Chat at a time, even in spy mode."); eprintln! ("Address in use. You can only run 1 instance of Insecure Chat at a time, even in spy mode.");
@ -144,6 +289,10 @@ enum Error {
#[error ("CLI args")] #[error ("CLI args")]
Args, Args,
#[error (transparent)] #[error (transparent)]
Hyper (#[from] hyper::Error),
#[error (transparent)]
HyperHttp (#[from] hyper::http::Error),
#[error (transparent)]
Io (#[from] std::io::Error), Io (#[from] std::io::Error),
#[error (transparent)] #[error (transparent)]
Ip (#[from] ip::Error), Ip (#[from] ip::Error),