albion_handler/
lib.rs

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}