Skip to content

Commit

Permalink
Added support for dual-stack socket #3
Browse files Browse the repository at this point in the history
  • Loading branch information
SudoDios committed Sep 9, 2024
1 parent 21d8e0d commit 809c7d2
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ tokio = {version = "1.40.0", features = ["net","io-util","rt","macros","rt-multi
tokio-rustls = {version = "0.26.0", features = ["logging","tls12","ring"], default-features = false}
webpki-roots = "0.26.5"
rustls-pemfile = "2.1.3"
socket2 = "0.5.7"
#ip
maxminddb = "0.24.0"
#image processing
Expand Down
13 changes: 6 additions & 7 deletions src/http/http_server.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use std::sync::Arc;
use log::{info, trace};
use tokio::io::{AsyncReadExt, AsyncWriteExt, BufReader, BufWriter, split};
use tokio::net::TcpListener;
use tokio::sync::Mutex;
use tokio_rustls::TlsAcceptor;
use crate::config::{ROUTES, SERVER_CONFIG};
Expand All @@ -11,37 +10,37 @@ use crate::http::request::handle_socket;
use crate::http::response::Response;

use crate::http::routes::*;
use crate::http::tcp_socket::TcpSocket;
use crate::http::tls::setup_tls_acceptor;
use crate::ip::ip_info::IPInfo;
use crate::results::stats::handle_stat_page;

pub struct HttpServer {
pub tcp_listener: TcpListener,
pub tcp_socket: TcpSocket,
pub tls_acceptor: Option<TlsAcceptor>
}

impl HttpServer {

pub async fn init () -> std::io::Result<Self> {
let config = SERVER_CONFIG.get().unwrap();
let addr = format!("{}:{}",config.bind_address,config.listen_port);
let listener = TcpListener::bind(addr.clone()).await?;
info!("Server started on {}",addr);
let tcp_socket = TcpSocket::bind(config)?;
info!("Server started on {}",tcp_socket.to_string());
info!("Server base url : {}/",config.base_url);
let mut tls_acceptor = None;
if config.enable_tls {
tls_acceptor = Some(setup_tls_acceptor(&config.tls_cet_file,&config.tls_key_file)?);
}
Ok(HttpServer {
tcp_listener : listener,
tcp_socket,
tls_acceptor
})
}

pub async fn listen (&mut self, database : &mut Arc<Mutex<dyn Database + Send>>) {
loop {

let tcp_accept = self.tcp_listener.accept().await;
let tcp_accept = self.tcp_socket.accept().await;
let mut database = database.clone();
let tls_acceptor = self.tls_acceptor.clone();

Expand Down
1 change: 1 addition & 0 deletions src/http/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub mod response;
pub mod cookie;
pub mod tls;
pub mod http_client;
mod tcp_socket;

#[derive(Debug)]
pub enum Method {
Expand Down
72 changes: 72 additions & 0 deletions src/http/tcp_socket.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
use core::fmt;
use std::fmt::Formatter;
use std::io;
use std::io::{Error, ErrorKind};
use std::net::{IpAddr, SocketAddr};
use std::str::FromStr;
use socket2::{Domain, Type};
use tokio::net::{TcpListener, TcpStream};
use crate::config::ServerConfig;

pub struct TcpSocket {
tcp_listener: TcpListener,
addr : TcpAddr
}

impl TcpSocket {
pub fn bind(config: &ServerConfig) -> io::Result<TcpSocket> {
let tcp_addr = TcpAddr::new(config)?;
let socket = socket2::Socket::new(tcp_addr.domain,Type::STREAM,None)?;
if !tcp_addr.is_only_v6 {
socket.set_only_v6(false)?;
}
socket.bind(&tcp_addr.sock_addr.into())?;
socket.listen(128)?;
let tcp_listener = TcpListener::from_std(socket.into())?;
Ok(TcpSocket {
tcp_listener,
addr : tcp_addr
})
}

pub async fn accept (&self) -> io::Result<(TcpStream, SocketAddr)> {
self.tcp_listener.accept().await
}

}

impl fmt::Display for TcpSocket {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
write!(f,"{}",self.addr.sock_addr)
}
}

#[derive(Debug)]
pub struct TcpAddr {
sock_addr: SocketAddr,
domain: Domain,
is_only_v6: bool,
}

impl TcpAddr {
pub fn new(config: &ServerConfig) -> io::Result<Self> {
let bind_addr = config.bind_address.as_str();
let parse_addr = Self::parse_addr(bind_addr)?;
let addr = SocketAddr::new(parse_addr.0, config.listen_port);
Ok(TcpAddr {
sock_addr: addr,
domain: parse_addr.1,
is_only_v6: bind_addr != "::" && bind_addr != "::0",
})
}

fn parse_addr(ip_str: &str) -> io::Result<(IpAddr, Domain)> {
match IpAddr::from_str(ip_str) {
Ok(ip) => match ip {
IpAddr::V4(_) => Ok((ip, Domain::IPV4)),
IpAddr::V6(_) => Ok((ip, Domain::IPV6)),
},
Err(e) => Err(Error::new(ErrorKind::Other, e)),
}
}
}

0 comments on commit 809c7d2

Please sign in to comment.