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
#[macro_use]
extern crate lazy_static;

mod photon_decode;
mod packet_sniffer;
pub mod photon_messages;
pub mod game;
mod translate;
mod publisher;

use log::*;
use simplelog::*;
use std::env;
use std::fs::File;
use std::sync::mpsc::{channel, Receiver, Sender};
use std::thread;

use packet_sniffer::UdpPacket;
use photon_decode::Photon;

use crate::game::World;
use crate::publisher::Publisher;

pub use crate::publisher::Subscribers;

use crate::translate::udp_packet_to_game_events;

pub enum InitializationError {
    NetworkInterfaceListMissing,
}

pub fn initialize(subscribers: Subscribers) -> Result<(), InitializationError> {
    initialize_logging();
    if let Ok(interfaces) = packet_sniffer::network_interfaces() {
        thread::spawn(move || {
            let (tx, rx): (Sender<UdpPacket>, Receiver<UdpPacket>) = channel();

            let mut photon = Photon::new();
            let mut world = World::new();
            let mut publisher = Publisher::new(subscribers);

            packet_sniffer::receive(interfaces, tx);
            info!("Listening to network packets...");
            loop {
                if let Ok(packet) = rx.recv() {
                    udp_packet_to_game_events(&mut world, &mut photon, &packet)
                        .into_iter()
                        .for_each(|e| {
                            publisher.publish(&e);
                        });
                }
            }
        });
    } else {
        return Err(InitializationError::NetworkInterfaceListMissing);
    }

    Ok(())
}

fn initialize_logging() {
    CombinedLogger::init(vec![WriteLogger::new(
        get_logging_level(),
        Config::default(),
        File::create("aoaddons.log").unwrap(),
    )])
    .unwrap();
}

fn get_logging_level() -> LevelFilter {
    match env::var("BACKEND_LOG_LEVEL")
        .unwrap_or("INFO".into())
        .to_lowercase()
        .as_str()
    {
        "debug" => LevelFilter::Debug,
        _ => LevelFilter::Info,
    }
}