use crate::courierust_body::Body;
use crate::courierust_http::header::HeaderMap;
use crate::courierust_http::response::Response;
use crate::courierust_http::status::StatusCode;
use crate::courierust_io::{BufReader, Read, Write};
use crate::courierust_net::ConnStream;
use std::net::{Shutdown, SocketAddr};
use std::sync::Arc;
use std::time::Duration;
pub enum TunnelReply {
Pass,
Refuse(Response<Body>),
Accept(TunnelPlan),
}
pub struct TunnelPlan {
pub status: StatusCode,
pub headers: HeaderMap,
pub service: Arc<dyn TunnelService>,
}
impl TunnelPlan {
pub fn connect(service: Arc<dyn TunnelService>) -> Self {
Self {
status: StatusCode::OK,
headers: HeaderMap::new(),
service,
}
}
pub fn switching(service: Arc<dyn TunnelService>) -> Self {
Self {
status: StatusCode::SWITCHING_PROTOCOLS,
headers: HeaderMap::new(),
service,
}
}
}
pub trait TunnelService: Send + Sync + 'static {
fn run(&self, conn: TunnelConn);
}
impl<F> TunnelService for F
where
F: Fn(TunnelConn) + Send + Sync + 'static,
{
fn run(&self, conn: TunnelConn) {
self(conn)
}
}
pub struct TunnelConn {
stream: Arc<ConnStream>,
reader: BufReader<Arc<ConnStream>>,
secure: bool,
}
impl TunnelConn {
pub(crate) fn new(
stream: Arc<ConnStream>,
reader: BufReader<Arc<ConnStream>>,
secure: bool,
) -> Self {
Self {
stream,
reader,
secure,
}
}
pub fn peer_addr(&self) -> SocketAddr {
self.stream.peer_addr()
}
pub fn is_secure(&self) -> bool {
self.secure
}
pub fn alpn(&self) -> Option<Vec<u8>> {
self.stream.alpn()
}
pub fn configure(&self, read_timeout: Option<Duration>) -> crate::courierust_error::Result<()> {
self.stream.configure(read_timeout)
}
pub fn set_deadline(
&self,
read_timeout: Option<Duration>,
) -> crate::courierust_error::Result<()> {
self.stream.set_deadline(read_timeout)
}
pub fn shutdown(&self, how: Shutdown) -> std::io::Result<()> {
self.stream.shutdown(how)
}
pub fn linger_close(&self, budget: usize, deadline: Duration) {
self.stream.linger_close(budget, deadline);
}
}
impl Read for TunnelConn {
fn read(&mut self, buf: &mut [u8]) -> crate::courierust_error::Result<usize> {
self.reader.read_direct(buf)
}
}
impl Write for TunnelConn {
fn write(&mut self, buf: &[u8]) -> crate::courierust_error::Result<usize> {
let mut writer = &*self.stream;
writer.write(buf)
}
fn flush(&mut self) -> crate::courierust_error::Result<()> {
let mut writer = &*self.stream;
writer.flush()
}
}