Jake Probst
5 years ago
10 changed files with 461 additions and 234 deletions
-
2Cargo.toml
-
131src/common/client.rs
-
190src/common/clientpool.rs
-
90src/common/mainloop.rs
-
2src/common/mod.rs
-
7src/common/serverstate.rs
-
56src/login/character.rs
-
40src/login/login.rs
-
107src/login/main.rs
-
38src/patch/main.rs
@ -0,0 +1,190 @@ |
|||||
|
use std::thread;
|
||||
|
use std::collections::HashMap;
|
||||
|
|
||||
|
use std::net::{SocketAddr, Ipv4Addr};
|
||||
|
|
||||
|
use std::sync::mpsc::TryRecvError;
|
||||
|
use mio::tcp::{TcpStream, TcpListener};
|
||||
|
use mio::{Events, Poll, Token, Ready, PollOpt};
|
||||
|
|
||||
|
use crate::common::client::Client;
|
||||
|
use crate::common::serverstate::{ServerState, SendServerPacket, RecvServerPacket, OnConnect, ClientId};
|
||||
|
//use std::sync::mpsc;
|
||||
|
//use mio::channel as mpsc;
|
||||
|
use libpso::crypto::PSOCipher;
|
||||
|
|
||||
|
use mio_extras::channel::{channel, Sender, Receiver};
|
||||
|
|
||||
|
use crate::common::network::PacketNetworkError;
|
||||
|
|
||||
|
use threadpool::ThreadPool;
|
||||
|
|
||||
|
const THREAD_COUNT: usize = 4;
|
||||
|
|
||||
|
fn client_read<S, R>(sender: &Sender<ClientPoolAction<R>>, client: &mut Client<S, R>) -> Result<(), PacketNetworkError> where
|
||||
|
S: SendServerPacket + std::fmt::Debug,
|
||||
|
R: RecvServerPacket + std::fmt::Debug,
|
||||
|
{
|
||||
|
println!("client read");
|
||||
|
let pkts = client.read_pkts();
|
||||
|
println!("pkts: {:?}", pkts);
|
||||
|
|
||||
|
for pkt in pkts? {
|
||||
|
sender.send(ClientPoolAction::Packet(client.id, pkt)).unwrap();
|
||||
|
}
|
||||
|
Ok(())
|
||||
|
}
|
||||
|
|
||||
|
fn client_write<S, R>(client: &mut Client<S, R>) where
|
||||
|
S: SendServerPacket + std::fmt::Debug,
|
||||
|
R: RecvServerPacket + std::fmt::Debug,
|
||||
|
{
|
||||
|
client.send_data();
|
||||
|
}
|
||||
|
|
||||
|
pub enum ClientAction<S> {
|
||||
|
EncryptionKeys(ClientId, Box<dyn PSOCipher + Send>, Box<dyn PSOCipher + Send>),
|
||||
|
Packet(ClientId, S)
|
||||
|
}
|
||||
|
|
||||
|
#[derive(Debug)]
|
||||
|
pub enum ClientPoolAction<R> {
|
||||
|
NewClient(ClientId),
|
||||
|
Packet(ClientId, R),
|
||||
|
}
|
||||
|
|
||||
|
|
||||
|
pub struct ClientPool<S, R>{
|
||||
|
poll: Poll,
|
||||
|
receiver: Receiver<ClientAction<S>>,
|
||||
|
sender: Sender<ClientPoolAction<R>>,
|
||||
|
client_ids: HashMap<Token, ClientId>,
|
||||
|
clients: HashMap<ClientId, Client<S, R>>,
|
||||
|
listener: TcpListener,
|
||||
|
client_id_incr: ClientId,
|
||||
|
}
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
impl<S, R> ClientPool<S, R> where
|
||||
|
S: SendServerPacket + std::fmt::Debug,
|
||||
|
R: RecvServerPacket + std::fmt::Debug,
|
||||
|
{
|
||||
|
pub fn new(
|
||||
|
receiver: Receiver<ClientAction<S>>,
|
||||
|
sender: Sender<ClientPoolAction<R>>,
|
||||
|
port: u16 |
||||
|
) -> ClientPool<S, R> {
|
||||
|
ClientPool {
|
||||
|
poll: Poll::new().unwrap(),
|
||||
|
receiver: receiver,
|
||||
|
sender: sender,
|
||||
|
client_ids: HashMap::new(),
|
||||
|
clients: HashMap::new(),
|
||||
|
listener: TcpListener::bind(&SocketAddr::from((Ipv4Addr::new(0,0,0,0), port))).unwrap(),
|
||||
|
client_id_incr: 3,
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
fn new_client(&mut self) {
|
||||
|
let (socket, _addr) = self.listener.accept().unwrap();
|
||||
|
|
||||
|
let client_id = self.client_id_incr;
|
||||
|
self.client_id_incr += 1;
|
||||
|
|
||||
|
self.poll.register(&socket, Token(client_id), Ready::readable() | Ready::writable(), PollOpt::edge()).unwrap();
|
||||
|
let client = Client::new(client_id, socket);
|
||||
|
|
||||
|
self.client_ids.insert(Token(client_id), client_id);
|
||||
|
self.clients.insert(client_id, client);
|
||||
|
self.sender.send(ClientPoolAction::NewClient(client_id)).unwrap();
|
||||
|
}
|
||||
|
|
||||
|
fn packet_to_send(&mut self) {
|
||||
|
loop {
|
||||
|
match self.receiver.try_recv() {
|
||||
|
Ok(action) => {
|
||||
|
match action {
|
||||
|
ClientAction::EncryptionKeys(client_id, cipher_in, cipher_out) => {
|
||||
|
println!("enc {:?}", client_id);
|
||||
|
self.clients.get_mut(&client_id)
|
||||
|
.map(|client| {
|
||||
|
client.set_cipher(cipher_in, cipher_out);
|
||||
|
});
|
||||
|
}
|
||||
|
ClientAction::Packet(client_id, pkt) => {
|
||||
|
println!("action pkt {:?}", pkt);
|
||||
|
println!("clients! {:?} {:?}", client_id, self.clients.get(&client_id).is_some());
|
||||
|
self.clients.get_mut(&client_id)
|
||||
|
.map(|client| {
|
||||
|
client.send_pkt(pkt);
|
||||
|
});
|
||||
|
}
|
||||
|
}
|
||||
|
},
|
||||
|
Err(err) => {
|
||||
|
println!("err! {:?}", err);
|
||||
|
match err {
|
||||
|
TryRecvError::Empty => break,
|
||||
|
TryRecvError::Disconnected => {
|
||||
|
// TODO!
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
|
||||
|
pub fn io_loop(mut self) {
|
||||
|
self.poll.register(&self.listener, Token(0), Ready::readable(), PollOpt::edge()).unwrap();
|
||||
|
self.poll.register(&self.receiver, Token(1), Ready::readable(), PollOpt::edge()).unwrap();
|
||||
|
|
||||
|
let mut events = Events::with_capacity(1024);
|
||||
|
|
||||
|
println!("looping");
|
||||
|
loop {
|
||||
|
self.poll.poll(&mut events, None).unwrap();
|
||||
|
println!("events! {:?}", events);
|
||||
|
|
||||
|
for event in &events {
|
||||
|
println!("event! {:?}", event);
|
||||
|
match event.token() {
|
||||
|
Token(0) => self.new_client(),
|
||||
|
Token(1) => self.packet_to_send(),
|
||||
|
_ => {
|
||||
|
|
||||
|
let client_id = match self.client_ids.get(&event.token()) {
|
||||
|
Some(client_id) => client_id,
|
||||
|
None => continue,
|
||||
|
};
|
||||
|
|
||||
|
let client = match self.clients.get_mut(&client_id) {
|
||||
|
Some(client) => client,
|
||||
|
None => continue,
|
||||
|
};
|
||||
|
|
||||
|
if event.readiness().is_writable() {
|
||||
|
client_write(client);
|
||||
|
}
|
||||
|
if event.readiness().is_readable() {
|
||||
|
match client_read(&self.sender, client) {
|
||||
|
Ok(()) =>{},
|
||||
|
Err(err) => {
|
||||
|
match err {
|
||||
|
PacketNetworkError::ClientDisconnected => {
|
||||
|
self.poll.deregister(&client.socket).unwrap();
|
||||
|
},
|
||||
|
_ => {},
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
@ -0,0 +1,90 @@ |
|||||
|
use std::thread;
|
||||
|
use mio::{Events, Poll, Token, Ready, PollOpt};
|
||||
|
use mio::tcp::TcpStream;
|
||||
|
use mio_extras::channel::{channel, Sender, Receiver};
|
||||
|
|
||||
|
use crate::common::clientpool::{ClientPool, ClientAction, ClientPoolAction};
|
||||
|
use crate::common::serverstate::{RecvServerPacket, SendServerPacket, ServerState, OnConnect, ClientId};
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
fn recv_from_clientpool<STATE, S, R, E>(state: &mut STATE,
|
||||
|
pool_recv: &Receiver<ClientPoolAction<R>>,
|
||||
|
pool_send: &Sender<ClientAction<S>>) where
|
||||
|
STATE: ServerState<SendPacket=S, RecvPacket=R, PacketError=E>,
|
||||
|
S: SendServerPacket,
|
||||
|
R: RecvServerPacket,
|
||||
|
E: std::fmt::Debug,
|
||||
|
{
|
||||
|
loop {
|
||||
|
match pool_recv.try_recv() {
|
||||
|
Ok(incoming) => {
|
||||
|
match incoming {
|
||||
|
ClientPoolAction::NewClient(client_id) => {
|
||||
|
for s in state.on_connect().into_iter() {
|
||||
|
match s {
|
||||
|
OnConnect::Cipher((in_cipher, out_cipher)) => {
|
||||
|
pool_send.send(ClientAction::EncryptionKeys(client_id, in_cipher, out_cipher)).unwrap();
|
||||
|
}
|
||||
|
OnConnect::Packet(pkt) => {
|
||||
|
pool_send.send(ClientAction::Packet(client_id, pkt)).unwrap();
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
},
|
||||
|
ClientPoolAction::Packet(client_id, pkt) => {
|
||||
|
let to_send = state.handle(client_id, &pkt);
|
||||
|
for s in to_send {
|
||||
|
pool_send.send(ClientAction::Packet(s.0, s.1)).unwrap();
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
},
|
||||
|
Err(_err) => {
|
||||
|
break;
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
|
||||
|
|
||||
|
pub fn mainloop<STATE, S, R, E>(mut state: STATE, port: u16) where
|
||||
|
STATE: ServerState<SendPacket=S, RecvPacket=R, PacketError=E> + Send + 'static,
|
||||
|
S: SendServerPacket + std::fmt::Debug + Send + 'static,
|
||||
|
R: RecvServerPacket + std::fmt::Debug + Send + 'static,
|
||||
|
E: std::fmt::Debug,
|
||||
|
{
|
||||
|
let (pool_send, pool_recv) = channel();
|
||||
|
//let (patch_handler_send, patch_handler_recv) = channel::<ClientPoolAction<RecvPatchPacket>>();
|
||||
|
let (handler_send, handler_recv) = channel();
|
||||
|
|
||||
|
//let sender_clone = patch_handler_send.clone();
|
||||
|
let client_thread = thread::spawn(move || {
|
||||
|
let clientpool = ClientPool::new(pool_recv, handler_send, port);
|
||||
|
clientpool.io_loop();
|
||||
|
});
|
||||
|
|
||||
|
let handler_threadpool = threadpool::ThreadPool::new(4);
|
||||
|
let handler_thread = thread::spawn(move || {
|
||||
|
let poll = Poll::new().unwrap();
|
||||
|
poll.register(&handler_recv, Token(0), Ready::readable(), PollOpt::edge()).unwrap();
|
||||
|
|
||||
|
let mut events = Events::with_capacity(1024);
|
||||
|
|
||||
|
loop {
|
||||
|
poll.poll(&mut events, None).unwrap();
|
||||
|
|
||||
|
for event in &events {
|
||||
|
match event.token() {
|
||||
|
Token(0) => recv_from_clientpool(&mut state, &handler_recv, &pool_send),
|
||||
|
_ => panic!()
|
||||
|
}
|
||||
|
}
|
||||
|
}
|
||||
|
});
|
||||
|
|
||||
|
client_thread.join().unwrap();
|
||||
|
handler_thread.join().unwrap();
|
||||
|
}
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue