use blake2::digest::Mac;
use blake2::digest::consts::U16;
use blake2::{Blake2s256, Blake2sMac, Digest};
use hex_literal::hex;
use std::net::{IpAddr, Ipv4Addr, SocketAddr, UdpSocket};
use std::sync::atomic::{AtomicU16, Ordering};
use std::thread;
use std::time::Duration;
use wgproxy::config::Config;
pub const WGPROXY_PUBKEY: [u8; 32] = hex!("4B6172696E6D6167656E20 4B6172696E6D6167656E20 4B6172696E6D6167656E");
pub const WGPROXY_BASEPORT: u16 = 60000;
pub fn session() -> (Config, SocketAddr, UdpSocket) {
static PORT_COUNTER: AtomicU16 = AtomicU16::new(WGPROXY_BASEPORT);
let server_socket = UdpSocket::bind("127.0.0.1:0").expect("failed to create server socket");
let server_address = server_socket.local_addr().expect("failed to get server socket address");
let proxy_port = PORT_COUNTER.fetch_add(1, Ordering::SeqCst);
let proxy_address = SocketAddr::new(IpAddr::V4(Ipv4Addr::LOCALHOST), proxy_port);
let config = Config {
WGPROXY_SERVER: server_address.to_string(),
WGPROXY_PUBKEY,
WGPROXY_LISTEN: proxy_address,
WGPROXY_TIMEOUT: Duration::from_secs(3),
WGPROXY_LOGLEVEL: 1,
};
let config_ = config.clone();
thread::spawn(move || wgproxy::eventloop(config_));
thread::sleep(Duration::from_secs(3));
(config, proxy_address, server_socket)
}
pub fn handshake(public_key: &[u8; 32]) -> [u8; 148] {
const TEMPLATE: [u8; 148] = hex! {
"01000000"
"4B6172696E6D6167656E20 4B6172696E6D6167656E20 4B6172696E6D6167656E20 4B6172696E6D6167656E20"
"4B6172696E6D6167656E20 4B6172696E6D6167656E20 4B6172696E6D6167656E20 4B6172696E6D6167656E20"
"4B6172696E6D6167656E20 4B6172696E6D6167656E20 5858"
"58585858585858585858585858585858 00000000000000000000000000000000"
};
static HANDSHAKE_COUNTER: AtomicU16 = AtomicU16::new(0);
let mut packet = TEMPLATE;
let counter = HANDSHAKE_COUNTER.fetch_add(1, Ordering::SeqCst);
packet[114..116].copy_from_slice(&counter.to_be_bytes());
let label_pubkey_hash = Blake2s256::new().chain_update(b"mac1----").chain_update(public_key).finalize();
let mac1 = Blake2sMac::<U16>::new(&label_pubkey_hash).chain_update(&packet[..116]).finalize();
packet[116..132].copy_from_slice(&mac1.into_bytes());
packet
}