summaryrefslogtreecommitdiff
path: root/server/src/main.rs
diff options
context:
space:
mode:
Diffstat (limited to 'server/src/main.rs')
-rw-r--r--server/src/main.rs42
1 files changed, 25 insertions, 17 deletions
diff --git a/server/src/main.rs b/server/src/main.rs
index a0a1d39..5e62213 100644
--- a/server/src/main.rs
+++ b/server/src/main.rs
@@ -83,7 +83,7 @@ impl Server {
self.database
.execute(
&self.set_puzzle_data,
- &[&width, &height, &url, &connectivity, &positions, &id, &seed],
+ &[&width, &height, &url, &connectivity, &positions, &seed, &id],
)
.await?;
Ok(())
@@ -174,7 +174,7 @@ enum Error {
UTF8(std::str::Utf8Error),
BadPuzzleID,
BadPieceID,
- BadSyntax,
+ BadSyntax(&'static str),
ImageURLTooLong,
TooManyPieces,
TooManyPlayers,
@@ -186,7 +186,7 @@ impl std::fmt::Display for Error {
match self {
Error::BadPieceID => write!(f, "bad piece ID"),
Error::BadPuzzleID => write!(f, "bad puzzle ID"),
- Error::BadSyntax => write!(f, "bad syntax"),
+ Error::BadSyntax(s) => write!(f, "bad syntax: {s}"),
Error::ImageURLTooLong => write!(f, "image URL too long"),
Error::TooManyPieces => write!(f, "too many pieces"),
Error::NotJoined => write!(f, "haven't joined a puzzle"),
@@ -267,29 +267,32 @@ async fn handle_websocket(
let mut parts = dimensions.split(' ');
let width: u8 = parts
.next()
- .ok_or(Error::BadSyntax)?
+ .ok_or(Error::BadSyntax("no width"))?
.parse()
- .map_err(|_| Error::BadSyntax)?;
+ .map_err(|_| Error::BadSyntax("width not integer"))?;
let height: u8 = parts
.next()
- .ok_or(Error::BadSyntax)?
+ .ok_or(Error::BadSyntax("no height"))?
.parse()
- .map_err(|_| Error::BadSyntax)?;
+ .map_err(|_| Error::BadSyntax("height not integer"))?;
if width < 3 || height < 3 {
- return Err(Error::BadSyntax);
+ return Err(Error::BadSyntax("dimensions too small"));
}
if usize::from(width) * usize::from(height) > MAX_PIECES {
return Err(Error::TooManyPieces);
}
- let url: String = parts.next().ok_or(Error::BadSyntax)?.replace(';', " ");
+ let url: String = parts
+ .next()
+ .ok_or(Error::BadSyntax("no URL"))?
+ .replace(';', " ");
if url.len() > 2048 {
return Err(Error::ImageURLTooLong);
}
let seed = parts
.next()
- .ok_or(Error::BadSyntax)?
+ .ok_or(Error::BadSyntax("no seed"))?
.parse()
- .map_err(|_| Error::BadSyntax)?;
+ .map_err(|_| Error::BadSyntax("seed not integer"))?;
let piece_positions = vec![0.0f32; 2 * (width as usize) * (height as usize)];
let mut connectivity_data: Vec<u16> =
Vec::with_capacity(usize::from(width) * usize::from(height));
@@ -319,7 +322,10 @@ async fn handle_websocket(
ws.send(Message::Text(format!("id: {}", std::str::from_utf8(&id)?)))
.await?;
} else if let Some(id) = text.strip_prefix("join ") {
- let id = id.as_bytes().try_into().map_err(|_| Error::BadSyntax)?;
+ let id = id
+ .as_bytes()
+ .try_into()
+ .map_err(|_| Error::BadSyntax("bad join ID"))?;
let mut player_counts = server.player_counts.lock().await;
let entry = player_counts.entry(id).or_default();
if *entry >= MAX_PLAYERS {
@@ -367,14 +373,16 @@ async fn handle_websocket(
}
} else if let Message::Binary(data) = &message {
if data.len() % 4 != 0 {
- return Err(Error::BadSyntax);
+ return Err(Error::BadSyntax("binary message not multiple of 4 bytes"));
}
let puzzle_id = puzzle_id.ok_or(Error::NotJoined)?;
let mut reader_data = std::io::Cursor::new(data);
let reader = &mut reader_data;
fn read<const N: usize>(reader: &mut std::io::Cursor<&Vec<u8>>) -> Result<[u8; N]> {
let mut data = [0; N];
- reader.read_exact(&mut data).map_err(|_| Error::BadSyntax)?;
+ reader
+ .read_exact(&mut data)
+ .map_err(|_| Error::BadSyntax("unexpected EOF in action sequence"))?;
Ok(data)
}
fn read_u32(reader: &mut std::io::Cursor<&Vec<u8>>) -> Result<u32> {
@@ -384,7 +392,7 @@ async fn handle_websocket(
Ok(f32::from_le_bytes(read(reader)?))
}
let message_id = read_u32(reader)?;
- while !reader.get_ref().is_empty() {
+ while reader.position() < reader.get_ref().len() as u64 {
let action = read_u32(reader)?;
if action == ACTION_MOVE {
let piece: usize = read_u32(reader)? as _;
@@ -392,7 +400,7 @@ async fn handle_websocket(
let y: f32 = read_f32(reader)?;
for coord in [x, y] {
if !coord.is_finite() || coord < 0.0 || coord > 2.0 {
- return Err(Error::BadSyntax);
+ return Err(Error::BadSyntax("piece position out of bounds"));
}
}
server.move_piece(puzzle_id, piece, x, y).await?;
@@ -401,7 +409,7 @@ async fn handle_websocket(
let piece2: usize = read_u32(reader)? as _;
server.connect_pieces(puzzle_id, piece1, piece2).await?;
} else {
- return Err(Error::BadSyntax);
+ return Err(Error::BadSyntax("bad action"));
}
}
ws.send(Message::Text(format!("ack {message_id}"))).await?;