PocketRelay / Server

Mass Effect 3 Rust Server Emulator, LAN and WAN private server
https://pocket-relay.pages.dev/
MIT License
12 stars 4 forks source link

Task: Tunnel #64

Closed jacobtread closed 8 months ago

jacobtread commented 9 months ago

Description

This is the tracking issue for the new server tunneling solution, this new layout will help make the WAN connectivity for Pocket Relay more reliable by using the server as a relay for the game client traffic.

In the standard game the client networking is a peer-to-peer structure where one client acts a host (server) and all the other clients connect to that client sending their information there which the host then provides the required details to the other clients.

This new solution takes advantage of being able to change the game networking topology from "PeerHosted" to "Dedicated" using this when a player creates a game as far as their game client is aware they have become a server for clients to connect too, but any other clients who join the game will be told instead that the game is a dedicated server and that they should connect to a local port (42132) this local port is apart of a pool of ports that the game server can use to talk to the client.

When the other clients then try to talk to 42132 on localhost the client takes all of the messages and forwards them to the Pocket Relay server which then sends them to the appropriate host players computer which then uses a local socket from a pool of sockets to send that data to the host "server" allowing the server and clients to communicate just as if they were all running on the same computer, thus bypassing any NAT restrictions that would normally cause issues.

The local pool of sockets is used to identify where each message is supposed to be sent, the server keeps track of which slot the player is in within the game and maps each player to one of the locally spawned sockets.

Diagrams

Below are some diagrams showcasing the different approaches

Normal Diagram Here is a diagram of the way clients connect on the official server (And the current Pocket Relay setup pre tunneling): ![image](https://github.com/PocketRelay/Server/assets/33708767/076babe7-9b6d-4e35-b0c5-2f5fba2de1fa)
Tunneled Diagram Here is a diagram of the tunneled way of connecting: ![image](https://github.com/PocketRelay/Server/assets/33708767/a71792a1-aa85-4ba3-9cf4-62f1dbb674f0)

Checklist

jacobtread commented 8 months ago

Added documentation for new tunneling configuration variable: https://pocket-relay.pages.dev/docs/server/configuration/#tunnel

jacobtread commented 8 months ago

Tunnel Messages

Below is the message structure used by messages sent through the server tunnel

 0                   1                   2        
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|     Index     |            Length             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                                               :
:                    Payload                    :
:                                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Tunnel message frames contain the following fields:

Index: 8-bits. Determines the destination of the message within the current tunnel pool.

Length: 16-bits. Determines the size in bytes of the payload that follows

Payload: Variable length. The message bytes payload of Length in bytes

jacobtread commented 8 months ago

Currently, the tunnel system uses the client public IP address to associate the tunnels with their sessions upon game creation, however this won't be a permanent solution as multiple devices could share the same public IP and this requires that IP be determine accurately (Reverse proxies require setting up headers for forwarding).

My proposed system is a sort of "Association token" which would be a new server endpoint that the client could request (maybe "POST /server/associate" which would response with a unique token, allowing the clients to be associated by some unique token rather than IP address. The clients would then provide the association token both when connecting blaze sessions and creating tunnels so that the association can be made.

The token could be some server signed UUID or something of the sort (So that its unique and stateless but doesn't have to expire)

jacobtread commented 8 months ago

The new association tokens system has been implemented in the following commits: https://github.com/PocketRelay/Server/commit/79ad07df2251ce5bbc01eb92670e30b3ba583955 https://github.com/PocketRelay/PocketRelayClientShared/commit/bc53e2e9af42c8a39d443286bde20cc74cd50970 https://github.com/PocketRelay/Client/commit/b057ab01a38a5a843e4836c84caa10a959c33540 https://github.com/PocketRelay/PocketRelayClientPlugin/commit/34b0647f4574e9032f197f436ba80efb61ff8fd0 tunnel association no longer relies on IP addresses

jacobtread commented 8 months ago

Local testing between two clients (One in an isolated VM) through an ngrok proxy showed that the tunnel is working correctly and was playable, still waiting on further community testing with actual players before public release can be made available: image

jacobtread commented 8 months ago

For performance down the line it might be better to split group associations into their own pool collections with their own read/write lock so that inserting tunnels into the collection of pools doesn't block alll pool active connections from sending messages, in practice this probabbly isn't even noticeable since its only write locked for a two map insertions but worth looking into as a possible optimization.

jacobtread commented 8 months ago

For performance down the line it might be better to split group associations into their own pool collections with their own read/write lock rather than the so that inserting tunnels into the collection of pools doesn't block all pool active connections from sending messages, in practice this probabbly isn't even noticeable since its only write locked for two map insertions but worth looking into as a possible optimization.