We have a server at least #3

Merged
PlexSheep merged 14 commits from devel into master 2024-01-19 16:40:16 +01:00
7 changed files with 105 additions and 18 deletions
Showing only changes of commit 78340a23d2 - Show all commits

View File

@ -18,9 +18,9 @@ clap = "4.4.18"
clap-num = "1.0.2"
clap-verbosity-flag = "2.1.2"
libpt = { version = "0.3.10", features = ["net"] }
threadpool = "1.8.1"
mio = { version = "0.8.10", features = ["net", "os-poll"] }
threadpool = { version = "1.8.1", optional = true }
[features]
default = ["server", "client"]
client = []
server = []
default = ["server"]
server = ["dep:threadpool"]

View File

@ -41,10 +41,17 @@ pub(crate) struct Cli {
#[arg(long)]
pub(crate) meta: bool,
// host a server instead of connecting to one
#[cfg(feature = "server")]
#[arg(short, long, default_value_t = false)]
pub(crate) server: bool,
// how much threads the server should use
#[cfg(feature = "server")]
#[arg(short, long, default_value_t = 4)]
pub(crate) threads: usize,
#[arg(short, long, default_value_t = Mode::Tcp, ignore_case = true)]
pub(crate) mode: Mode,

View File

@ -1,6 +1,6 @@
use std::fmt::Display;
use clap::ValueEnum;
use crate::common::args::Cli;
use clap::ValueEnum;
use std::fmt::Display;
#[derive(Debug, Clone, Copy)]
pub enum Mode {
Tcp,
@ -37,13 +37,18 @@ impl Display for Mode {
}
}
pub(crate) struct Config {
cli: Cli,
addr: std::net::SocketAddr,
pub struct Config {
pub addr: std::net::SocketAddr,
pub mode: Mode,
pub threads: usize
}
impl Config {
pub fn new(cli: Cli, addr: std::net::SocketAddr) -> Self {
Config { cli, addr }
pub fn new(cli: &Cli) -> Self {
Config {
addr: cli.addr.clone(),
mode: cli.mode.clone(),
threads: cli.threads
}
}
}

View File

@ -1,6 +1,2 @@
pub mod args;
use args::*;
pub mod conf;
use conf::*;

View File

@ -3,6 +3,7 @@
//! over a connection, while letting a server reply pong to
//! every connection. But I had to make it for some reason.
use anyhow::Result;
use libpt::log::*;
mod client;
@ -11,15 +12,21 @@ mod server;
use common::{args::Cli, conf::*};
fn main() {
use crate::server::Server;
fn main() -> Result<()> {
let cli = Cli::cli_parse();
debug!("dumping cli args:\n{:#?}", cli);
let cfg = Config::new(&cli);
#[cfg(feature = "server")]
if cli.server {
info!("starting server");
return;
Server::build(cfg)?.run()?;
return Ok(());
}
// implicit else, so we can work without the server feature
info!("starting client");
Ok(())
}

6
src/server/listener.rs Normal file
View File

@ -0,0 +1,6 @@
use std::net::TcpListener;
pub trait Listener {}
pub trait Stream {}
impl Listener for TcpListener {}

View File

@ -0,0 +1,66 @@
#![cfg(feature = "server")]
use anyhow::Result;
use libpt::log::{error, info};
use mio::{self, event::Event, net::TcpListener, Events, Interest, Poll, Token};
use std::{
io::{prelude::*, BufReader},
time::Duration,
};
use threadpool::ThreadPool;
use crate::common::conf::{Config, Mode};
pub mod listener;
use listener::*;
const EVENT_CAPACITY: usize = 128;
const SERVER: Token = Token(0);
pub struct Server {
cfg: Config,
work: Poll,
events: Events,
pool: ThreadPool,
pub timeout: Option<Duration>,
server: TcpListener,
}
impl Server {
pub fn build(cfg: Config) -> Result<Self> {
let mut server = TcpListener::bind(cfg.addr)?;
let poll: Poll = Poll::new()?;
poll.registry()
.register(&mut server, SERVER, Interest::READABLE | Interest::WRITABLE);
let events: Events = Events::with_capacity(EVENT_CAPACITY);
let pool = ThreadPool::new(cfg.threads);
let timeout = Some(Duration::from_secs(5));
Ok(Server {
cfg,
work: poll,
events,
pool,
timeout,
server,
})
}
pub fn run(&mut self) -> Result<()> {
loop {
self.work.poll(&mut self.events, self.timeout)?;
for event in self.events.iter() {
// self.pool.execute(|| {
let result = self.handle_event(event);
if let Err(err) = result {
error!("Error while handling server event {:?}: {:?}", event, err);
}
// });
}
}
}
fn handle_event(&self, event: &Event) -> Result<()> {
dbg!(event);
let connection = self.server.accept()?;
info!("received a connection!");
Ok(())
}
}