Update README and environment configuration; enhance code1 functionality and add assembly code
This commit is contained in:
+53
-7
@@ -3,21 +3,62 @@ use serde_json::Value;
|
||||
use std::net::SocketAddr;
|
||||
|
||||
pub const ID: &str = "code1";
|
||||
const TARGET_DELAY_MS: i64 = 6430;
|
||||
const SELF_NOTIFICATION: &str = "Code 1 has been submitted while the server is live.";
|
||||
const CHALLENGE_1_FIRST: &str = "TODO: secded data";
|
||||
const CHALLENGE_1_SECOND: &str = "SECDED-13\nMSB-LSB";
|
||||
const CHALLENGE_1_FIRST: &str = "SECDED-13\nPARITY MSB...LSB";
|
||||
const CHALLENGE_1_SECOND: &str = "0x144A
|
||||
0x17AE
|
||||
0x17AA
|
||||
0x07A0
|
||||
0x079E
|
||||
0x1751
|
||||
0x02FD
|
||||
0x02FD
|
||||
0x163F
|
||||
0x067A
|
||||
0x062B
|
||||
0x122C
|
||||
0x12FA
|
||||
0x1667
|
||||
0x0606
|
||||
0x179B
|
||||
0x164D
|
||||
0x16F9
|
||||
0x027E
|
||||
0x0629
|
||||
0x1E2C
|
||||
0x07B3
|
||||
0x12FA
|
||||
0x121F
|
||||
0x0676
|
||||
0x1667
|
||||
0x02FC
|
||||
0x0F9E
|
||||
0x07AD
|
||||
0x061C
|
||||
0x1267
|
||||
0x064D
|
||||
0x16AA
|
||||
0x02F5
|
||||
0x0505
|
||||
0x065B
|
||||
0x1329
|
||||
0x1E2C
|
||||
0x1484
|
||||
0x1671";
|
||||
|
||||
pub async fn buzz_event_handler(
|
||||
ConnectInfo(address): ConnectInfo<SocketAddr>,
|
||||
Json(payload): Json<Value>,
|
||||
) -> Result<StatusCode, (StatusCode, String)> {
|
||||
let delta_ms = payload
|
||||
.get("delta_ms")
|
||||
let delay_ms = payload
|
||||
.get("delay_ms")
|
||||
.and_then(Value::as_i64)
|
||||
.filter(|delay_ms| *delay_ms >= 0)
|
||||
.ok_or_else(|| {
|
||||
(
|
||||
StatusCode::BAD_REQUEST,
|
||||
"delta_ms must be a signed 64-bit integer".to_string(),
|
||||
"delay_ms must be a non-negative 64-bit integer".to_string(),
|
||||
)
|
||||
})?;
|
||||
let secret = payload
|
||||
@@ -39,6 +80,7 @@ pub async fn buzz_event_handler(
|
||||
let live = crate::manage::server_live_state();
|
||||
crate::codes::history::record_successful_submission(address.ip(), live, ID)
|
||||
.map_err(|error| (StatusCode::INTERNAL_SERVER_ERROR, error.to_string()))?;
|
||||
let delta_ms = delay_ms - TARGET_DELAY_MS;
|
||||
on_submit(live, delta_ms).await.map_err(|error| {
|
||||
leptos::logging::log!("Code 1 buzz event failed: {error}");
|
||||
(
|
||||
@@ -50,11 +92,15 @@ pub async fn buzz_event_handler(
|
||||
Ok(StatusCode::ACCEPTED)
|
||||
}
|
||||
|
||||
async fn on_submit(live: bool, delta_ms: i64) -> Result<(), String> {
|
||||
async fn on_submit(live: bool, mut delta_ms: i64) -> Result<(), String> {
|
||||
let direction = match delta_ms.cmp(&0) {
|
||||
std::cmp::Ordering::Less => "short",
|
||||
std::cmp::Ordering::Greater => "long",
|
||||
std::cmp::Ordering::Equal => "exactly on time",
|
||||
std::cmp::Ordering::Equal => {
|
||||
// pretend they were off a little bit
|
||||
delta_ms = 52;
|
||||
"long"
|
||||
}
|
||||
};
|
||||
let congrats_message = format!(
|
||||
"Congratulations on completing Challenge 1. It appears that you've figured out what to do, although your buzz was {}ms {}. Consider being more precise in the future. Your sloppiness has been noted.",
|
||||
|
||||
+12
-4
@@ -2,14 +2,22 @@ use leptos::prelude::*;
|
||||
use leptos_router::components::A;
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
use std::sync::{
|
||||
atomic::{AtomicBool, Ordering},
|
||||
OnceLock,
|
||||
};
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
static SERVER_LIVE: AtomicBool = AtomicBool::new(false);
|
||||
static SERVER_LIVE: OnceLock<AtomicBool> = OnceLock::new();
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
fn live_state() -> &'static AtomicBool {
|
||||
SERVER_LIVE.get_or_init(|| AtomicBool::new(crate::secrets::runtime().initial_live))
|
||||
}
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
pub(crate) fn server_live_state() -> bool {
|
||||
SERVER_LIVE.load(Ordering::SeqCst)
|
||||
live_state().load(Ordering::SeqCst)
|
||||
}
|
||||
|
||||
#[server]
|
||||
@@ -23,7 +31,7 @@ async fn set_live_state(live: bool, secret_key: String) -> Result<(), ServerFnEr
|
||||
return Err(ServerFnError::ServerError("Invalid secret key".to_string()));
|
||||
}
|
||||
|
||||
SERVER_LIVE.store(live, Ordering::SeqCst);
|
||||
live_state().store(live, Ordering::SeqCst);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@ pub(crate) const RECIPIENT_SELF: &str = "RECIPIENT_SELF";
|
||||
pub(crate) const RECIPIENT_1: &str = "RECIPIENT_1";
|
||||
pub(crate) const RECIPIENT_2: &str = "RECIPIENT_2";
|
||||
pub(crate) const CODE1_SECRET: &str = "CODE1_SECRET";
|
||||
pub(crate) const PROD: &str = "PROD";
|
||||
|
||||
static RUNTIME_SECRETS: OnceLock<RuntimeSecrets> = OnceLock::new();
|
||||
|
||||
@@ -18,6 +19,7 @@ pub(crate) struct RuntimeSecrets {
|
||||
pub(crate) recipient_1: String,
|
||||
pub(crate) recipient_2: String,
|
||||
pub(crate) code1_secret: String,
|
||||
pub(crate) initial_live: bool,
|
||||
}
|
||||
|
||||
pub fn init() -> Result<(), String> {
|
||||
@@ -54,6 +56,9 @@ impl RuntimeSecrets {
|
||||
let recipient_1 = required_recipient(RECIPIENT_1)?;
|
||||
let recipient_2 = required_recipient(RECIPIENT_2)?;
|
||||
let code1_secret = required(CODE1_SECRET)?;
|
||||
let initial_live = env::var(PROD)
|
||||
.map(|value| is_truthy(&value))
|
||||
.unwrap_or(false);
|
||||
|
||||
if code1_secret.len() < 32 {
|
||||
return Err(format!("{CODE1_SECRET} must contain at least 32 bytes"));
|
||||
@@ -71,6 +76,7 @@ impl RuntimeSecrets {
|
||||
recipient_1,
|
||||
recipient_2,
|
||||
code1_secret,
|
||||
initial_live,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -98,3 +104,10 @@ fn is_e164_number(number: &str) -> bool {
|
||||
&& !digits.starts_with('0')
|
||||
&& digits.bytes().all(|byte| byte.is_ascii_digit())
|
||||
}
|
||||
|
||||
fn is_truthy(value: &str) -> bool {
|
||||
matches!(
|
||||
value.trim().to_ascii_lowercase().as_str(),
|
||||
"1" | "true" | "yes" | "on"
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user