🚧 wip: messing with UDP multicast
parent
2de0c5d6a7
commit
7b4eeea12c
|
@ -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",
|
||||||
|
|
|
@ -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" }
|
||||||
|
|
|
@ -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),
|
||||||
|
|
Loading…
Reference in New Issue