151 lines
3.3 KiB
Rust
151 lines
3.3 KiB
Rust
use std::{
|
|
net::{
|
|
Ipv4Addr,
|
|
SocketAddrV4,
|
|
UdpSocket,
|
|
},
|
|
};
|
|
|
|
mod ip;
|
|
|
|
fn main () -> Result <(), Error>
|
|
{
|
|
let mut args = std::env::args ();
|
|
let mut bail_unknown = true;
|
|
let mut last_unknown = None;
|
|
let mut name = ptth_diceware::passphrase ("_", 3);
|
|
let mut subcommand_count = 0;
|
|
let mut subcommand = None;
|
|
|
|
args.next ();
|
|
while let Some (arg) = args.next () {
|
|
if arg == "--ignore-unknown" {
|
|
bail_unknown = false;
|
|
}
|
|
if arg == "--name" {
|
|
name = args.next ().unwrap ().to_string ();
|
|
}
|
|
else if arg == "sender" {
|
|
subcommand = Some (Subcommand::Sender);
|
|
subcommand_count += 1;
|
|
}
|
|
else if arg == "spy" {
|
|
subcommand = Some (Subcommand::Spy);
|
|
subcommand_count += 1;
|
|
}
|
|
else {
|
|
last_unknown = Some (arg);
|
|
}
|
|
}
|
|
|
|
if bail_unknown {
|
|
if let Some (last_unknown) = last_unknown {
|
|
eprintln! ("Unknown argument `{}`", last_unknown);
|
|
return Err (Error::Args);
|
|
}
|
|
}
|
|
|
|
if subcommand_count >= 2 {
|
|
eprintln! ("Detected {} subcommands in arguments", subcommand_count);
|
|
return Err (Error::Args)
|
|
}
|
|
|
|
let rt = tokio::runtime::Runtime::new ()?;
|
|
|
|
let params = Params::default ();
|
|
|
|
rt.block_on (async {
|
|
if let Some (cmd) = subcommand {
|
|
return match cmd {
|
|
Subcommand::Sender => sender (params).await,
|
|
Subcommand::Spy => spy (params),
|
|
};
|
|
}
|
|
|
|
println! ("Name is `{}`", name);
|
|
|
|
Ok::<_, Error> (())
|
|
})?;
|
|
|
|
Ok (())
|
|
}
|
|
|
|
enum Subcommand {
|
|
Sender,
|
|
Spy,
|
|
}
|
|
|
|
struct Params {
|
|
multicast_group: (Ipv4Addr, u16),
|
|
}
|
|
|
|
impl Default for Params {
|
|
fn default () -> Self {
|
|
let multicast_group = (Ipv4Addr::new (225, 100, 99, 98), 9041);
|
|
|
|
Self {
|
|
multicast_group,
|
|
}
|
|
}
|
|
}
|
|
|
|
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;
|
|
|
|
socket.join_multicast_v4 (multicast_addr, Ipv4Addr::UNSPECIFIED)?;
|
|
eprintln! ("Multicast group is {:?}", params.multicast_group);
|
|
eprintln! ("Local addr is {}", socket.local_addr ()?);
|
|
|
|
socket.send_to (&[], params.multicast_group).await?;
|
|
|
|
Ok (())
|
|
}
|
|
|
|
fn spy (params: Params) -> Result <(), Error>
|
|
{
|
|
let (multicast_addr, multicast_port) = params.multicast_group;
|
|
|
|
let socket = match UdpSocket::bind (SocketAddrV4::new (Ipv4Addr::UNSPECIFIED, multicast_port)) {
|
|
Ok (x) => x,
|
|
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.");
|
|
return Err (Error::AddrInUse);
|
|
}
|
|
else {
|
|
return Err (e.into ());
|
|
}
|
|
};
|
|
|
|
for bind_addr in ip::get_ips ()? {
|
|
socket.join_multicast_v4 (&multicast_addr, &bind_addr)?;
|
|
// eprintln! ("Joined multicast with {}", bind_addr);
|
|
}
|
|
eprintln! ("Multicast addr is {}", multicast_addr);
|
|
eprintln! ("Local addr is {}", socket.local_addr ()?);
|
|
|
|
loop {
|
|
let mut buf = vec! [0u8; 2048];
|
|
|
|
eprintln! ("Listening for UDP packets...");
|
|
let (bytes_recved, remote_addr) = socket.recv_from (&mut buf)?;
|
|
buf.truncate (bytes_recved);
|
|
|
|
println! ("Received {} bytes from {}", bytes_recved, remote_addr);
|
|
}
|
|
}
|
|
|
|
#[derive (Debug, thiserror::Error)]
|
|
enum Error {
|
|
#[error ("Address in use")]
|
|
AddrInUse,
|
|
#[error ("CLI args")]
|
|
Args,
|
|
#[error (transparent)]
|
|
Io (#[from] std::io::Error),
|
|
#[error (transparent)]
|
|
Ip (#[from] ip::Error),
|
|
}
|