NoahShomette / bevy_eventwork_mod_websockets

A crate that provides a websocket networking transport layer for Bevy_eventwork that supports WASM and Native.
8 stars 4 forks source link

Sending messages from JavaScript #2

Open davi4046 opened 3 months ago

davi4046 commented 3 months ago

How can I format messages in JavaScript such that bevy_eventwork is able to handle them correctly?

So far I've tried the naive approach:

const socket = new WebSocket('ws://localhost:8081');

const message = {
    kind: 'balls_of_steel:ChatMessage',
    data: {
        message: 'Hi Server!',
    },
};

socket.send(JSON.stringify(message))

Sending this message terminates the connection (which I have succesfully established).

I assume this is because the message format is wrong.

When receiving messages from the server in JavaScript, I get a Blob object. Calling "text" on this Blob, gives me the following text (some weird bytes):

balls_of_steel:ChatMessage
hello

Receiving messages in JS:

socket.addEventListener('message', async (event) => {
    const blob = event.data as Blob;

    console.log('Message from server:', await blob.text());
});

ChatMessage:

#[derive(Serialize, Deserialize, Clone, Debug)]
pub struct ChatMessage {
    pub message: String,
}

impl NetworkMessage for ChatMessage {
    const NAME: &'static str = "balls_of_steel:ChatMessage";
}

I used the websocket crate beforehand and I with this crate I was able to send JSON-stringified JavaScript objects and handle them in Rust.

NoahShomette commented 3 months ago

BEMW and Eventwork internally just straight up uses Bincode to serialize/deserialize messages. I don't believe theres any javascript representations of bincode unfortunately.

I'm not sure if you are related to this crate but someone else has a fork that supports json (Though they also have a fork of eventwork since eventwork internally sends/receives with bincode as well). json fork.

I'll try and look at it over the weekend and see if theres a way to allow the NetworkProvider trait and Eventwork to use user supplied/or default serialization methods but I'm pretty out of my depth with serialization so I can't promise anything.

NoahShomette commented 3 months ago

I had some time and threw together an incredibly hacky patch to both crates to support different serialization methods. It's proof of concept more than anything else rn but can you go ahead and see if it works for you?

You'll need to implement the new bevy_eventwork NetworkSerializer trait for a new JsonSerializer. Then you'll have to use that JsonSerializer as a generic in your eventwork plugin and listen_for_messages.

Let me know if this works and I'll try and figure out a better way to support this

Patches

Eventwork branch BEMW Branch

davi4046 commented 3 months ago

The link to the BEMW branch is incorrect.

It's missing an 'n' in 'serialization' ;-)

Corrected: https://github.com/NoahShomette/bevy_eventwork_mod_websockets/tree/dynamic_serialization

But awesome support👍 I'm going to test if it works now

davi4046 commented 3 months ago

I couldn't compile when switching to the new branches because the BEMW branch doesn't reference the new bevy_eventwork branch. See my pull request: https://github.com/NoahShomette/bevy_eventwork_mod_websockets/pull/3

Once that is fixed, I will try again and share my results.

NoahShomette commented 3 months ago

I couldn't compile when switching to the new branches because the BEMW branch doesn't reference the new bevy_eventwork branch. See my pull request: https://github.com/NoahShomette/bevy_eventwork_mod_websockets/pull/3

Once that is fixed, I will try again and share my results.

Oops. I went ahead and merged your PR. See if that works now?

davi4046 commented 3 months ago

Okay, I've implemented the same server-client logic as I had before but with the new JSON serializer.

I still have unexpected behaviour where the client gets disconnected when trying to send a message (and the message doesn't get received, it appears).

Try to have a look at this repo: https://github.com/davi4046/bevy_eventwork_websocket_json_demo

NoahShomette commented 3 months ago

Okay, I've implemented the same server-client logic as I had before but with the new JSON serializer.

I still have unexpected behaviour where the client gets disconnected when trying to send a message (and the message doesn't get received, it appears).

Try to have a look at this repo: https://github.com/davi4046/bevy_eventwork_websocket_json_demo

So I spent all day looking into this. I'm really not entirely sure what's going on but I've got ideas based on what I looked at.

I think it's two things.

  1. Your message still isn't the expected format. BEMW expects bytes and doesn't support strings which is causing the message to bounce when you send just a straight string through js which is also causing the client to disconnect (actually the clients not even disconnecting but the listen loop on the servers ending so that's something that needs to be fixed). I sent blobs/bytearrays and the messages made it through but still had issues which is the second part.

  2. I think there's something funky that's going on with the JavaScript websocket that's causing it to mess up the bytes and then it's not working. Some type of masking or something maybe. As far as I can tell the content of the messages are the some but the byte representation is different and I think that's freaking out BEMW and I'm not sure why/what to do with that. It might be something BEMW can do to work with it/unmask it or maybe there's a way to disable it but im not really sure at this point.

I'm gonna keep looking at this but wanted to update you with what I'd found


I forked your project and made some changes. Using those changes the message goes through buuut it's "too big" so it's discarded still.

Also I used wireshark to investigate the actual messages sent back and forth. If you are looking into it maybe try that too.

NoahShomette commented 3 months ago

@davi4046 Great news! I figured out the problems and made some very very slight adjustments to BEMW and now your project works! Use the most recent branches of dynamic_serialization for BEMW and my fork of your demo and it just works.

The crux was that BEMW was expecting messages to be preceeded by a u64 that signified the upcoming messages length. Removing that requirement works fine by my testing and with a properly byte-ified message from JS it works perfectly. I had just copied that requirement over from the TCP version without double checking and I don't believe its necessary but I could be proven wrong so let me know if you run into issues with it.

Please give it a check and let me know if it works for you! I'm still running some tests to try and make serialization less generic heavy for Bevy_eventwork so I wouldn't expect any public crate releases soon but its on my agenda if I can figure it out so hopefully the branches will work for you in the meantime. I wont touch them so they should be safe.

I'll keep this issue up until I merge a fix properly and just ping me if you have any further issues. Thanks for working with me through this!

davi4046 commented 3 months ago

Amazing! It looks to be working on my machine as well. This is truly a game changer (pun intended).

I will of course let you know if I encounter any issues.

Thank you for this awesome library and the support you're providing!