Stop crashing on EOF in codec

This commit is contained in:
Garen Tyler 2025-02-15 19:40:46 -07:00
parent 3b7fe29f0f
commit 8227b5d4f0
Signed by: garentyler
SSH Key Fingerprint: SHA256:G4ke7blZMdpWPbkescyZ7IQYE4JAtwpI85YoJdq+S7U
5 changed files with 56 additions and 16 deletions

1
.gitignore vendored
View File

@ -5,3 +5,4 @@ target
/world
/server-icon.png
/composition.toml
/reference

View File

@ -1,12 +1,15 @@
FROM rust:1.83.0-alpine3.20 AS base
RUN apk add --no-cache musl-dev git
RUN cargo install cargo-chef --locked --version 0.1.71
RUN cargo install cargo-watch --locked --version 8.5.3
WORKDIR /app
RUN git config --global --add safe.directory /app
ARG FEATURES
RUN addgroup --gid 25565 --system composition && adduser --uid 25565 --system --ingroup composition --home /app composition
RUN chown -R composition:composition /app
USER composition
FROM base AS dev
RUN cargo install cargo-watch --locked --version 8.5.3
VOLUME /app
VOLUME /app/.git
EXPOSE 25565

View File

@ -43,3 +43,5 @@ services:
volumes:
- .:/app
- .git:/app/.git
environment:
CARGO_HOME: "/app/.cargo"

View File

@ -219,11 +219,22 @@ impl Connection {
}
pub async fn read_packet(&mut self) -> Option<Result<Packet, Error>> {
self.last_received_data_time = Instant::now();
self.stream.next().await
self.stream.next().await.map(|packet| {
packet.map_err(|mut e| {
// Set the codec error to something more descriptive.
if e.to_string() == "bytes remaining on stream" {
e = Error::Io(std::io::Error::new(std::io::ErrorKind::UnexpectedEof, e));
}
trace!("Error reading packet from connection {}: {:?}", self.id, e);
e
})
})
}
pub async fn send_packet<P: Into<Packet>>(&mut self, packet: P) -> Result<(), Error> {
let packet: Packet = packet.into();
self.stream.send(packet).await
self.stream.send(packet).await.inspect_err(|e| {
trace!("Error sending packet to connection {}: {:?}", self.id, e);
})
}
pub async fn disconnect(mut self, reason: Option<Chat>) -> Result<(), Error> {
trace!("Connection disconnected (id {})", self.id);

View File

@ -90,7 +90,8 @@ impl App for Proxy {
return Ok(());
};
let mut client_parsing_error = false;
let mut client_error = false;
let mut server_error = false;
// At the same time, try to read packets from the server and client.
// Forward the packet onto the other.
@ -106,11 +107,24 @@ impl App for Proxy {
*self.upstream.client_state_mut() = next_state;
}
}
Err(NetworkError::Parsing) => {
debug!("Got invalid data from client (id {})", client.id());
client_parsing_error = true;
Err(e) => {
client_error = true;
match e {
NetworkError::Parsing => {
trace!("Got invalid data from client (id {})", client.id());
return Err(Error::Network(NetworkError::Parsing));
}
NetworkError::Io(e) => {
if e.kind() == std::io::ErrorKind::UnexpectedEof {
trace!("Client (id {}) disconnected", client.id());
} else {
trace!("Got IO error from client (id {}): {}", client.id(), e);
return Err(Error::Io(e));
}
}
e => return Err(Error::Network(e)),
};
}
Err(e) => return Err(Error::Network(e)),
}
}
}
@ -125,17 +139,26 @@ impl App for Proxy {
*client.client_state_mut() = next_state;
}
}
Err(NetworkError::Parsing) => {
error!("Got invalid data from upstream");
return Err(Error::Network(NetworkError::Parsing));
},
Err(e) => return Err(Error::Network(e)),
Err(e) => {
server_error = true;
return match e {
NetworkError::Parsing => {
trace!("Got invalid data from upstream");
Err(Error::Network(NetworkError::Parsing))
}
NetworkError::Io(e) => {
trace!("Got IO error from upstream");
Err(Error::Io(e))
}
e => Err(Error::Network(e)),
};
}
}
}
}
}
if client_parsing_error {
if client_error {
let id = client.id();
// Drop the &mut Connection
let _ = client;
@ -147,7 +170,7 @@ impl App for Proxy {
)
.await;
}
if self.upstream.client_state() == ClientState::Disconnected {
if self.upstream.client_state() == ClientState::Disconnected || server_error {
// Start a new connection with the upstream server.
self.upstream = Proxy::connect_upstream(&self.upstream_address).await?;
}