clean + minify
This commit is contained in:
parent
23d03920ae
commit
fc6423ad44
86
Cargo.lock
generated
86
Cargo.lock
generated
@ -290,48 +290,6 @@ version = "0.3.13"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e"
|
checksum = "f578e8e2c440e7297e008bb5486a3a8a194775224bbc23729b0dbdfaeebf162e"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "defmt"
|
|
||||||
version = "0.3.10"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "86f6162c53f659f65d00619fe31f14556a6e9f8752ccc4a41bd177ffcf3d6130"
|
|
||||||
dependencies = [
|
|
||||||
"bitflags 1.3.2",
|
|
||||||
"defmt-macros",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "defmt-macros"
|
|
||||||
version = "0.4.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "9d135dd939bad62d7490b0002602d35b358dce5fd9233a709d3c1ef467d4bde6"
|
|
||||||
dependencies = [
|
|
||||||
"defmt-parser",
|
|
||||||
"proc-macro-error2",
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.100",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "defmt-parser"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "3983b127f13995e68c1e29071e5d115cd96f215ccb5e6812e3728cd6f92653b3"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "defmt-rtt"
|
|
||||||
version = "0.4.1"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "bab697b3dbbc1750b7c8b821aa6f6e7f2480b47a99bc057a2ed7b170ebef0c51"
|
|
||||||
dependencies = [
|
|
||||||
"critical-section",
|
|
||||||
"defmt",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "dhcparse"
|
name = "dhcparse"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
@ -399,7 +357,6 @@ source = "git+https://github.com/embassy-rs/embassy#cae954a87ec3c5ece520b6a44168
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"defmt",
|
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-executor-macros",
|
"embassy-executor-macros",
|
||||||
]
|
]
|
||||||
@ -427,7 +384,6 @@ source = "git+https://github.com/embassy-rs/embassy#cae954a87ec3c5ece520b6a44168
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"cortex-m",
|
"cortex-m",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"defmt",
|
|
||||||
"num-traits",
|
"num-traits",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -436,7 +392,6 @@ name = "embassy-net"
|
|||||||
version = "0.7.0"
|
version = "0.7.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy#cae954a87ec3c5ece520b6a44168b36e79f3f86a"
|
source = "git+https://github.com/embassy-rs/embassy#cae954a87ec3c5ece520b6a44168b36e79f3f86a"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt",
|
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-net-driver",
|
"embassy-net-driver",
|
||||||
"embassy-sync",
|
"embassy-sync",
|
||||||
@ -452,9 +407,6 @@ dependencies = [
|
|||||||
name = "embassy-net-driver"
|
name = "embassy-net-driver"
|
||||||
version = "0.2.0"
|
version = "0.2.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy#cae954a87ec3c5ece520b6a44168b36e79f3f86a"
|
source = "git+https://github.com/embassy-rs/embassy#cae954a87ec3c5ece520b6a44168b36e79f3f86a"
|
||||||
dependencies = [
|
|
||||||
"defmt",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-net-driver-channel"
|
name = "embassy-net-driver-channel"
|
||||||
@ -476,7 +428,6 @@ dependencies = [
|
|||||||
"cortex-m",
|
"cortex-m",
|
||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
"critical-section",
|
"critical-section",
|
||||||
"defmt",
|
|
||||||
"document-features",
|
"document-features",
|
||||||
"embassy-embedded-hal",
|
"embassy-embedded-hal",
|
||||||
"embassy-futures",
|
"embassy-futures",
|
||||||
@ -567,9 +518,6 @@ dependencies = [
|
|||||||
name = "embassy-usb-driver"
|
name = "embassy-usb-driver"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/embassy-rs/embassy#cae954a87ec3c5ece520b6a44168b36e79f3f86a"
|
source = "git+https://github.com/embassy-rs/embassy#cae954a87ec3c5ece520b6a44168b36e79f3f86a"
|
||||||
dependencies = [
|
|
||||||
"defmt",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "embassy-usb-logger"
|
name = "embassy-usb-logger"
|
||||||
@ -834,7 +782,6 @@ version = "0.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
checksum = "0bfb9eb618601c89945a70e254898da93b13be0388091d42117462b265bb3fad"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"defmt",
|
|
||||||
"hash32",
|
"hash32",
|
||||||
"serde",
|
"serde",
|
||||||
"stable_deref_trait",
|
"stable_deref_trait",
|
||||||
@ -1031,15 +978,6 @@ version = "1.21.1"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
|
checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc"
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "panic-probe"
|
|
||||||
version = "0.3.2"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "4047d9235d1423d66cc97da7d07eddb54d4f154d6c13805c6d0793956f4f25b0"
|
|
||||||
dependencies = [
|
|
||||||
"cortex-m",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "parking_lot"
|
name = "parking_lot"
|
||||||
version = "0.12.3"
|
version = "0.12.3"
|
||||||
@ -1109,8 +1047,6 @@ dependencies = [
|
|||||||
"cortex-m-rt",
|
"cortex-m-rt",
|
||||||
"cyw43",
|
"cyw43",
|
||||||
"cyw43-pio",
|
"cyw43-pio",
|
||||||
"defmt",
|
|
||||||
"defmt-rtt",
|
|
||||||
"dhcparse",
|
"dhcparse",
|
||||||
"dnsparse",
|
"dnsparse",
|
||||||
"embassy-executor",
|
"embassy-executor",
|
||||||
@ -1122,7 +1058,6 @@ dependencies = [
|
|||||||
"embedded-io-async",
|
"embedded-io-async",
|
||||||
"heapless",
|
"heapless",
|
||||||
"log",
|
"log",
|
||||||
"panic-probe",
|
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
"rand_core",
|
"rand_core",
|
||||||
@ -1494,7 +1429,6 @@ dependencies = [
|
|||||||
"bitflags 1.3.2",
|
"bitflags 1.3.2",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
"defmt",
|
|
||||||
"heapless",
|
"heapless",
|
||||||
"managed",
|
"managed",
|
||||||
]
|
]
|
||||||
@ -1583,26 +1517,6 @@ dependencies = [
|
|||||||
"winapi-util",
|
"winapi-util",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror"
|
|
||||||
version = "2.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "567b8a2dae586314f7be2a752ec7474332959c6460e02bde30d702a66d488708"
|
|
||||||
dependencies = [
|
|
||||||
"thiserror-impl",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "thiserror-impl"
|
|
||||||
version = "2.0.12"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "7f7cf42b4507d8ea322120659672cf1b9dbb93f8f2d4ecfd6e51350ff5b17a1d"
|
|
||||||
dependencies = [
|
|
||||||
"proc-macro2",
|
|
||||||
"quote",
|
|
||||||
"syn 2.0.100",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "typenum"
|
name = "typenum"
|
||||||
version = "1.18.0"
|
version = "1.18.0"
|
||||||
|
@ -16,14 +16,12 @@ default = ["dhcp", "dns", "ttt"]
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
embassy-executor = { git = "https://github.com/embassy-rs/embassy", features = [
|
embassy-executor = { git = "https://github.com/embassy-rs/embassy", features = [
|
||||||
"defmt",
|
|
||||||
"nightly",
|
"nightly",
|
||||||
"arch-cortex-m",
|
"arch-cortex-m",
|
||||||
"executor-thread",
|
"executor-thread",
|
||||||
"executor-interrupt",
|
"executor-interrupt",
|
||||||
] }
|
] }
|
||||||
embassy-rp = { git = "https://github.com/embassy-rs/embassy", features = [
|
embassy-rp = { git = "https://github.com/embassy-rs/embassy", features = [
|
||||||
"defmt",
|
|
||||||
"unstable-pac",
|
"unstable-pac",
|
||||||
"rp2040",
|
"rp2040",
|
||||||
"time-driver",
|
"time-driver",
|
||||||
@ -32,7 +30,6 @@ embassy-rp = { git = "https://github.com/embassy-rs/embassy", features = [
|
|||||||
embassy-time = { git = "https://github.com/embassy-rs/embassy" }
|
embassy-time = { git = "https://github.com/embassy-rs/embassy" }
|
||||||
embassy-usb-logger = { git = "https://github.com/embassy-rs/embassy" }
|
embassy-usb-logger = { git = "https://github.com/embassy-rs/embassy" }
|
||||||
embassy-net = { git = "https://github.com/embassy-rs/embassy", features = [
|
embassy-net = { git = "https://github.com/embassy-rs/embassy", features = [
|
||||||
"defmt",
|
|
||||||
"proto-ipv4",
|
"proto-ipv4",
|
||||||
"tcp",
|
"tcp",
|
||||||
"udp",
|
"udp",
|
||||||
@ -43,9 +40,6 @@ cyw43-pio = { git = "https://github.com/embassy-rs/embassy" }
|
|||||||
cyw43 = { git = "https://github.com/embassy-rs/embassy" }
|
cyw43 = { git = "https://github.com/embassy-rs/embassy" }
|
||||||
|
|
||||||
embedded-io-async = "*"
|
embedded-io-async = "*"
|
||||||
defmt = "*"
|
|
||||||
defmt-rtt = "*"
|
|
||||||
panic-probe = "*"
|
|
||||||
cortex-m = { version = "*", features = ["inline-asm"] }
|
cortex-m = { version = "*", features = ["inline-asm"] }
|
||||||
cortex-m-rt = "*"
|
cortex-m-rt = "*"
|
||||||
static_cell = "*"
|
static_cell = "*"
|
||||||
|
2
build.rs
2
build.rs
@ -32,5 +32,5 @@ fn main() {
|
|||||||
println!("cargo:rustc-link-arg-bins=--nmagic");
|
println!("cargo:rustc-link-arg-bins=--nmagic");
|
||||||
println!("cargo:rustc-link-arg-bins=-Tlink.x");
|
println!("cargo:rustc-link-arg-bins=-Tlink.x");
|
||||||
println!("cargo:rustc-link-arg-bins=-Tlink-rp.x");
|
println!("cargo:rustc-link-arg-bins=-Tlink-rp.x");
|
||||||
println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
|
// println!("cargo:rustc-link-arg-bins=-Tdefmt.x");
|
||||||
}
|
}
|
||||||
|
@ -1,15 +1,10 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<head>
|
|
||||||
<script>
|
|
||||||
var ws = new WebSocket("/chat");
|
|
||||||
</script>
|
|
||||||
</head>
|
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
<h1>Apps</h1>
|
<h1>Apps</h1>
|
||||||
<ul>
|
<ul>
|
||||||
<li><a href="http://pico.wifi:8080">Tic Tac Toe</a> (team blue)</li>
|
<li><a href="/ttt?team=0">Tic Tac Toe</a> (team blue)</li>
|
||||||
<li><a href="http://pico.wifi:8081">Tic Tac Toe</a> (team red)</li>
|
<li><a href="/ttt?team=1">Tic Tac Toe</a> (team red)</li>
|
||||||
</ul>
|
</ul>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
@ -23,7 +23,18 @@ impl App for IndexApp {
|
|||||||
"/" | "/index" | "/index.html" => (
|
"/" | "/index" | "/index.html" => (
|
||||||
HttpResCode::Ok,
|
HttpResCode::Ok,
|
||||||
"html",
|
"html",
|
||||||
Some(include_str!("./index.html").into()),
|
#[cfg(debug_assertions)]
|
||||||
|
Some(include_str!("index.html").into()),
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
Some(include_str!("../../static/index.min.html").into()),
|
||||||
|
),
|
||||||
|
"/htmx.js" => (
|
||||||
|
HttpResCode::Ok,
|
||||||
|
"javascript",
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
|
Some(include_str!("../../static/htmx.js").into()),
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
Some(include_str!("../../static/htmx.min.js").into()),
|
||||||
),
|
),
|
||||||
path => {
|
path => {
|
||||||
let (path, args) = path.split_once('?').unwrap_or((path, ""));
|
let (path, args) = path.split_once('?').unwrap_or((path, ""));
|
||||||
@ -39,7 +50,11 @@ impl App for IndexApp {
|
|||||||
let Some(team) = team else {
|
let Some(team) = team else {
|
||||||
return (HttpResCode::BadRequest, "", None);
|
return (HttpResCode::BadRequest, "", None);
|
||||||
};
|
};
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
let html = include_str!("ttt.html");
|
let html = include_str!("ttt.html");
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
let html = include_str!("../../static/ttt.min.html");
|
||||||
|
|
||||||
let mut content = Vec::new();
|
let mut content = Vec::new();
|
||||||
let r: Result<(), &str> = try {
|
let r: Result<(), &str> = try {
|
||||||
let (html1, html2) = html.split_once("/ttt.js").ok_or("")?;
|
let (html1, html2) = html.split_once("/ttt.js").ok_or("")?;
|
||||||
@ -60,8 +75,11 @@ impl App for IndexApp {
|
|||||||
let r: Result<(), &str> = try {
|
let r: Result<(), &str> = try {
|
||||||
content.push("const team = ")?;
|
content.push("const team = ")?;
|
||||||
content.push(team)?;
|
content.push(team)?;
|
||||||
content.push(";\n")?;
|
content.push(";")?;
|
||||||
|
#[cfg(debug_assertions)]
|
||||||
content.push(include_str!("ttt.js"))?;
|
content.push(include_str!("ttt.js"))?;
|
||||||
|
#[cfg(not(debug_assertions))]
|
||||||
|
content.push(include_str!("../../static/ttt.min.js"))?;
|
||||||
};
|
};
|
||||||
unwrap(r).await;
|
unwrap(r).await;
|
||||||
(HttpResCode::Ok, "javascript", Some(Content(content)))
|
(HttpResCode::Ok, "javascript", Some(Content(content)))
|
||||||
|
@ -31,12 +31,6 @@ pub trait App {
|
|||||||
|
|
||||||
pub struct Content<'a>(pub Vec<&'a str, 8>);
|
pub struct Content<'a>(pub Vec<&'a str, 8>);
|
||||||
|
|
||||||
// pub enum Content<'a> {
|
|
||||||
// Str(&'a str),
|
|
||||||
// /// Return the number of bytes written
|
|
||||||
// /// (fn that writes content, length)
|
|
||||||
// Fn(fn(&mut [u8]) -> usize, usize),
|
|
||||||
// }
|
|
||||||
impl<'a> From<&'a str> for Content<'a> {
|
impl<'a> From<&'a str> for Content<'a> {
|
||||||
fn from(value: &'a str) -> Self {
|
fn from(value: &'a str) -> Self {
|
||||||
let mut v = Vec::new();
|
let mut v = Vec::new();
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<head>
|
<head>
|
||||||
<!-- <script src="./htmx.js"></script> -->
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
body {
|
body {
|
||||||
#grid {
|
#grid {
|
||||||
|
@ -27,7 +27,6 @@ const ws = new WebSocket(
|
|||||||
);
|
);
|
||||||
|
|
||||||
ws.onmessage = (event) => {
|
ws.onmessage = (event) => {
|
||||||
console.log(event.data);
|
|
||||||
if (typeof event.data == "string") {
|
if (typeof event.data == "string") {
|
||||||
let msg = JSON.parse(event.data);
|
let msg = JSON.parse(event.data);
|
||||||
let cells = [];
|
let cells = [];
|
||||||
@ -46,18 +45,12 @@ ws.onmessage = (event) => {
|
|||||||
|
|
||||||
if (tagName === "button") {
|
if (tagName === "button") {
|
||||||
cell.addEventListener("click", (event) => {
|
cell.addEventListener("click", (event) => {
|
||||||
console.log(i);
|
|
||||||
ws.send(new Uint8Array([i]));
|
ws.send(new Uint8Array([i]));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
cell.setAttribute("team", owner);
|
cell.setAttribute("team", owner);
|
||||||
|
|
||||||
// if (msg.board & (1 << i != 0) || msg.board & (1 << (i + 9))) {
|
|
||||||
// if (msg.board & (1 << (i + 9) != 0)) {
|
|
||||||
// col = "firebrick";
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
cells.push(cell);
|
cells.push(cell);
|
||||||
}
|
}
|
||||||
document.getElementById("grid").replaceChildren(...cells);
|
document.getElementById("grid").replaceChildren(...cells);
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
|
use core::ops::Not;
|
||||||
use core::str::from_utf8_unchecked;
|
use core::str::from_utf8_unchecked;
|
||||||
use core::{ops::Not, sync::atomic::Ordering};
|
|
||||||
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
use embassy_sync::blocking_mutex::raw::ThreadModeRawMutex;
|
||||||
use embassy_sync::mutex::Mutex;
|
use embassy_sync::mutex::Mutex;
|
||||||
use embassy_time::{Duration, Instant, Timer};
|
use embassy_time::{Duration, Instant, Timer};
|
||||||
use heapless::{String, Vec};
|
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
use pico_website::{unwrap, unwrap_opt};
|
use pico_website::{unwrap, unwrap_opt};
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
@ -60,8 +59,6 @@ impl Game {
|
|||||||
|
|
||||||
static GAME: Mutex<ThreadModeRawMutex, Game> = Mutex::new(Game::default());
|
static GAME: Mutex<ThreadModeRawMutex, Game> = Mutex::new(Game::default());
|
||||||
|
|
||||||
// {"board"=[null,null,null,null,null,null,null,null,null],"turn"=null,"winner":null}
|
|
||||||
|
|
||||||
pub struct TttApp {
|
pub struct TttApp {
|
||||||
team: Team,
|
team: Team,
|
||||||
last_game: Game,
|
last_game: Game,
|
||||||
@ -82,67 +79,17 @@ impl TttApp {
|
|||||||
json_buf: [0; 128],
|
json_buf: [0; 128],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// pub fn is_ended(&self, board: u32) -> (bool, Option<Team>) {
|
|
||||||
// if let Some((_, t)) = self.end {
|
|
||||||
// return (true, t);
|
|
||||||
// }
|
|
||||||
// for (t, m) in [(Team::Zero, 0), (Team::One, 9)] {
|
|
||||||
// for w in [
|
|
||||||
// 0b111000000,
|
|
||||||
// 0b000111000,
|
|
||||||
// 0b000000111,
|
|
||||||
// 0b100100100,
|
|
||||||
// 0b010010010,
|
|
||||||
// 0b001001001,
|
|
||||||
// 0b100010001,
|
|
||||||
// 0b001010100,
|
|
||||||
// ] {
|
|
||||||
// if board & (w << m) == (w << m) {
|
|
||||||
// return (true, Some(t));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// if ((board | (board >> 9)) & 0b111111111) == 0b111111111 {
|
|
||||||
// return (true, None);
|
|
||||||
// }
|
|
||||||
// (false, None)
|
|
||||||
// }
|
|
||||||
// pub fn update_end_state(&mut self, board: &mut u32) {
|
|
||||||
// if let Some((i, _)) = self.end {
|
|
||||||
// if i + Duration::from_secs(7) < Instant::now() {
|
|
||||||
// self.end = None;
|
|
||||||
// // BOARD.store(0, Ordering::Release);
|
|
||||||
// *board = 0;
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// if let (true, t) = self.is_ended(*board) {
|
|
||||||
// self.end = Some((Instant::now(), t));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl App for TttApp {
|
impl App for TttApp {
|
||||||
fn socket_name(&self) -> &'static str {
|
fn socket_name(&self) -> &'static str {
|
||||||
self.team.name()
|
match self.team {
|
||||||
}
|
Team::Zero => "ttt0",
|
||||||
async fn handle_request<'a>(
|
Team::One => "ttt1",
|
||||||
&'a mut self,
|
|
||||||
path: &str,
|
|
||||||
_req_type: HttpRequestType,
|
|
||||||
_content: &str,
|
|
||||||
) -> (HttpResCode, &'static str, Option<Content<'a>>) {
|
|
||||||
match path {
|
|
||||||
"/" | "/index" | "/index.html" | "/ttt" | "/ttt.html" => (
|
|
||||||
HttpResCode::Ok,
|
|
||||||
"html",
|
|
||||||
Some(include_str!("ttt.html").into()),
|
|
||||||
),
|
|
||||||
_ => (HttpResCode::NotFound, "", None),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn accept_ws(&self, path: &str) -> bool {
|
fn accept_ws(&self, path: &str) -> bool {
|
||||||
matches!(path, "/blue" | "/red")
|
(self.team == Team::Zero && path == "/blue") || (self.team == Team::One && path == "/red")
|
||||||
}
|
}
|
||||||
async fn handle_ws<'a, const BUF_SIZE: usize, const RES_HEAD_BUF_SIZE: usize>(
|
async fn handle_ws<'a, const BUF_SIZE: usize, const RES_HEAD_BUF_SIZE: usize>(
|
||||||
&'a mut self,
|
&'a mut self,
|
||||||
@ -154,22 +101,18 @@ impl App for TttApp {
|
|||||||
loop {
|
loop {
|
||||||
Timer::after_millis(1).await;
|
Timer::after_millis(1).await;
|
||||||
let Ok(mut game) = GAME.try_lock() else {
|
let Ok(mut game) = GAME.try_lock() else {
|
||||||
info!("locked");
|
info!("game locked");
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
// match GAME.try_lock() ;
|
|
||||||
if self.last_game != *game {
|
if self.last_game != *game {
|
||||||
// let json = unwrap(serde_json_core::to_string::<Game, 128>(&game)).await;
|
|
||||||
let n = unwrap(serde_json_core::to_slice(&(*game), &mut self.json_buf)).await;
|
let n = unwrap(serde_json_core::to_slice(&(*game), &mut self.json_buf)).await;
|
||||||
let json =
|
let json =
|
||||||
unsafe { from_utf8_unchecked(&unwrap_opt(self.json_buf.get(..n)).await) };
|
unsafe { from_utf8_unchecked(&unwrap_opt(self.json_buf.get(..n)).await) };
|
||||||
info!("{:?}", json);
|
|
||||||
ws.send(WsMsg::Text(json)).await?;
|
ws.send(WsMsg::Text(json)).await?;
|
||||||
self.last_game = game.clone();
|
self.last_game = game.clone();
|
||||||
}
|
}
|
||||||
if ws.last_msg.elapsed() >= Duration::from_secs(5) {
|
if ws.last_msg.elapsed() >= Duration::from_secs(5) {
|
||||||
ws.send(WsMsg::Ping(&[])).await?;
|
ws.send(WsMsg::Ping(&[])).await?;
|
||||||
info!("ping");
|
|
||||||
}
|
}
|
||||||
if self.end.map(|e| e.elapsed()).unwrap_or_default() > Duration::from_secs(5) {
|
if self.end.map(|e| e.elapsed()).unwrap_or_default() > Duration::from_secs(5) {
|
||||||
self.end = None;
|
self.end = None;
|
||||||
@ -179,17 +122,15 @@ impl App for TttApp {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
while let Some(r) = ws.rcv().await? {
|
while let Some(r) = ws.rcv().await? {
|
||||||
info!("{:?}", r);
|
|
||||||
if let WsMsg::Bytes([c]) = r {
|
if let WsMsg::Bytes([c]) = r {
|
||||||
let c = *c as usize;
|
let c = *c as usize;
|
||||||
info!("c={}", c);
|
|
||||||
if c >= game.board.len() {
|
if c >= game.board.len() {
|
||||||
warn!("Cell played is too big!");
|
warn!("Cell played is too big!");
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
if game.board[c].is_some() {
|
if game.board[c].is_some() {
|
||||||
warn!("Cell is already taken!");
|
warn!("Cell is already taken!");
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
if game.turn == Some(self.team) {
|
if game.turn == Some(self.team) {
|
||||||
game.board[c] = Some(self.team);
|
game.board[c] = Some(self.team);
|
||||||
@ -199,17 +140,18 @@ impl App for TttApp {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
warn!("It's not your turn!");
|
warn!("It's not your turn!");
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
info!("{:#?}", game);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Timer::after_secs(1).await;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
warn!("error: {:?}", r);
|
if r.is_err() {
|
||||||
Timer::after_micros(100).await;
|
warn!(
|
||||||
|
"Socket {}: error in ws, terminating connection",
|
||||||
|
self.socket_name()
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ pub async fn dhcp_server(stack: Stack<'static>) {
|
|||||||
|
|
||||||
info!("Starting DHCP server");
|
info!("Starting DHCP server");
|
||||||
loop {
|
loop {
|
||||||
|
Timer::after_secs(0).await;
|
||||||
let (n, _) = unwrap(socket.recv_from(&mut buf).await).await;
|
let (n, _) = unwrap(socket.recv_from(&mut buf).await).await;
|
||||||
|
|
||||||
let msg = unwrap_opt(buf.get(..n)).await;
|
let msg = unwrap_opt(buf.get(..n)).await;
|
||||||
@ -54,7 +55,6 @@ pub async fn dhcp_server(stack: Stack<'static>) {
|
|||||||
rapid_commit = true;
|
rapid_commit = true;
|
||||||
}
|
}
|
||||||
info!("Dhcp: received {:?} message", msg_type);
|
info!("Dhcp: received {:?} message", msg_type);
|
||||||
Timer::after_secs(0).await;
|
|
||||||
|
|
||||||
match msg_type {
|
match msg_type {
|
||||||
DhcpMsgType::DISCOVER | DhcpMsgType::REQUEST => {
|
DhcpMsgType::DISCOVER | DhcpMsgType::REQUEST => {
|
||||||
@ -127,7 +127,6 @@ pub async fn dhcp_server(stack: Stack<'static>) {
|
|||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
info!("Dhcp: offer/ack sent for ip 192.254.0.{}", current_ip);
|
info!("Dhcp: offer/ack sent for ip 192.254.0.{}", current_ip);
|
||||||
Timer::after_secs(0).await;
|
|
||||||
|
|
||||||
if msg_type == DhcpMsgType::REQUEST || rapid_commit {
|
if msg_type == DhcpMsgType::REQUEST || rapid_commit {
|
||||||
current_ip += 1;
|
current_ip += 1;
|
||||||
@ -161,8 +160,7 @@ async fn write_dhcp_opts<const N: usize>(buf: &mut Vec<u8, N>, op_codes: &[u8])
|
|||||||
59 => (4, &3500_u32.to_be_bytes()), // rebinding time
|
59 => (4, &3500_u32.to_be_bytes()), // rebinding time
|
||||||
80 => (0, &[]),
|
80 => (0, &[]),
|
||||||
_ => {
|
_ => {
|
||||||
info!("Dhcp: unhandled requested option {}", o);
|
warn!("Dhcp: unhandled requested option {}", o);
|
||||||
Timer::after_secs(0).await;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
use core::{fmt::Debug, panic::PanicInfo};
|
use core::{fmt::Debug, panic::PanicInfo};
|
||||||
use embassy_time::Timer;
|
use embassy_time::Timer;
|
||||||
use log::info;
|
use log::error;
|
||||||
|
|
||||||
pub async fn unwrap<T, E: Debug>(res: Result<T, E>) -> T {
|
pub async fn unwrap<T, E: Debug>(res: Result<T, E>) -> T {
|
||||||
match res {
|
match res {
|
||||||
Ok(v) => v,
|
Ok(v) => v,
|
||||||
Err(e) => loop {
|
Err(e) => loop {
|
||||||
info!("FATAL ERROR : {:?}", e);
|
error!("FATAL ERROR : {:?}", e);
|
||||||
Timer::after_secs(5).await;
|
Timer::after_secs(5).await;
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
@ -24,9 +24,9 @@ pub async fn assert(condition: bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Doesn't work
|
// TODO: make this log work
|
||||||
#[panic_handler]
|
#[panic_handler]
|
||||||
fn panic(info: &PanicInfo) -> ! {
|
fn panic(info: &PanicInfo) -> ! {
|
||||||
info!("PANIC: {}", info);
|
error!("PANIC: {}", info);
|
||||||
loop {}
|
loop {}
|
||||||
}
|
}
|
||||||
|
24
src/main.rs
24
src/main.rs
@ -1,12 +1,6 @@
|
|||||||
#![no_std]
|
#![no_std]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
#![allow(async_fn_in_trait)]
|
#![allow(async_fn_in_trait)]
|
||||||
#![deny(
|
|
||||||
// clippy::unwrap_used,
|
|
||||||
// clippy::expect_used,
|
|
||||||
clippy::panic,
|
|
||||||
clippy::indexing_slicing
|
|
||||||
)]
|
|
||||||
#![feature(impl_trait_in_assoc_type)]
|
#![feature(impl_trait_in_assoc_type)]
|
||||||
#![feature(slice_split_once)]
|
#![feature(slice_split_once)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
@ -16,8 +10,6 @@
|
|||||||
use core::net::Ipv4Addr;
|
use core::net::Ipv4Addr;
|
||||||
|
|
||||||
use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
|
use cyw43_pio::{DEFAULT_CLOCK_DIVIDER, PioSpi};
|
||||||
use defmt::warn;
|
|
||||||
use defmt_rtt as _;
|
|
||||||
use embassy_executor::Spawner;
|
use embassy_executor::Spawner;
|
||||||
use embassy_net::{Config, StackResources};
|
use embassy_net::{Config, StackResources};
|
||||||
use embassy_rp::bind_interrupts;
|
use embassy_rp::bind_interrupts;
|
||||||
@ -70,13 +62,6 @@ async fn main(spawner: Spawner) {
|
|||||||
spawner.spawn(logger_task(driver)).unwrap();
|
spawner.spawn(logger_task(driver)).unwrap();
|
||||||
let mut rng = RoscRng;
|
let mut rng = RoscRng;
|
||||||
|
|
||||||
// let mut i = 0;
|
|
||||||
// loop {
|
|
||||||
// info!("test{}", i);
|
|
||||||
// Timer::after_secs(1).await;
|
|
||||||
// i += 1;
|
|
||||||
// }
|
|
||||||
|
|
||||||
let fw = include_bytes!("../cyw43-firmware/43439A0.bin");
|
let fw = include_bytes!("../cyw43-firmware/43439A0.bin");
|
||||||
let clm = include_bytes!("../cyw43-firmware/43439A0_clm.bin");
|
let clm = include_bytes!("../cyw43-firmware/43439A0_clm.bin");
|
||||||
let pwr = Output::new(p.PIN_23, Level::Low);
|
let pwr = Output::new(p.PIN_23, Level::Low);
|
||||||
@ -171,9 +156,6 @@ async fn main(spawner: Spawner) {
|
|||||||
// Wait for DHCP, not necessary when using static IP
|
// Wait for DHCP, not necessary when using static IP
|
||||||
info!("waiting for DHCP...");
|
info!("waiting for DHCP...");
|
||||||
stack.wait_config_up().await;
|
stack.wait_config_up().await;
|
||||||
// while !stack.is_config_up() {
|
|
||||||
// Timer::after_millis(100).await;
|
|
||||||
// }
|
|
||||||
info!("DHCP is now up!");
|
info!("DHCP is now up!");
|
||||||
info!(
|
info!(
|
||||||
"ip : {}",
|
"ip : {}",
|
||||||
@ -182,12 +164,6 @@ async fn main(spawner: Spawner) {
|
|||||||
.address
|
.address
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
// embassy_time::Timer::after_secs(5).await;
|
|
||||||
// info!("test0");
|
|
||||||
|
|
||||||
// embassy_time::Timer::after_secs(3).await;
|
|
||||||
|
|
||||||
// panic!("test");
|
|
||||||
|
|
||||||
#[cfg(feature = "dhcp")]
|
#[cfg(feature = "dhcp")]
|
||||||
unwrap(spawner.spawn(dhcp::dhcp_server(stack))).await;
|
unwrap(spawner.spawn(dhcp::dhcp_server(stack))).await;
|
||||||
|
@ -32,10 +32,6 @@ pub async fn chat_listen_task(stack: embassy_net::Stack<'static>, port: u16) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps::App, port: u16) {
|
pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps::App, port: u16) {
|
||||||
// loop {
|
|
||||||
// info!("team:{:?}", team);
|
|
||||||
// Timer::after_millis(0).await;
|
|
||||||
// }
|
|
||||||
let mut rx_buffer = [0; 1024];
|
let mut rx_buffer = [0; 1024];
|
||||||
let mut tx_buffer = [0; 2048];
|
let mut tx_buffer = [0; 2048];
|
||||||
let mut buf = [0; 1024];
|
let mut buf = [0; 1024];
|
||||||
@ -84,9 +80,6 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// info!("\n{:?}\n", headers);
|
|
||||||
// Timer::after_micros(100).await;
|
|
||||||
|
|
||||||
let mut hl = headers.lines();
|
let mut hl = headers.lines();
|
||||||
let (request_type, path) = match hl.next() {
|
let (request_type, path) = match hl.next() {
|
||||||
None => {
|
None => {
|
||||||
@ -147,7 +140,6 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
|
|||||||
host,
|
host,
|
||||||
path,
|
path,
|
||||||
);
|
);
|
||||||
Timer::after_micros(100).await;
|
|
||||||
|
|
||||||
head_buf.clear();
|
head_buf.clear();
|
||||||
let res_content: Result<Option<Content>, core::fmt::Error> = try {
|
let res_content: Result<Option<Content>, core::fmt::Error> = try {
|
||||||
@ -182,24 +174,14 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
|
|||||||
Upgrade: websocket\r\n\
|
Upgrade: websocket\r\n\
|
||||||
Connection: Upgrade\r\n\
|
Connection: Upgrade\r\n\
|
||||||
Sec-WebSocket-Accept: {}\r\n\r\n",
|
Sec-WebSocket-Accept: {}\r\n\r\n",
|
||||||
// Sec-WebSocket-Protocol: chat\r\n
|
|
||||||
Into::<&str>::into(HttpResCode::SwitchingProtocols),
|
Into::<&str>::into(HttpResCode::SwitchingProtocols),
|
||||||
accept
|
accept
|
||||||
)?;
|
)?;
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let (code, res_type, res_content) = match path {
|
let (code, res_type, res_content) =
|
||||||
"/htmx.js" => (
|
app.handle_request(path, request_type, content).await;
|
||||||
HttpResCode::Ok,
|
|
||||||
"javascript",
|
|
||||||
#[cfg(debug_assertions)]
|
|
||||||
Some(include_str!("../static/htmx.js").into()),
|
|
||||||
#[cfg(not(debug_assertions))]
|
|
||||||
Some(include_bytes!("../static/htmx.min.js").into()),
|
|
||||||
),
|
|
||||||
_ => app.handle_request(path, request_type, content).await,
|
|
||||||
};
|
|
||||||
|
|
||||||
write!(&mut head_buf, "{}", Into::<&str>::into(code))?;
|
write!(&mut head_buf, "{}", Into::<&str>::into(code))?;
|
||||||
if let Some(ref c) = res_content {
|
if let Some(ref c) = res_content {
|
||||||
@ -225,9 +207,6 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
info!("\n{}\n", unwrap(from_utf8(&head_buf)).await);
|
|
||||||
Timer::after_micros(1000).await;
|
|
||||||
|
|
||||||
let w: Result<(), embassy_net::tcp::Error> = try {
|
let w: Result<(), embassy_net::tcp::Error> = try {
|
||||||
socket.write_all(&head_buf).await?;
|
socket.write_all(&head_buf).await?;
|
||||||
if let Some(ref c) = res_content {
|
if let Some(ref c) = res_content {
|
||||||
@ -248,8 +227,6 @@ pub async fn listen_task(stack: embassy_net::Stack<'static>, mut app: impl apps:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(path) = ws_path {
|
if let Some(path) = ws_path {
|
||||||
info!("handle ws");
|
|
||||||
Timer::after_micros(200).await;
|
|
||||||
app.handle_ws(
|
app.handle_ws(
|
||||||
&path,
|
&path,
|
||||||
Ws::new(&mut socket, &mut buf, &mut head_buf, app.socket_name()),
|
Ws::new(&mut socket, &mut buf, &mut head_buf, app.socket_name()),
|
||||||
@ -297,7 +274,6 @@ impl Into<&str> for HttpResCode {
|
|||||||
|
|
||||||
async fn compute_ws_accept(key: &str) -> Result<String<28>, EncodeSliceError> {
|
async fn compute_ws_accept(key: &str) -> Result<String<28>, EncodeSliceError> {
|
||||||
let mut res = Vec::<u8, 28>::new();
|
let mut res = Vec::<u8, 28>::new();
|
||||||
Timer::after_micros(10).await;
|
|
||||||
res.extend_from_slice(&[0; 28]).unwrap();
|
res.extend_from_slice(&[0; 28]).unwrap();
|
||||||
let mut hasher = Sha1::new();
|
let mut hasher = Sha1::new();
|
||||||
hasher.update(key.as_bytes());
|
hasher.update(key.as_bytes());
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use core::str::from_utf8;
|
use core::str::from_utf8;
|
||||||
|
|
||||||
use embassy_net::tcp::{TcpReader, TcpSocket, TcpWriter};
|
use embassy_net::tcp::{TcpReader, TcpSocket, TcpWriter};
|
||||||
use embassy_time::{Instant, Timer};
|
use embassy_time::Instant;
|
||||||
use embedded_io_async::{ErrorType, ReadReady, Write};
|
use embedded_io_async::{ErrorType, ReadReady, Write};
|
||||||
use heapless::Vec;
|
use heapless::Vec;
|
||||||
use log::{info, warn};
|
use log::{info, warn};
|
||||||
@ -58,7 +58,6 @@ impl<'a, const HEAD_BUF_SIZE: usize> WsTx<'a, HEAD_BUF_SIZE> {
|
|||||||
.extend_from_slice(&(msg.len() as u16).to_le_bytes()),
|
.extend_from_slice(&(msg.len() as u16).to_le_bytes()),
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
// self.head_buf.extend_from_slice(msg.as_bytes()).unwrap();
|
|
||||||
}
|
}
|
||||||
let w: Result<(), <TcpSocket<'_> as ErrorType>::Error> = try {
|
let w: Result<(), <TcpSocket<'_> as ErrorType>::Error> = try {
|
||||||
self.socket.write_all(&self.head_buf).await?;
|
self.socket.write_all(&self.head_buf).await?;
|
||||||
@ -66,7 +65,6 @@ impl<'a, const HEAD_BUF_SIZE: usize> WsTx<'a, HEAD_BUF_SIZE> {
|
|||||||
};
|
};
|
||||||
w.map_err(|e| {
|
w.map_err(|e| {
|
||||||
warn!("write error: {:?}", e);
|
warn!("write error: {:?}", e);
|
||||||
()
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -99,7 +97,7 @@ impl<'a, const BUF_SIZE: usize, const HEAD_BUF_SIZE: usize> Ws<'a, BUF_SIZE, HEA
|
|||||||
name,
|
name,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Do this often to respond to pings
|
/// Do this often to respond to pings
|
||||||
pub async fn rcv(&mut self) -> Result<Option<WsMsg>, ()> {
|
pub async fn rcv(&mut self) -> Result<Option<WsMsg>, ()> {
|
||||||
let n = match self.rx.msg_in_buf.take() {
|
let n = match self.rx.msg_in_buf.take() {
|
||||||
Some(n) => {
|
Some(n) => {
|
||||||
@ -108,12 +106,12 @@ impl<'a, const BUF_SIZE: usize, const HEAD_BUF_SIZE: usize> Ws<'a, BUF_SIZE, HEA
|
|||||||
if unwrap(self.rx.socket.read_ready()).await {
|
if unwrap(self.rx.socket.read_ready()).await {
|
||||||
let n_rcv = match self.rx.socket.read(&mut self.rx.buf[n.1..]).await {
|
let n_rcv = match self.rx.socket.read(&mut self.rx.buf[n.1..]).await {
|
||||||
Ok(0) => {
|
Ok(0) => {
|
||||||
info!("read EOF");
|
warn!("read EOF");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info!("Socket {}: read error: {:?}", self.name, e);
|
warn!("Socket {}: read error: {:?}", self.name, e);
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -126,12 +124,12 @@ impl<'a, const BUF_SIZE: usize, const HEAD_BUF_SIZE: usize> Ws<'a, BUF_SIZE, HEA
|
|||||||
if unwrap(self.rx.socket.read_ready()).await {
|
if unwrap(self.rx.socket.read_ready()).await {
|
||||||
match self.rx.socket.read(self.rx.buf).await {
|
match self.rx.socket.read(self.rx.buf).await {
|
||||||
Ok(0) => {
|
Ok(0) => {
|
||||||
info!("read EOF");
|
warn!("read EOF");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
Ok(n) => n,
|
Ok(n) => n,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
info!("Socket {}: read error: {:?}", self.name, e);
|
warn!("Socket {}: read error: {:?}", self.name, e);
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -142,11 +140,11 @@ impl<'a, const BUF_SIZE: usize, const HEAD_BUF_SIZE: usize> Ws<'a, BUF_SIZE, HEA
|
|||||||
};
|
};
|
||||||
|
|
||||||
if self.rx.buf[0] & 0b1000_0000 == 0 {
|
if self.rx.buf[0] & 0b1000_0000 == 0 {
|
||||||
info!("Fragmented ws messages are not supported!");
|
warn!("Fragmented ws messages are not supported!");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
if self.rx.buf[0] & 0b0111_0000 != 0 {
|
if self.rx.buf[0] & 0b0111_0000 != 0 {
|
||||||
info!(
|
warn!(
|
||||||
"Reserved ws bits are set : {}",
|
"Reserved ws bits are set : {}",
|
||||||
(self.rx.buf[0] >> 4) & 0b0111
|
(self.rx.buf[0] >> 4) & 0b0111
|
||||||
);
|
);
|
||||||
@ -164,14 +162,14 @@ impl<'a, const BUF_SIZE: usize, const HEAD_BUF_SIZE: usize> Ws<'a, BUF_SIZE, HEA
|
|||||||
l => (l as u64, 2),
|
l => (l as u64, 2),
|
||||||
};
|
};
|
||||||
if length > 512 {
|
if length > 512 {
|
||||||
info!("ws payload bigger than 512!");
|
warn!("ws payload bigger than 512!");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
|
|
||||||
let content = if self.rx.buf[1] & 0b1000_0000 != 0 {
|
let content = if self.rx.buf[1] & 0b1000_0000 != 0 {
|
||||||
// masked message
|
// masked message
|
||||||
if n_after_length + 4 + length as usize > n {
|
if n_after_length + 4 + length as usize > n {
|
||||||
info!("ws payload smaller than length");
|
warn!("ws payload smaller than length");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
let mask_key: [u8; 4] = self.rx.buf[n_after_length..n_after_length + 4]
|
let mask_key: [u8; 4] = self.rx.buf[n_after_length..n_after_length + 4]
|
||||||
@ -192,7 +190,7 @@ impl<'a, const BUF_SIZE: usize, const HEAD_BUF_SIZE: usize> Ws<'a, BUF_SIZE, HEA
|
|||||||
&self.rx.buf[n_after_length + 4..n_after_length + 4 + length as usize]
|
&self.rx.buf[n_after_length + 4..n_after_length + 4 + length as usize]
|
||||||
} else {
|
} else {
|
||||||
if n_after_length + length as usize > n {
|
if n_after_length + length as usize > n {
|
||||||
info!("ws payload smaller than length");
|
warn!("ws payload smaller than length");
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
if n_after_length + (length as usize) < n {
|
if n_after_length + (length as usize) < n {
|
||||||
@ -220,7 +218,7 @@ impl<'a, const BUF_SIZE: usize, const HEAD_BUF_SIZE: usize> Ws<'a, BUF_SIZE, HEA
|
|||||||
// Pong
|
// Pong
|
||||||
10 => Ok(Some(WsMsg::Pong(&content))),
|
10 => Ok(Some(WsMsg::Pong(&content))),
|
||||||
c => {
|
c => {
|
||||||
info!("Unknown ws op code (ignoring) : {}", c);
|
warn!("Unknown ws op code (ignoring) : {}", c);
|
||||||
Ok(Some(WsMsg::Unknown(c, &content)))
|
Ok(Some(WsMsg::Unknown(c, &content)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
1
static/index.min.html
Normal file
1
static/index.min.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<!doctype html><html><body><h1>Apps</h1><ul><li><a href="/ttt?team=0">Tic Tac Toe</a>(team blue)</li><li><a href="/ttt?team=1">Tic Tac Toe</a>(team red)</li></ul></body></html>
|
1
static/ttt.min.html
Normal file
1
static/ttt.min.html
Normal file
@ -0,0 +1 @@
|
|||||||
|
<!doctype html><head><style type="text/css"> body { #grid { .cell { border: 1px dotted black; padding: 33%; } .cell[team="0"] { background-color: dodgerblue; } .cell[team="1"] { background-color: firebrick; } display: grid; border: 1px solid black; grid-template-rows: 1fr 1fr 1fr; grid-template-columns: 1fr 1fr 1fr; } } </style><script src="/ttt.js" defer></script></head><html><body><h1>TicTacToe</h1><h3 id="team"></h3><h3 id="winner"></h3><div id="grid"></div></body></html>
|
1
static/ttt.min.js
vendored
Normal file
1
static/ttt.min.js
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
if(0!=team&&1!=team)throw"team is not 0 or 1! team="+team;const teams=[{name:"blue",color:"dodgerblue",port:"8080"},{name:"red",color:"firebrick",port:"8081"}];document.getElementById("team").innerHTML='Team : <span style="color:'+teams[team].color+'">'+teams[team].name+"</span>";const ws=new WebSocket("ws://192.254.0.2:"+teams[team].port+"/"+teams[team].name);ws.onmessage=e=>{if("string"==typeof e.data){let t=JSON.parse(e.data),n=[];for(let e=0;e<9;e++){let a,r=t.board[e];a=t.turn==team&&null===r?"button":"div";let m=document.createElement(a);m.classList.add("cell"),"button"===a&&m.addEventListener("click",(t=>{ws.send(new Uint8Array([e]))})),m.setAttribute("team",r),n.push(m)}document.getElementById("grid").replaceChildren(...n),null==t.turn?null==t.winner?document.getElementById("winner").innerHTML="Draw!":document.getElementById("winner").innerHTML='Winner : <span style="color:'+teams[t.winner].color+'">'+teams[t.winner].name+"</span>":document.getElementById("winner").innerHTML=""}};
|
Loading…
Reference in New Issue
Block a user