acmcarther / gaffer_udp

Half baked network protocol in Rust based on http://gafferongames.com/networking-for-game-programmers/reliability-and-flow-control/
8 stars 0 forks source link

Question about stablility... #10

Closed TimonPost closed 5 years ago

TimonPost commented 6 years ago

You state that this is not ready for the public. why is that and what needs to be done before it is? Is this because of the congestion avoidance?

acmcarther commented 6 years ago

The crate was tested and appeared to work well in a local context (example gifs here: https://github.com/acmcarther/space_coop/pull/17) but I can't recommend holding out hope for this crate. Its a partial implementation of a protocol I didn't design myself and probably wont ever finish the implementation of. Such a "finished" state would have to include proper flow control and a more rigorous performance analysis at the very least.

Instead, I'd recommend wrapping the C libraries authored by Glenn Fiedler himself: netcode.io and reliable.io.

I've done some of that work myself privately, but I use my own versions of basically everything, so it wouldn't be directly portable: https://github.com/acmcarther/void/blob/master/core/net/low/netcode_api.rs. I might be up to help out if there's a centralized effort for this though.

TimonPost commented 6 years ago

Thanks for the reaction! I'll look into implementing congestion avoidence.

I want to try implementing this crate or use code from it for the amethyst game engine written in rust. There is need for a game network implementation.

When I read gaffer docs I wanted to implement it in rust, that's where I ended up here actualdentily here.

So I'll give it a try your crate and see if I can make it work with the missing parts. I'll better use rust than C.

Yea cool your help would be appreciated if you want to! Do you have discord or something would be helpful if I could for if i have some questions ?

acmcarther commented 6 years ago

OK, I think I understand what you're after. I can understand wanting to avoid C code where possible. That said, I mentally view this as a problem where "robustness of implementation" is the goal. There are two "viable" approaches as I see it: you either need patience in the form of bringing in and wrapping an already robust implementation, or tenacity enough to understand the protocol and re-implement it in Rust, most notably without it having terrible performance characteristics due to overzealous clones. This may mean unsafe code.

I don't have my own Discord, but I'd be open to joining any existing Rust / Amethyst Discords so that we could discuss this on a higher bandwidth medium.

Some details on what this library does and does not accomplish follows


To best approach a Rust implementation of the "gaffer" protocol. you'll want to be familiar with what it's trying to accomplish. Layer-by-layer, this includes:

1) Implementation of a "connection" state. Since UDP is connectionless on its own, this means "scripting" a series of send+recv messages that act as a "handshake" for a connection. This also (usually) involves directing the client to communicate on a separate port from the connection port. All told, this requires some bookkeeping so that the "server" end can tell which packets on which connections correspond to which client, and it requires some due diligence in making sure that packet origin spoofing isn't easy. For the record, this library doesn't perform very robust connection management instead just treating the origin data in the packet as the connection identifier: https://github.com/acmcarther/gaffer_udp/blob/5a8f994d59a177f1b269b063a1b33183f0e09d3d/src/socket/mod.rs#L26

Glenn's implementation performs actual tokenized authentication, and encrypts payloads using a client specific key.

2) Packet fragmentation + reassembly. Users will want to be able to transmit data larger than the so called "maximum transmission unit" of the connection channel. In this implementation, the user must pre-split their packets and perform their own sequencing to guarantee reassembly at the other side. You can see what that looks like from a user perspective in the following code:

https://github.com/acmcarther/space_coop/blob/59186cd806f04ae1a53070dd1ab283a2a5054e7c/prototype2/common/src/protocol.rs#L27-L40

https://github.com/acmcarther/space_coop/blob/59186cd806f04ae1a53070dd1ab283a2a5054e7c/prototype2/server/core/server_network/src/lib.rs#L28-L53

3) Reliability Part of the point of a network protocol is to give users a degree of assurance that packets that are sent will arrive (even if they have to be retransmitted). Glenn's protocol doesn't have very strong guarantees to this effect and basically dumps ordering guarantees. I think this library's implementation of that (see "ack" related code) is pretty solid and can be worked forward from.

4) Flow control A network protocol needs to behave correctly when the underlying channel is lossy or saturated. This means that it has to detect a state of network saturation, then either apply backpressure to callers (by blocking, or something) or it needs to queue payloads. This implementation does not address this issue and may saturate a connection and devolve into a unrecoverable bad state.

5) Bonus: Payload serialization protocol I would be remiss to miss that users should generally be guided into using a ser/de protocol that is denser than plain old json. I suggest protobuf, but any binary encoding protocol would work. This does mean going off the traditional web-development oriented approaches that the Rust ecosystem tends toward (I'm referring to serde here).

TimonPost commented 6 years ago

Sorry for the late reaction! Thanks for your detailed reaction, you can join Discord here if you want.

TimonPost commented 5 years ago

Thanks for the help we have released our reliable UDP crate. You can look here if you are interested.