initial commit
This commit is contained in:
commit
5eb250212c
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
/target
|
||||||
|
**/*.rs.bk
|
||||||
|
Cargo.lock
|
8
Cargo.toml
Normal file
8
Cargo.toml
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
[package]
|
||||||
|
name = "wakey"
|
||||||
|
version = "0.1.0"
|
||||||
|
authors = ["Hubert Bugaj<lesny.rumcajs@gmail.com>"]
|
||||||
|
edition = "2018"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
hex = "0.3.2"
|
128
src/lib.rs
Normal file
128
src/lib.rs
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
extern crate hex;
|
||||||
|
|
||||||
|
use std::iter;
|
||||||
|
use std::net::{SocketAddr, ToSocketAddrs, UdpSocket};
|
||||||
|
|
||||||
|
const MAC_SIZE: usize = 6;
|
||||||
|
const MAC_PER_MAGIC: usize = 16;
|
||||||
|
|
||||||
|
/// Wake-on-LAN packet
|
||||||
|
pub struct WolPacket {
|
||||||
|
/// WOL packet bytes
|
||||||
|
packet: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl WolPacket {
|
||||||
|
/// Creates WOL packet from byte MAC representation
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// extern crate wakey;
|
||||||
|
/// let wol = wakey::WolPacket::from_bytes(&vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05]);
|
||||||
|
/// ```
|
||||||
|
pub fn from_bytes(mac: &[u8]) -> WolPacket {
|
||||||
|
static HEADER: [u8; 6] = [0xFF; 6];
|
||||||
|
let mut packet = Vec::with_capacity(HEADER.len() + MAC_SIZE * MAC_PER_MAGIC);
|
||||||
|
|
||||||
|
packet.extend(HEADER.iter());
|
||||||
|
packet.extend(WolPacket::extend_mac(mac));
|
||||||
|
|
||||||
|
WolPacket { packet }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates WOL packet from string MAC representation (e.x. 00:01:02:03:04:05)
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// extern crate wakey;
|
||||||
|
/// let wol = wakey::WolPacket::from_string("00:01:02:03:04:05", ':');
|
||||||
|
/// ```
|
||||||
|
pub fn from_string(data: &str, sep: char) -> WolPacket {
|
||||||
|
WolPacket::from_bytes(&WolPacket::mac_to_byte(data, sep))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Broadcasts the magic packet from / to default address
|
||||||
|
/// Source: 0.0.0.0:0
|
||||||
|
/// Destination 255.255.255.255:9
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// extern crate wakey;
|
||||||
|
/// let wol = wakey::WolPacket::from_bytes(&vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05]);
|
||||||
|
/// wol.send_magic();
|
||||||
|
/// ```
|
||||||
|
pub fn send_magic(&self) -> std::io::Result<()> {
|
||||||
|
self.send_magic_to(
|
||||||
|
SocketAddr::from(([0, 0, 0, 0], 0)),
|
||||||
|
SocketAddr::from(([255, 255, 255, 255], 9)),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Broadcasts the magic packet from / to specified address.
|
||||||
|
/// # Example
|
||||||
|
/// ```
|
||||||
|
/// extern crate wakey;
|
||||||
|
/// use std::net::SocketAddr;
|
||||||
|
/// let wol = wakey::WolPacket::from_bytes(&vec![0x00, 0x01, 0x02, 0x03, 0x04, 0x05]);
|
||||||
|
/// let src = SocketAddr::from(([0,0,0,0], 0));
|
||||||
|
/// let dst = SocketAddr::from(([255,255,255,255], 9));
|
||||||
|
/// wol.send_magic_to(src, dst);
|
||||||
|
/// ```
|
||||||
|
pub fn send_magic_to<A: ToSocketAddrs>(&self, src: A, dst: A) -> std::io::Result<()> {
|
||||||
|
let udp_sock = UdpSocket::bind(src)?;
|
||||||
|
udp_sock.set_broadcast(true)?;
|
||||||
|
udp_sock.send_to(&self.packet, dst)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Converts string representation of MAC address (e.x. 00:01:02:03:04:05) to raw bytes.
|
||||||
|
/// Panics when input MAC is invalid (i.e. contains non-byte characters)
|
||||||
|
fn mac_to_byte(data: &str, sep: char) -> Vec<u8> {
|
||||||
|
data.split(sep)
|
||||||
|
.map(|x| hex::decode(x).expect("Invalid mac!"))
|
||||||
|
.flatten()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Extends the MAC address to fill the magic packet
|
||||||
|
fn extend_mac(mac: &[u8]) -> Vec<u8> {
|
||||||
|
iter::repeat(mac)
|
||||||
|
.take(MAC_PER_MAGIC)
|
||||||
|
.flatten()
|
||||||
|
.cloned()
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
#[test]
|
||||||
|
fn extend_mac_test() {
|
||||||
|
let mac = vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06];
|
||||||
|
|
||||||
|
let extended_mac = super::WolPacket::extend_mac(&mac);
|
||||||
|
|
||||||
|
assert_eq!(extended_mac.len(), super::MAC_PER_MAGIC * super::MAC_SIZE);
|
||||||
|
assert_eq!(&extended_mac[90..], &mac[..]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn mac_to_byte_test() {
|
||||||
|
let mac = "01:02:03:04:05:06";
|
||||||
|
let result = super::WolPacket::mac_to_byte(mac, ':');
|
||||||
|
|
||||||
|
assert_eq!(result, vec![0x01, 0x02, 0x03, 0x04, 0x05, 0x06]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn mac_to_byte_invalid_chars_test() {
|
||||||
|
let mac = "ZZ:02:03:04:05:06";
|
||||||
|
super::WolPacket::mac_to_byte(mac, ':');
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
#[should_panic]
|
||||||
|
fn mac_to_byte_invalid_separator_test() {
|
||||||
|
let mac = "01002:03:04:05:06";
|
||||||
|
super::WolPacket::mac_to_byte(mac, ':');
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user