Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 24 additions & 3 deletions client/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,15 +42,21 @@ impl EventLoopWrapper {
/// 서버 메시지 수신 태스크 (읽기 전용)
async fn network_listener(mut read_half: OwnedReadHalf, tx: mpsc::Sender<ServerMessage>) {
use tokio::io::AsyncReadExt;
let mut buffer = vec![0u8; 1024];

let mut read_buf = vec![0u8; 1024];
let mut buf = Vec::<u8>::new();

loop {
match read_half.read(&mut buffer).await {
match read_half.read(&mut read_buf).await {
Ok(0) => {
println!("Server disconnected.");
break;
}
Ok(n) => {
if let Ok(msg) = bincode::deserialize::<ServerMessage>(&buffer[..n]) {
buf.extend_from_slice(&read_buf[..n]);

while let Ok((msg, consumed)) = try_deser::<ServerMessage>(&buf) {
buf.drain(..consumed);
if tx.send(msg).await.is_err() {
eprintln!("Failed to send server message to channel");
}
Expand All @@ -65,6 +71,21 @@ async fn network_listener(mut read_half: OwnedReadHalf, tx: mpsc::Sender<ServerM
println!("network_listener finished.");
}

fn try_deser<T: serde::de::DeserializeOwned>(buf: &[u8]) -> Result<(T, usize), bincode::Error> {
let mut cur = std::io::Cursor::new(buf);

match bincode::deserialize_from(&mut cur) {
Ok(m) => Ok((m, cur.position() as usize)),

Err(e) => match *e {
bincode::ErrorKind::Io(ref io_err) if io_err.kind() == std::io::ErrorKind::UnexpectedEof => {
Err(e)
}
_ => panic!("Invalid data during deserialization: {:?}", e),
},
}
}

#[tokio::main]
async fn main() {
let server_addr = env::args().nth(1).unwrap_or_else(|| {
Expand Down
3 changes: 3 additions & 0 deletions messages/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ edition = "2021"
[dependencies]
serde = { version = "1.0.217", features = ["derive"] }
map-types = { version = "0.1.0", path = "../map_types" }

[dev-dependencies]
bincode = "1.3"
47 changes: 47 additions & 0 deletions messages/tests/partial_stream.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
use messages::{ServerMessage, PlayerAction, PlayerPosition};
use bincode;

fn try_deser<T: serde::de::DeserializeOwned>(buf: &[u8]) -> Result<(T, usize), bincode::Error> {
let mut cur = std::io::Cursor::new(buf);
match bincode::deserialize_from(&mut cur) {
Ok(m) => Ok((m, cur.position() as usize)),
Err(e) => match *e {
bincode::ErrorKind::Io(ref io_err) if io_err.kind() == std::io::ErrorKind::UnexpectedEof => Err(e),
_ => panic!("Invalid data during deserialization: {:?}", e),
},
}
}

#[test]
fn parse_two_messages_from_partial_third() {
// prepare three messages
let msg1 = ServerMessage::Init { your_player_id: 1, your_position: PlayerPosition::NotInWorld };
let msg2 = ServerMessage::PlayerAction { action: PlayerAction::DestroyBlock };
let msg3 = ServerMessage::Init { your_player_id: 2, your_position: PlayerPosition::NotInWorld };

let mut buf = Vec::new();
bincode::serialize_into(&mut buf, &msg1).unwrap();
bincode::serialize_into(&mut buf, &msg2).unwrap();
let partial = bincode::serialize(&msg3).unwrap();
let cut = partial.len() / 2;
buf.extend_from_slice(&partial[..cut]);

// first message
let (parsed1, consumed1) = try_deser::<ServerMessage>(&buf).unwrap();
match parsed1 {
ServerMessage::Init { your_player_id, .. } => assert_eq!(your_player_id, 1),
_ => panic!("Unexpected variant for first message"),
}
buf.drain(..consumed1);

// second message
let (parsed2, consumed2) = try_deser::<ServerMessage>(&buf).unwrap();
match parsed2 {
ServerMessage::PlayerAction { action: PlayerAction::DestroyBlock } => {},
_ => panic!("Unexpected variant for second message"),
}
buf.drain(..consumed2);

// third message should be incomplete
assert!(try_deser::<ServerMessage>(&buf).is_err());
}