<commit_before>extern crate idola;
extern crate crypto;
extern crate psocrypto;
extern crate byteorder;
extern crate rand;
#[macro_use] extern crate log;
extern crate env_logger;

use std::thread;
use std::io;
use std::io::{Write, Read};
use std::net::{TcpListener, TcpStream};
use std::fmt::Debug;

use idola::message::{MessageEncode, MessageDecode};
use idola::message::patch::Message;

use psocrypto::PcCipher;

use crypto::symmetriccipher::Decryptor;

#[derive(Clone, Copy)]
enum ClientState {
    Connected,
    Welcomed
}

struct ClientContext {
    pub stream: TcpStream,
    pub state: ClientState,
    pub client_cipher: PcCipher,
    pub server_cipher: PcCipher
}

impl ClientContext {
    /// Send a message struct.
    fn send_msg<T: MessageEncode + Debug>(&mut self, msg: &T, encrypt: bool) -> io::Result<()> {
        if encrypt {
            debug!("msg send: {:?}", msg);
            try!(msg.encode_msg(&mut self.stream as &mut Write, Some(&mut self.server_cipher)));
            self.stream.flush()
        } else {
            debug!("msg send (unenc): {:?}", msg);
            try!(msg.encode_msg(&mut self.stream as &mut Write, None));
            self.stream.flush()
        }
    }

    /// Receive a message enum.
    fn recv_msg(&mut self, decrypt: bool) -> io::Result<Message> {
        if decrypt {
            let m = Message::decode_msg(&mut self.stream as &mut Read, Some(&mut self.client_cipher as &mut Decryptor));
            match m {
                Ok(m) => {debug!("msg recv: {:?}", m); Ok(m)},
                e => e
            }
        } else {
            let m = Message::decode_msg(&mut self.stream as &mut Read, None);
            match m {
                Ok(m) => {debug!("msg recv (unenc): {:?}", m); Ok(m)},
                e => e
            }
        }
    }
}

unsafe impl Send for ClientState {}
unsafe impl Send for ClientContext {}

fn handle_client(mut ctx: ClientContext) {
    use idola::message::patch::*;

    let peer_addr = ctx.stream.peer_addr().unwrap();

    info!("client {} connected", peer_addr);

    let w = Welcome {
        server_vector: ctx.server_cipher.seed(),
        client_vector: ctx.client_cipher.seed()
    };
    if let Err(e) = ctx.send_msg(&w, false) {
        error!("unable to send welcome message to {}: {}", peer_addr, e);
        return
    }
    info!("client {} welcomed", peer_addr);

    ctx.state = ClientState::Welcomed;

    // Client will send a Welcome message as an ack. We reply with a Login ack.
    if let Ok(s) = ctx.recv_msg(true) {
        info!("received a message after being welcomed");
        if let Message::Welcome(None) = s {
            info!("sending login ack");
            match ctx.send_msg(&Message::Login(None), true) { Err(_) => return, _ => () }
        }
    }

    loop {
        use std::net::Ipv4Addr;
        use std::str::FromStr;
        // Read message
        if let Ok(s) = ctx.recv_msg(true) {match s {
            Message::Login(Some(_)) => {
                let motd = Motd {
                    message: "how am I gonna feed all these little... BABS\nhey there\n\nrust is cool".to_string()
                };
                ctx.send_msg(&motd, true).unwrap();
                let red = Redirect { ip_addr: Ipv4Addr::from_str("127.0.0.1").unwrap(), port: 11001 };
                ctx.send_msg(&red, true).unwrap();
                // Now we break out of this connection.
                return;
            },
            _ => println!("uhhh")
        }}
    };
}

fn main() {
    if let Err(_) = std::env::var("RUST_LOG") {
        std::env::set_var("RUST_LOG", "DEBUG");
        std::env::set_var("RUST_BACKTRACE", "1");
    }
    env_logger::init().unwrap();

    info!("IDOLA Phantasy Star Online Patch Server");
    info!("Version 0.1.0");

    let tcp_listener = TcpListener::bind("127.0.0.1:11000").unwrap();
    for stream in tcp_listener.incoming() {
        match stream {
            Ok(s) => {
                let ctx = ClientContext {
                    stream: s,
                    state: ClientState::Connected,
                    client_cipher: PcCipher::new(0),
                    server_cipher: PcCipher::new(0)
                };
                thread::spawn(move|| handle_client(ctx));
            },
            Err(e) => {println!("Error: could not accept connection from {}", e);}
        };
    }
    println!("Placeholders");
}<commit_msg>Should probably randomize those patch server keys.<commit_after>extern crate idola;
extern crate crypto;
extern crate psocrypto;
extern crate byteorder;
extern crate rand;
#[macro_use] extern crate log;
extern crate env_logger;

use std::thread;
use std::io;
use std::io::{Write, Read};
use std::net::{TcpListener, TcpStream};
use std::fmt::Debug;

use idola::message::{MessageEncode, MessageDecode};
use idola::message::patch::Message;

use psocrypto::PcCipher;

use crypto::symmetriccipher::Decryptor;

use rand::random;

#[derive(Clone, Copy)]
enum ClientState {
    Connected,
    Welcomed
}

struct ClientContext {
    pub stream: TcpStream,
    pub state: ClientState,
    pub client_cipher: PcCipher,
    pub server_cipher: PcCipher
}

impl ClientContext {
    /// Send a message struct.
    fn send_msg<T: MessageEncode + Debug>(&mut self, msg: &T, encrypt: bool) -> io::Result<()> {
        if encrypt {
            debug!("msg send: {:?}", msg);
            try!(msg.encode_msg(&mut self.stream as &mut Write, Some(&mut self.server_cipher)));
            self.stream.flush()
        } else {
            debug!("msg send (unenc): {:?}", msg);
            try!(msg.encode_msg(&mut self.stream as &mut Write, None));
            self.stream.flush()
        }
    }

    /// Receive a message enum.
    fn recv_msg(&mut self, decrypt: bool) -> io::Result<Message> {
        if decrypt {
            let m = Message::decode_msg(&mut self.stream as &mut Read, Some(&mut self.client_cipher as &mut Decryptor));
            match m {
                Ok(m) => {debug!("msg recv: {:?}", m); Ok(m)},
                e => e
            }
        } else {
            let m = Message::decode_msg(&mut self.stream as &mut Read, None);
            match m {
                Ok(m) => {debug!("msg recv (unenc): {:?}", m); Ok(m)},
                e => e
            }
        }
    }
}

unsafe impl Send for ClientState {}
unsafe impl Send for ClientContext {}

fn handle_client(mut ctx: ClientContext) {
    use idola::message::patch::*;

    let peer_addr = ctx.stream.peer_addr().unwrap();

    info!("client {} connected", peer_addr);

    let w = Welcome {
        server_vector: ctx.server_cipher.seed(),
        client_vector: ctx.client_cipher.seed()
    };
    if let Err(e) = ctx.send_msg(&w, false) {
        error!("unable to send welcome message to {}: {}", peer_addr, e);
        return
    }
    info!("client {} welcomed", peer_addr);

    ctx.state = ClientState::Welcomed;

    // Client will send a Welcome message as an ack. We reply with a Login ack.
    if let Ok(s) = ctx.recv_msg(true) {
        info!("received a message after being welcomed");
        if let Message::Welcome(None) = s {
            info!("sending login ack");
            match ctx.send_msg(&Message::Login(None), true) { Err(_) => return, _ => () }
        }
    }

    loop {
        use std::net::Ipv4Addr;
        use std::str::FromStr;
        // Read message
        if let Ok(s) = ctx.recv_msg(true) {match s {
            Message::Login(Some(_)) => {
                let motd = Motd {
                    message: "how am I gonna feed all these little... BABS\nhey there\n\nrust is cool".to_string()
                };
                ctx.send_msg(&motd, true).unwrap();
                let red = Redirect { ip_addr: Ipv4Addr::from_str("127.0.0.1").unwrap(), port: 11001 };
                ctx.send_msg(&red, true).unwrap();
                // Now we break out of this connection.
                return;
            },
            _ => println!("uhhh")
        }}
    };
}

fn main() {
    if let Err(_) = std::env::var("RUST_LOG") {
        std::env::set_var("RUST_LOG", "DEBUG");
        std::env::set_var("RUST_BACKTRACE", "1");
    }
    env_logger::init().unwrap();

    info!("IDOLA Phantasy Star Online Patch Server");
    info!("Version 0.1.0");

    let tcp_listener = TcpListener::bind("127.0.0.1:11000").unwrap();
    for stream in tcp_listener.incoming() {
        match stream {
            Ok(s) => {
                let ctx = ClientContext {
                    stream: s,
                    state: ClientState::Connected,
                    client_cipher: PcCipher::new(random()),
                    server_cipher: PcCipher::new(random())
                };
                thread::spawn(move|| handle_client(ctx));
            },
            Err(e) => {println!("Error: could not accept connection from {}", e);}
        };
    }
    println!("Placeholders");
}
{'fraction_non_alphanumeric': 0.1480981318928652, 'fraction_numerical': 0.006527121314427189, 'mean_word_length': 2.1436151397240892, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 33, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 4, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3063202', 'n_tokens_mistral': 2801, 'n_tokens_neox': 2723, 'n_words': 694}