Unexpected end of file during wasm sent package (work in native)

⚓ Rust    📅 2025-09-28    👤 surdeus    👁️ 6      

surdeus

Warning

This post was published 33 days ago. The information described in this article may have changed.

Hi everyone !

I work on a live version of freeciv game.

It uses the bevy engine, work in native and wasm target. After long time without tested my wasm version (I only checked its compile) I have a strange error in the network layer.

Unfortunately, I was unable to make a minimal reproduction code. I am not comfortable with wasm (I think bevy do a lot for me). I stopped trying after one day of try. I post this message in hope of someone have a good idea or a path to follow :slight_smile:

There is the situation :

I use message-io for http server. I serve like this (entire module) :

let (handler, node_listener) = node::split::<Signal>();

info!(
    "Starting TCP {} and Ws {}",
    &self.tcp_listen_addr, &self.ws_listen_addr
);
handler
    .network()
    .listen(Transport::FramedTcp, &self.tcp_listen_addr)
    .unwrap();
handler
    .network()
    .listen(Transport::Ws, &self.ws_listen_addr)
    .unwrap();

// [...]

node_listener.for_each(move |event| match event {
    node::NodeEvent::Network(event) => match event {
        NetEvent::Connected(_, _) => unreachable!(), // There is no connect() calls.
        NetEvent::Accepted(_, _) => {}
        NetEvent::Message(endpoint, input_data) => {
            let message = match bincode::deserialize::<ClientToServerMessage>(input_data) {
                Ok(message) => message,
                Err(error) => {
                    log::error!("Receive error: {error}");
                    return;
                }
            };
         // Use message [...]

The native client (gui) part send message like this (entire file):

// message is `ClientToServerMessage`
let message = bincode::serialize(&message).unwrap();
// handler is from message-io
handler.network().send(server, &message);

The wasm client (gui) part use async-wsocket send message like this (entire file):

// message is `ClientToServerMessage`
let bytes = bincode::serialize(&message).unwrap();
tx.send(WsMessage::Binary(bytes)).await.unwrap();

The ClientToServerMessage definition is (partial here, entire file):

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ClientToServerMessage {
    Network(ClientToServerNetworkMessage),
    Game(ClientToServerGameMessage),
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ClientToServerNetworkMessage {
    Hello(Client, Resolution),
    Goodbye,
}

#[derive(Serialize, Deserialize, Clone, Debug)]
pub enum ClientToServerGameMessage {
    Establishment(ClientToServerEstablishmentMessage),
    InGame(ClientToServerInGameMessage),
}

// [...]

There are the facts:

  • The native version works perfectly
  • The wasm version success when send ClientToServerMessage::Network message but fail when send ClientToServerMessage::Game message. Error in server part is io error: unexpected end of file on bincode::deserialize::<ClientToServerMessage>(input_data)
  • The wasm version worked perfectly some weeks (month ?) ago. Before I made some refactor (not on network layer!) (I fail to git bisect, as I didn't check regularly the wasm version ...)

My feeling is that is related to ClientToServerMessage. But I don't understand why wasm version can work when send ClientToServerMessage::Network if fail with ClientToServerMessage::Game ...

If you feel very brave :sweat_smile: , there is the way to reproduce locally (tested with Ubuntu, but should work on Windows and Mac):

To generate a world and start server:

  • git clone git@github.com:buxx/civ.git
  • git checkout fix-wasm-message
  • cargo run --bin world --release -- ./world 5000 5000
  • cargo run --release --bin server -- ./world

In other terminal, to start wasm http server :

  • ./build_wasm.sh && http-server wasm

Then you can open http://127.0.0.1:7878/index.html . You cal click on Connect, then again Connect (here, ClientToServerMessage::Network message has been sent then correctly deserialized by server). Click now on Join after choose a country. You will see the io error: unexpected end of file error in server part.

If you've read this far, thank you!

1 post - 1 participant

Read full topic

🏷️ Rust_feed