#![allow(dead_code, unused_must_use, unused_variables, unused_imports)]
use std::thread::{self,Thread,Builder};
use std::sync::mpsc::TryRecvError;
use std::net::{SocketAddr,Shutdown};
use mio::net::*;
use mio::*;
use mio::unix::UnixReady;
use mio::timer::{Timer,Timeout};
use std::collections::{HashSet,HashMap};
use std::io::{self,Read,ErrorKind};
use nom::HexDisplay;
use std::error::Error;
use slab::Slab;
use std::io::Write;
use std::str::FromStr;
use std::marker::PhantomData;
use std::fmt::Debug;
use time::precise_time_ns;
use std::time::Duration;
use rand::random;
use network::{ClientResult,MessageId,ServerMessage,ServerMessageStatus,ConnectionError,
SocketType,Protocol,ProxyOrder,RequiredEvents};
use network::{http,tls,tcp};
use network::session::{BackToken,FrontToken,ListenToken,ProxyClient,ProxyConfiguration,Readiness,Session};
use messages::{self,TcpFront,Order,Instance};
use channel::Channel;
const SERVER: Token = Token(0);
const DEFAULT_FRONT_TIMEOUT: u64 = 50000;
const DEFAULT_BACK_TIMEOUT: u64 = 50000;
pub type ProxyChannel = Channel<ServerMessage,ProxyOrder>;
#[derive(Debug,Clone,PartialEq)]
enum ProxyType {
HTTP,
HTTPS,
TCP,
}
pub struct Server<Client> {
clients: Slab<Client,FrontToken>,
backend: Slab<FrontToken,BackToken>,
max_listeners: usize,
max_connections: usize,
pub poll: Poll,
timer: Timer<Token>,
shutting_down: Option<MessageId>,
accept_ready: HashSet<ListenToken>,
can_accept: bool,
channel: ProxyChannel,
http: Option<Session<http::ServerConfiguration, http::Client>>,
https: Option<Session<tls::ServerConfiguration, tls::TlsClient>>,
tcp: Option<Session<tcp::ServerConfiguration, tcp::Client>>,
}
impl<Client:ProxyClient> Server<Client> {
pub fn new(max_listeners: usize, max_connections: usize, poll: Poll, channel: ProxyChannel,
http: Option<Session<http::ServerConfiguration, http::Client>>, https: Option<Session<tls::ServerConfiguration, tls::TlsClient>>,
tcp: Option<Session<tcp::ServerConfiguration, tcp::Client>>) -> Self {
poll.register(
&channel,
Token(0),
Ready::readable() | Ready::writable() | Ready::from(UnixReady::hup() | UnixReady::error()),
PollOpt::edge()
).expect("should register the channel");
let clients = Slab::with_capacity(max_connections);
let backend = Slab::with_capacity(max_connections);
let timer = Timer::default();
Server {
clients: clients,
backend: backend,
max_listeners: max_listeners,
max_connections: max_connections,
poll: poll,
timer: timer,
shutting_down: None,
accept_ready: HashSet::new(),
can_accept: true,
channel: channel,
http: http,
https: https,
tcp: tcp,
}
}
pub fn to_front(&self, token: Token) -> FrontToken {
FrontToken(token.0 - 2 - self.max_listeners)
}
pub fn to_back(&self, token: Token) -> BackToken {
BackToken(token.0 - 2 - self.max_listeners - self.max_connections)
}
pub fn from_front(&self, token: FrontToken) -> Token {
Token(token.0 + 2 + self.max_listeners )
}
pub fn from_back(&self, token: BackToken) -> Token {
Token(token.0 + 2 + self.max_listeners + self.max_connections)
}
}
type Message = ProxyOrder;
impl<Client:ProxyClient> Server<Client> {
pub fn run(&mut self) {
let mut events = Events::with_capacity(1024);
let poll_timeout = Some(Duration::from_millis(1000));
loop {
self.poll.poll(&mut events, poll_timeout).expect("should be able to poll for events");
for event in events.iter() {
if event.token() == Token(0) {
let kind = event.readiness();
if UnixReady::from(kind).is_error() {
error!("error reading from command channel");
continue;
}
if UnixReady::from(kind).is_hup() {
error!("command channel was closed");
continue;
}
self.channel.handle_events(kind);
self.channel.run();
loop {
let msg = self.channel.read_message();
if msg.is_none() {
if (self.channel.interest & self.channel.readiness).is_readable() {
self.channel.run();
continue;
} else {
break;
}
}
let msg = msg.expect("the message should be valid");
if let Order::HardStop = msg.order {
self.notify(msg);
self.channel.run();
return;
} else if let Order::SoftStop = msg.order {
self.shutting_down = Some(msg.id.clone());
self.notify(msg);
} else {
self.notify(msg);
}
}
self.channel.run();
} else if event.token() == Token(1) {
while let Some(token) = self.timer.poll() {
self.timeout(token);
}
} else {
match proxy_type(event.token().0) {
ProxyType::HTTP => if let Some(mut http) = self.http.take() {
http.ready(&mut self.poll, event.token(), event.readiness());
self.http = Some(http);
},
ProxyType::HTTPS => if let Some(mut https) = self.https.take() {
https.ready(&mut self.poll, event.token(), event.readiness());
self.https = Some(https);
},
ProxyType::TCP => if let Some(mut tcp) = self.tcp.take() {
tcp.ready(&mut self.poll, event.token(), event.readiness());
self.tcp = Some(tcp);
},
};
}
}
if let Some(mut http) = self.http.take() {
http.handle_remaining_readiness(&mut self.poll);
self.http = Some(http);
}
if let Some(mut https) = self.https.take() {
https.handle_remaining_readiness(&mut self.poll);
self.https = Some(https);
}
if let Some(mut tcp) = self.tcp.take() {
tcp.handle_remaining_readiness(&mut self.poll);
self.tcp = Some(tcp);
}
while let Some(token) = self.timer.poll() {
self.timeout(token);
}
if self.shutting_down.is_some() && self.clients.len() == 0 {
info!("last client stopped, shutting down!");
self.channel.write_message(&ServerMessage{ id: self.shutting_down.take().expect("should have shut down correctly"), status: ServerMessageStatus::Ok});
self.channel.run();
return;
}
}
}
fn notify(&mut self, message: Message) {
if let Some(mut http) = self.http.take() {
http.configuration().notify(&mut self.poll, &mut self.channel, message.clone());
self.http = Some(http);
}
if let Some(mut https) = self.https.take() {
https.configuration().notify(&mut self.poll, &mut self.channel, message.clone());
self.https = Some(https);
}
if let Some(mut tcp) = self.tcp.take() {
tcp.configuration().notify(&mut self.poll, &mut self.channel, message);
self.tcp = Some(tcp);
}
}
fn timeout(&mut self, token: Token) {
}
}
fn proxy_type(token: usize) -> ProxyType {
if token < 6148914691236517205 {
ProxyType::HTTP
} else if token < 12297829382473034410 {
ProxyType::HTTPS
} else {
ProxyType::TCP
}
}