albion_handler/
lib.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use photon_decode::{Message, Photon};
use pnet::{
    datalink::{self, Channel, Config, NetworkInterface},
    packet::{
        ethernet::{EtherTypes::Ipv4, EthernetPacket},
        ip::IpNextHeaderProtocols,
        ipv4::Ipv4Packet,
        Packet,
    },
};
use std::{
    sync::mpsc::{channel, Receiver, Sender},
    sync::{Arc, Mutex},
    thread,
};

pub type UdpPacketPayload = Vec<u8>;

const GAME_PORT: u16 = 5056;
const MAX_PACKET_SIZE: usize = 1600;

pub fn listen_packets<F>(cb: F)
where
    F: Fn(Message) + Send + Sync + 'static,
{
    let interfaces = get_network_interfaces().unwrap();
    let (tx, rx): (Sender<UdpPacketPayload>, Receiver<UdpPacketPayload>) = channel();
    receive(interfaces, tx);
    decode(rx, cb);
}

fn decode<F>(rx: Receiver<UdpPacketPayload>, cb: F)
where
    F: Fn(Message) + Send + Sync + 'static,
{
    let mut photon = Photon::new();
    thread::spawn(move || {
        for udp_packet in rx {
            for message in photon.decode(&udp_packet) {
                cb(message)
            }
        }
    });
}

fn get_network_interfaces() -> Result<Vec<NetworkInterface>, &'static str> {
    Ok(datalink::interfaces()
        .into_iter()
        .filter(|i| !i.is_loopback())
        .collect::<Vec<NetworkInterface>>())
}

fn receive(interfaces: Vec<NetworkInterface>, tx: Sender<UdpPacketPayload>) {
    let shared_tx = Arc::new(Mutex::new(tx));

    let config = Config {
        write_buffer_size: MAX_PACKET_SIZE,
        read_buffer_size: MAX_PACKET_SIZE,
        ..Default::default()
    };

    for interface in interfaces {
        let tx = shared_tx.clone();

        let mut rx = match datalink::channel(&interface, config) {
            Ok(Channel::Ethernet(_, rx)) => rx,
            _ => continue,
        };

        thread::spawn(move || loop {
            match rx.next() {
                Ok(packet) => {
                    let ethernet = &EthernetPacket::new(packet).unwrap();
                    if ethernet.get_ethertype() == Ipv4 {
                        let header = Ipv4Packet::new(ethernet.payload()).unwrap();
                        let next_header = header.get_next_level_protocol();

                        if next_header == IpNextHeaderProtocols::Udp {
                            let udp = pnet::packet::udp::UdpPacket::new(header.payload()).unwrap();
                            let udp_source = udp.get_source();
                            let udp_destination = udp.get_destination();

                            if udp_source == GAME_PORT || udp_destination == GAME_PORT {
                                let tx = tx.lock().unwrap();
                                tx.send(Vec::from(udp.payload())).unwrap();
                            }
                        }
                    }
                }
                Err(_) => continue,
            };
        });
    }
}