renet icon indicating copy to clipboard operation
renet copied to clipboard

Add Client and Server Transport Layers based on WebTransport

Open TrustNoOneElse opened this issue 1 year ago • 12 comments

Overview

This pull request introduces two transport layers, one for the client and one for the server, built on top of the WebTransport API. These transport layers enable efficient and reliable communication between clients and servers over the web. Additionally, we provide a comprehensive example to showcase their usage.

Todos

  • [x] Server Transport working (with h3 or wTransport)
  • [x] Client Transport working
  • [x] Light Chat Example
  • [x] Documentation

Additional Notes

We could add as an optional Feature that the Client Webtransport runs in a Webworker. Since im not from the users which often implement games for browsers, im not sure how much sense it would make. Also since the concept is mostly pulling data from the update method which is called trough user code.

Happy for every feedback.

TrustNoOneElse avatar Sep 07 '23 17:09 TrustNoOneElse

Having some certs problem at the moment, 46 certificate unknown a tls handshake problem. Not really sure what broke or what i missed, because last week it was working xD So if anyone knows what could be wrong with the cert generation on the server side, i would be grateful. I will try this go tool for generating the cert later, maybe that will help. But yeah thats why there is currently no progress

TrustNoOneElse avatar Sep 20 '23 17:09 TrustNoOneElse

Finally good news, i got the local certs working again. But chrome somehow is dead on my system (it doesn't accept anymore flags or trusted certs), so i will instead modify the readme, to support firefox for windows. I hope thats okay for everyone, i will link a Linux version from a different repo for chrome.

TrustNoOneElse avatar Sep 23 '23 12:09 TrustNoOneElse

image Another good update, i finally managed, to have a non blocking client running, which can now send data to the server! And also recieve! image Now i just need make the server also non blocking when its reading the datagram stream. Afterwards i can develop further the example and finally make clippy/format things and look other things up :D

TrustNoOneElse avatar Sep 30 '23 12:09 TrustNoOneElse

Okay i tested a bit more and the write on the client side is also blocking when the server was shutdown forcefully. So i need to move this also to worker, i taking this back to draft until resolved

TrustNoOneElse avatar Oct 02 '23 16:10 TrustNoOneElse

We could add as an optional Feature that the Client Webtransport runs in a Webworker. Since im not from the users which often implement games for browsers, im not sure how much sense it would make. Also since the concept is mostly pulling data from the update method which is called trough user code.

Have you done any benchmarks comparing web workers vs wasm bindgen futures? Web workers have a lot of overhead, so I'm not sure they are performant for a mainly IO use-case like this.

UkoeHB avatar Oct 07 '23 21:10 UkoeHB

Have you done any benchmarks comparing web workers vs wasm bindgen futures? Web workers have a lot of overhead, so I'm not sure they are performant for a mainly IO use-case like this.

I didn't find a way which would be able to handle the read outside of the web worker. The main problem was, that the await(JsFuture into Rust async) would hold the wasm ptr for as long as no message is there. This would mean that every next usage of the app would then throw with recursive use and the app would no longer be usable.

For the writing part i didn't test it further with worker, i had one running example but for the simple use case of a chat app it was hard to tell the difference and i wanted to avoid to give the worker more load by also writing and so maybe delay the reading depending on the load.

TrustNoOneElse avatar Oct 07 '23 21:10 TrustNoOneElse

Hi! Very nice work, hoping to see it merged soon! I spotted a consistent spelling mistake: receive should be spelled like so (and not recieve). I hope this is not bad tone to mention it here.

5tr1k3r avatar Oct 13 '23 16:10 5tr1k3r

I'm sorry, I must have worded things poorly. I suggested the correct spelling now.

ah thanks, i guess my brain autocompleted the sentence and filtered out "and not" lol, thanks for the suggestions :D!

TrustNoOneElse avatar Oct 13 '23 19:10 TrustNoOneElse

Another review from me.

I now see two important issues with this PR.

  • Client ids are defined from an internal iterator. This means a server cannot directly map a pre-defined client list onto new connections (you would need a bespoke handshake after connecting to establish the client id mapping, which would be full of security challenges). With the netcode transport, client ids are assigned by the server when creating ConnectTokens, which allows the server to map 'internal user ids' onto 'renet client ids' up front. It also means the server doesn't have to re-map clients after a reconnect.
  • It seems that any client can connect to a server. Implementers must add a bespoke handshake on top of renet to validate new connections, which goes against the API expectation that you can safely send messages to clients once they are connected.

Both of these problems could be addressed by adopting the netcode ConnectToken workflow. Servers should issue WtConnectToken to clients. Then, the server should expect a valid WtConnectToken from connection requests, and should affiliate the client id embedded in that token with sent/received packets.

As a first-pass/proof-of-concept I would directly port ConnectToken logic into this PR, and then we can think about refinement. A big problem I have with the netcode protocol is it doesn't support reusing a ConnectToken for reconnects - the server needs to reissue tokens every time. It would be super nice to A) update the netcode protocol to enable token reuse (this is a project for me), B) for this webtransport PR to enable token reuse out of the box. EDIT: on further reflection, there are no good solutions for reconnects so I don't think the netcode protocol can be improved in this area.

Okay after a lot of reading i get what this is about. Im not sure how complex it will be to get this mechanism into this. Thanks for the finding and i can understand the concern that it is not secure enough.

TrustNoOneElse avatar Dec 15 '23 21:12 TrustNoOneElse

Im not sure how complex it will be to get this mechanism into this.

I would look for the lowest common denominator between renetcode and webtransport, then port all the renetcode logic on top of webtransport. Renetcode has a lot of connection management logic that is quite useful for games.

It's possible that renetcode could be refactored into two crates: the netcode protocol pieces, and the integration with UDP sockets. Then the netcode protocol piece can be reused for the webtransport implementation. I haven't looked deeply into this, so I don't fully understand how much webtransport differs from UDP, or how much of the netcode protocol is not needed when using webtransport.

UkoeHB avatar Dec 15 '23 21:12 UkoeHB

I would look for the lowest common denominator between renetcode and webtransport, then port all the renetcode logic on top of webtransport. Renetcode has a lot of connection management logic that is quite useful for games.

i will try my best, thanks for the tips! I guess we could refactor the token out like you say, @lucaspoffo, do you have any preferences on that?

TrustNoOneElse avatar Dec 16 '23 13:12 TrustNoOneElse

@TrustNoOneElse The issues I mentioned would be fixed by migrating your implementation to use the TransportSocket trait from #145, which should be very easy. Let's hope poffo merges that.

UkoeHB avatar Feb 04 '24 05:02 UkoeHB

@TrustNoOneElse can you give more detailed instructions for running the client example? I am having a lot of pain trying to run it. You reference ../pkg in package.json but idk what's supposed to be in there.

UkoeHB avatar Apr 08 '24 21:04 UkoeHB

@TrustNoOneElse can you give more detailed instructions for running the client example? I am having a lot of pain trying to run it. You reference ../pkg in package.json but idk what's supposed to be in there.

Was answered on discord, but for everyone else wondering you need to build the example rust library with "wasm-pack build" :)

TrustNoOneElse avatar Apr 09 '24 19:04 TrustNoOneElse

This is now implemented in renet2, using this PR as a base.

UkoeHB avatar Apr 20 '24 00:04 UkoeHB

Thanks @UkoeHB with that there is no reason to hold this PR any longer open :)

TrustNoOneElse avatar Apr 20 '24 09:04 TrustNoOneElse