1use photon_decode::{Message, Photon};
2use pnet::{
3 datalink::{self, Channel, Config, NetworkInterface},
4 packet::{
5 ethernet::{EtherTypes::Ipv4, EthernetPacket},
6 ip::IpNextHeaderProtocols,
7 ipv4::Ipv4Packet,
8 Packet,
9 },
10};
11use std::{
12 sync::mpsc::{channel, Receiver, Sender},
13 sync::{Arc, Mutex},
14 thread,
15};
16
17pub type UdpPacketPayload = Vec<u8>;
18
19const GAME_PORT: u16 = 5056;
20const MAX_PACKET_SIZE: usize = 1600;
21
22pub fn listen_packets<F>(cb: F)
23where
24 F: Fn(Message) + Send + Sync + 'static,
25{
26 let interfaces = get_network_interfaces().unwrap();
27 let (tx, rx): (Sender<UdpPacketPayload>, Receiver<UdpPacketPayload>) = channel();
28 receive(interfaces, tx);
29 decode(rx, cb);
30}
31
32fn decode<F>(rx: Receiver<UdpPacketPayload>, cb: F)
33where
34 F: Fn(Message) + Send + Sync + 'static,
35{
36 let mut photon = Photon::new();
37 thread::spawn(move || {
38 for udp_packet in rx {
39 for message in photon.decode(&udp_packet) {
40 cb(message)
41 }
42 }
43 });
44}
45
46fn get_network_interfaces() -> Result<Vec<NetworkInterface>, &'static str> {
47 Ok(datalink::interfaces()
48 .into_iter()
49 .filter(|i| !i.is_loopback())
50 .collect::<Vec<NetworkInterface>>())
51}
52
53fn receive(interfaces: Vec<NetworkInterface>, tx: Sender<UdpPacketPayload>) {
54 let shared_tx = Arc::new(Mutex::new(tx));
55
56 let config = Config {
57 write_buffer_size: MAX_PACKET_SIZE,
58 read_buffer_size: MAX_PACKET_SIZE,
59 ..Default::default()
60 };
61
62 for interface in interfaces {
63 let tx = shared_tx.clone();
64
65 let mut rx = match datalink::channel(&interface, config) {
66 Ok(Channel::Ethernet(_, rx)) => rx,
67 _ => continue,
68 };
69
70 thread::spawn(move || loop {
71 match rx.next() {
72 Ok(packet) => {
73 let ethernet = &EthernetPacket::new(packet).unwrap();
74 if ethernet.get_ethertype() == Ipv4 {
75 let header = Ipv4Packet::new(ethernet.payload()).unwrap();
76 let next_header = header.get_next_level_protocol();
77
78 if next_header == IpNextHeaderProtocols::Udp {
79 let udp = pnet::packet::udp::UdpPacket::new(header.payload()).unwrap();
80 let udp_source = udp.get_source();
81 let udp_destination = udp.get_destination();
82
83 if udp_source == GAME_PORT || udp_destination == GAME_PORT {
84 let tx = tx.lock().unwrap();
85 tx.send(Vec::from(udp.payload())).unwrap();
86 }
87 }
88 }
89 }
90 Err(_) => continue,
91 };
92 });
93 }
94}