From 0db78399bd7c494bc36392a69e2757f271fb91b3 Mon Sep 17 00:00:00 2001 From: PlexSheep Date: Sun, 8 Sep 2024 14:19:36 +0200 Subject: [PATCH] refactor: change how ChallengeDesc works --- src/challenge/c1.rs | 19 ++++++++++--------- src/challenge/c2.rs | 21 ++++++++++----------- src/challenge/c3.rs | 25 +++++++++++++------------ src/challenge/mod.rs | 42 ++++++++++++++++++++++++++++++++++++------ src/lib.rs | 23 +++++++++-------------- 5 files changed, 78 insertions(+), 52 deletions(-) diff --git a/src/challenge/c1.rs b/src/challenge/c1.rs index 27ab331..e5501f9 100644 --- a/src/challenge/c1.rs +++ b/src/challenge/c1.rs @@ -34,17 +34,18 @@ impl ChallengeLike for C1 { Self { config, vault } } - fn text() -> ChallengeDesc { - ChallengeDesc { - id: 1, - title: "dumb TCP".to_string(), - hints: vec![String::from("TCP connect to 1337.")], - solution: String::from("Connect by TCP, then the secret will be sent to you."), - description: String::from("Do you know how to TCP?"), - } + fn text(&self) -> ChallengeDesc { + ChallengeDesc::new( + 1, + "dumb TCP", + &["TCP connect to 1337."], + "Connect by TCP, then the secret will be sent to you.", + "Do you know how to TCP?", + &self.config.addr, + ) } - async fn serve(&self, addr: SocketAddr) -> anyhow::Result<()> { + async fn serve(&self, addr: &SocketAddr) -> anyhow::Result<()> { let listener = TcpListener::bind(addr).await?; loop { diff --git a/src/challenge/c2.rs b/src/challenge/c2.rs index 02d4214..9112305 100644 --- a/src/challenge/c2.rs +++ b/src/challenge/c2.rs @@ -59,19 +59,18 @@ impl ChallengeLike for C2 { fn new(config: Config, vault: VaultRef) -> Self { Self { config, vault } } - fn text() -> ChallengeDesc { - ChallengeDesc { - id: 2, - title: "TCP dialogue".to_string(), - hints: vec![String::from( - "TCP connect to 1337 and give me a special u16", - )], - solution: String::from("Connect by TCP, send 1337 as bytes (not text)."), - description: String::from("Do you know how to TCP, but slightly cooler than for C1?"), - } + fn text(&self) -> ChallengeDesc { + ChallengeDesc::new( + 2, + "TCP dialogue", + &["TCP connect to 1337 and give me a special u16"], + "Connect by TCP, send 1337 as bytes (not text).", + "Do you know how to TCP, but slightly cooler than for C1?", + &self.config.addr, + ) } - async fn serve(&self, addr: SocketAddr) -> anyhow::Result<()> { + async fn serve(&self, addr: &SocketAddr) -> anyhow::Result<()> { let listener = TcpListener::bind(addr).await?; loop { diff --git a/src/challenge/c3.rs b/src/challenge/c3.rs index 45d85e6..ef8f794 100644 --- a/src/challenge/c3.rs +++ b/src/challenge/c3.rs @@ -217,21 +217,22 @@ impl ChallengeLike for C3 { fn new(config: Config, vault: VaultRef) -> Self { Self { config, vault } } - fn text() -> ChallengeDesc { - ChallengeDesc { - id: 3, - title: "TCP math exam".to_string(), - hints: vec![ - "TCP connect to 1337 and answer the questions.".to_string(), - "The questions keep chaning.".to_string(), - "You should try to solve the questions in an automated way.".to_string(), + fn text(&self) -> ChallengeDesc { + ChallengeDesc::new( + 3, + "TCP math exam", + &[ + "TCP connect to 1337 and answer the questions.", + "The questions keep chaning.", + "You should try to solve the questions in an automated way.", ], - solution: String::from("Connect by TCP, programmatically answer the questions."), - description: String::from("How fast can you do arithmetics?"), - } + "Connect by TCP, programmatically answer the questions.", + "How fast can you do arithmetics?", + &self.config.addr, + ) } - async fn serve(&self, addr: SocketAddr) -> anyhow::Result<()> { + async fn serve(&self, addr: &SocketAddr) -> anyhow::Result<()> { let listener = TcpListener::bind(addr).await?; loop { diff --git a/src/challenge/mod.rs b/src/challenge/mod.rs index ee79b9f..d0b76a5 100644 --- a/src/challenge/mod.rs +++ b/src/challenge/mod.rs @@ -23,9 +23,37 @@ pub struct ChallengeDesc { hints: Vec, solution: String, description: String, + addr: SocketAddr, } impl ChallengeDesc { + pub fn new( + id: usize, + title: &str, + hints: &[&str], + solution: &str, + description: &str, + base_addr: &SocketAddr, + ) -> Self { + Self { + id, + title: title.to_string(), + hints: hints.iter().map(|a| a.to_string()).collect(), + solution: solution.to_string(), + description: description.to_string(), + addr: SocketAddr::new(base_addr.ip(), base_addr.port() + id as u16), + } + } + /// Returns a [`SocketAddr`] for the challenge. + /// + /// The challenge will be hosted on this [`SocketAddr`]. + /// + /// # Returns + /// + /// The [`SocketAddr`] that the challenge is hosted on. + pub fn addr(&self) -> &SocketAddr { + &self.addr + } /// Returns a list of hints for the challenge. /// /// A hint is a short text to be given to the contestants in case the admin thinks they need @@ -98,7 +126,7 @@ where /// Getter for the [Config]. fn config(&self) -> Config; /// Get the various texts for this challenge. - fn text() -> ChallengeDesc; + fn text(&self) -> ChallengeDesc; /// Creates a new instance of the challenge with the given configuration and vault. /// /// # Arguments @@ -122,7 +150,7 @@ where /// # Errors /// /// Will error when the challenge errors, for example when the network adress cannot be bound. - async fn serve(&self, addr: SocketAddr) -> anyhow::Result<()>; + async fn serve(&self, addr: &SocketAddr) -> anyhow::Result<()>; /// Serves a challenge and sets up the hint and monitoring service for the admin. /// /// This method not only serves the challenge, but it also sets up a small webservice for the @@ -137,12 +165,14 @@ where /// # Returns /// /// A result indicating whether the challenge and the admin interface were successfully served. - async fn start(&self, addr: SocketAddr) -> anyhow::Result<()> { + async fn start(&self, addr: &SocketAddr) -> anyhow::Result<()> { let c = self.clone(); + let data = self.text(); + let addr = addr.to_owned(); tokio::spawn(async move { - info!("starting C{}", Self::text().id()); - if let Err(e) = c.serve(addr).await { - error!("challenge {} has crashed! {e:#?}", Self::text().title()); + info!("starting C{}", data.id()); + if let Err(e) = c.serve(&addr).await { + error!("challenge {} has crashed! {e:#?}", data.title()); }; }); Ok(()) diff --git a/src/lib.rs b/src/lib.rs index e43eaa7..0529a6d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -14,8 +14,6 @@ //! Wooly Vault is programmed asynchronously with [tokio] to be able to handle many contestants at //! once if needed. -use std::net::SocketAddr; - use anyhow::anyhow; use libpt::log::info; @@ -64,17 +62,17 @@ pub async fn select_and_start_single( match index { 1 => { challenge::c1::C1::new(config.clone(), vault) - .start(config.addr) + .start(&config.addr) .await? } 2 => { challenge::c2::C2::new(config.clone(), vault) - .start(config.addr) + .start(&config.addr) .await? } 3 => { challenge::c3::C3::new(config.clone(), vault) - .start(config.addr) + .start(&config.addr) .await? } _ => { @@ -88,22 +86,19 @@ pub async fn select_and_start_single( // TODO: actually use different vaults for the challenges #7 pub async fn start_all(config: Config, vault: VaultRef) -> anyhow::Result<()> { - let ip = config.addr.ip(); - let start_port = config.addr.port(); - let c1 = challenge::c1::C1::new(config.clone(), vault.clone()); let c2 = challenge::c2::C2::new(config.clone(), vault.clone()); let c3 = challenge::c3::C3::new(config.clone(), vault.clone()); - c1.start(SocketAddr::new(ip, start_port)).await?; - c2.start(SocketAddr::new(ip, start_port + 1)).await?; - c3.start(SocketAddr::new(ip, start_port + 2)).await?; + c1.start(c1.text().addr()).await?; + c2.start(c2.text().addr()).await?; + c3.start(c3.text().addr()).await?; meta::serve( vec![ - (challenge::c1::C1::text(), vault.clone()), - (challenge::c2::C2::text(), vault.clone()), - (challenge::c3::C3::text(), vault.clone()), + (c1.text(), vault.clone()), + (c2.text(), vault.clone()), + (c3.text(), vault.clone()), ], config.clone(), )