Crates.io | autodiscover-rs |
lib.rs | autodiscover-rs |
version | 0.1.1 |
source | src |
created_at | 2020-07-04 07:28:11.502366 |
updated_at | 2020-07-08 05:59:43.161188 |
description | autodiscover-rs implements a simple algorithm to detect peers on an IP network, connects to them, and calls back with the connected stream. The algorthm supports both UDP broadcast and multicasting. |
homepage | https://github.com/over-codes/autodiscover-rs |
repository | https://github.com/over-codes/autodiscover-rs |
max_upload_size | |
id | 261207 |
size | 19,154 |
autodiscover-rs implements a simple algorithm to detect peers on an IP network, connects to them, and calls back with the connected stream. The algorithm supports both UDP broadcast and multicasting.
Cargo.toml
autodiscover-rs = "0.1.0"
In your app:
use std::net::{TcpListener, TcpStream};
use std::thread;
use autodiscover_rs::{self, Method};
use env_logger;
fn handle_client(stream: std::io::Result<TcpStream>) {
println!("Got a connection from {:?}", stream.unwrap().peer_addr());
}
fn main() -> std::io::Result<()> {
env_logger::init();
// make sure to bind before announcing ready
let listener = TcpListener::bind(":::0")?;
// get the port we were bound too; note that the trailing :0 above gives us a random unused port
let socket = listener.local_addr()?;
thread::spawn(move || {
// this function blocks forever; running it a seperate thread
autodiscover_rs::run(&socket, Method::Multicast("[ff0e::1]:1337".parse().unwrap()), |s| {
// change this to task::spawn if using async_std or tokio
thread::spawn(|| handle_client(s));
}).unwrap();
});
let mut incoming = listener.incoming();
while let Some(stream) = incoming.next() {
// if you are using an async library, such as async_std or tokio, you can convert the stream to the
// appropriate type before using task::spawn from your library of choice.
thread::spawn(|| handle_client(stream));
}
Ok(())
}
The algorithm for peer discovery is to:
This has a few gotchas:
If a broadcast packet goes missing, some connections won't be made
The IP address we are broadcasting is of the form:
IPv4:
buff[0..4].clone_from_slice(&addr.ip().octets());
buff[4..6].clone_from_slice(&addr.port().to_be_bytes());
IPv6:
buff[0..16].clone_from_slice(&addr.ip().octets());
buff[16..18].clone_from_slice(&addr.port().to_be_bytes());