use crate::codec::AuthChoice;
use crate::messages::*;
use actix::prelude::*;
use actix::{Actor, Context, Handler};
use log::debug;
use rand::rngs::ThreadRng;
use rand::Rng;
use std::collections::HashMap;
const MUST_AUTH: bool = true;
#[derive(Clone)]
pub struct ProxyServer {
sessions: HashMap<usize, Recipient<ToSession>>,
rng: ThreadRng,
}
impl Default for ProxyServer {
fn default() -> Self {
ProxyServer {
sessions: HashMap::new(),
rng: rand::thread_rng(),
}
}
}
impl ProxyServer {
pub fn auth_choice(auths: &[u8]) -> AuthChoice {
for auth in auths {
if *auth == 0x02 {
return AuthChoice::UserNamePwd;
}
if *auth == 0x00 && !MUST_AUTH {
return AuthChoice::NoAuth;
}
if *auth == 0x00 && MUST_AUTH {
return AuthChoice::UserNamePwd;
}
}
AuthChoice::NoAcceptable
}
}
impl Actor for ProxyServer {
type Context = Context<Self>;
fn started(&mut self, _ctx: &mut Self::Context) {}
}
impl Handler<ToProxyServer> for ProxyServer {
type Result = MessageResult<ToProxyServer>;
fn handle(&mut self, command: ToProxyServer, _ctx: &mut Context<Self>) -> Self::Result {
match command {
ToProxyServer::Connect(recipient) => {
debug!("connect");
let id = self.rng.gen::<usize>();
self.sessions.insert(id, recipient.clone());
recipient.do_send(ToSession::ProxyServerReply(ProxyServerReply::Id(id)));
MessageResult(ProxyServerReply::Id(id))
}
ToProxyServer::DisConnect(id) => {
debug!("disconnect");
self.sessions.remove(&id);
MessageResult(ProxyServerReply::Ok)
}
ToProxyServer::OnlineCounter(id) => {
let len = self.sessions.len();
if let Some(session) = self.sessions.get(&id) {
session.do_send(ToSession::ProxyServerReply(
ProxyServerReply::OnlineCounter(len),
));
}
MessageResult(ProxyServerReply::OnlineCounter(len))
}
ToProxyServer::Cli(id, cli) => {
let cmd: Vec<String> = cli.into();
debug!("server recv cmd = {:?}", cmd);
match (self.sessions.get(&id), cmd.as_slice()) {
(Some(session), [c]) if c == "online_counter" => {
let len = self.sessions.len();
session.do_send(ToSession::ProxyServerReply(ProxyServerReply::Cli(
inn_common::cli::Cli::Integers(len as i64),
)));
}
(Some(session), [c]) if c == "stop" => {
session.do_send(ToSession::Stop);
}
_ => {}
}
MessageResult(ProxyServerReply::Ok)
}
ToProxyServer::HttpReq(http_req) => {
debug!("{:?}", http_req);
let msg = ToSession::ProxyServerReply(ProxyServerReply::HttpReq(http_req));
for s in self.sessions.values() {
s.do_send(msg.clone());
}
MessageResult(ProxyServerReply::Ok)
}
}
}
}
#[cfg(test)]
mod test {
use super::*;
pub struct Session;
impl Actor for Session {
type Context = Context<Self>;
fn started(&mut self, _: &mut Context<Self>) {}
}
impl Handler<ToSession> for Session {
type Result = MessageResult<ToSession>;
fn handle(&mut self, _: ToSession, _: &mut Context<Self>) -> Self::Result {
MessageResult(SessionReply::Ok)
}
}
#[actix_rt::test]
async fn new_session() {
let addr = ProxyServer::default().start();
let session = Session.start();
let counter = addr.send(ToProxyServer::OnlineCounter(0)).await.unwrap();
assert_eq!(counter, ProxyServerReply::OnlineCounter(0));
let id = addr
.send(ToProxyServer::Connect(session.recipient()))
.await
.unwrap();
match id {
ProxyServerReply::Id(id) => {
let counter = addr.send(ToProxyServer::OnlineCounter(0)).await.unwrap();
assert_eq!(counter, ProxyServerReply::OnlineCounter(1));
let rs = addr.send(ToProxyServer::DisConnect(id)).await.unwrap();
assert_eq!(rs, ProxyServerReply::Ok);
let counter = addr.send(ToProxyServer::OnlineCounter(0)).await.unwrap();
assert_eq!(counter, ProxyServerReply::OnlineCounter(0));
}
e => {
panic!("{:?}", e);
}
}
}
}