Last active
December 7, 2017 10:30
-
-
Save aniline/ebddc516ee198fd1fc3c58b6668f598d to your computer and use it in GitHub Desktop.
Multicast 'cat'
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// mc_cat <mc group> <port> [<from addr>] | consumer | |
// | |
use std::env; | |
use std::net::{UdpSocket, SocketAddrV4, IpAddr, Ipv4Addr}; | |
use std::str::FromStr; | |
use std::error::Error; | |
use std::io::Write; | |
macro_rules! eprintln(($($arg:tt)*) => { writeln!(&mut std::io::stderr(), $($arg)*).expect("Fail at failing."); } ); | |
fn getaddr() -> Option<(Ipv4Addr, u16, Option<Ipv4Addr>)> { | |
let mut args = env::args(); | |
let exe = args.next().unwrap(); | |
match args.len() { | |
2...3 => { | |
let addr = Ipv4Addr::from_str(&args.next().unwrap()); | |
let port = u16::from_str(&args.next().unwrap()); | |
if port.is_ok() && addr.is_ok() { | |
let addr_or_gtfo = |e: String| { | |
Ipv4Addr::from_str(&e).map_err(|x| { eprintln!("Bad Recv From address, ignoring."); x }).ok() | |
}; | |
return Some((addr.unwrap(), port.unwrap(), args.next().map_or(None, addr_or_gtfo))) | |
} | |
eprintln!("Bad MulticastV4 group or port spec."); | |
}, | |
_ => {}, | |
} | |
eprintln!("Usage: {} <mc_group>[:]<port>", exe); | |
None | |
} | |
fn do_mc_recv(mc_grp: &Ipv4Addr, port: u16, fa: &Option<Ipv4Addr>) | |
{ | |
#![allow(non_snake_case)] | |
let INADDR_ANY = Ipv4Addr::new(0,0,0,0); | |
let bind_addr: SocketAddrV4 = SocketAddrV4::new(INADDR_ANY, port); | |
let socket: UdpSocket = match UdpSocket::bind(bind_addr) { | |
Ok(socket) => socket, | |
Err(error) => { | |
eprintln!("Error (Bind): {}", &error.description()); | |
return | |
} | |
}; | |
match socket.join_multicast_v4(&mc_grp, &INADDR_ANY) { | |
Err(e) => eprintln!("Error join multicast: {}", &e.description()), | |
Ok(()) => { }, | |
} | |
let mut buf = [0u8; 65536]; | |
match *fa { | |
Some(faddr) => { | |
let from_addr = IpAddr::V4(faddr); | |
loop { | |
match socket.recv_from(&mut buf) { | |
Ok((n, saddr)) => { | |
if from_addr == saddr.ip() { | |
if (&mut std::io::stdout()) | |
.write(&buf[0..n]) | |
.is_err() { | |
return | |
} | |
} | |
}, | |
Err(err) => eprintln!("Err recv_from: {}", err), | |
} | |
} | |
} | |
None => { | |
loop { | |
match socket.recv_from(&mut buf) { | |
Ok((n, _)) => if (&mut std::io::stdout()).write(&buf[0..n]).is_err() { | |
return | |
}, | |
Err(err) => eprintln!("Err recv_from: {}", err), | |
} | |
} | |
} | |
} | |
} | |
fn main() { | |
let param = getaddr(); | |
match param { | |
Some((mc, port, fa)) => do_mc_recv(&mc, port, &fa), | |
None => () | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment