Skip to content

Commit

Permalink
Merge pull request #169 from cBournhonesque/cb/multi-transport
Browse files Browse the repository at this point in the history
Enable using multiple concurrent ServerConnections
  • Loading branch information
cBournhonesque committed Mar 12, 2024
2 parents 80fa6ee + 18cc5fd commit 28a18db
Show file tree
Hide file tree
Showing 80 changed files with 2,967 additions and 1,876 deletions.
788 changes: 443 additions & 345 deletions NOTES.md

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions benches/src/local_stepper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,10 +149,10 @@ impl LocalBevyStepper {
.with_key(private_key);
let config = ServerConfig {
shared: shared_config.clone(),
net: server::NetConfig::Netcode {
net: vec![server::NetConfig::Netcode {
config: netcode_config,
io: server_io,
},
}],
..default()
};
let plugin_config = server::PluginConfig::new(config, protocol());
Expand Down
4 changes: 2 additions & 2 deletions benches/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ pub fn bevy_setup(app: &mut App, addr: SocketAddr, protocol_id: u64, private_key
tick: TickConfig::new(Duration::from_millis(10)),
..default()
},
net: NetConfig::Netcode {
net: vec![NetConfig::Netcode {
config: NetcodeConfig::default()
.with_protocol_id(protocol_id)
.with_key(private_key),
io: IoConfig::from_transport(TransportConfig::UdpSocket(addr)),
},
}],
..default()
};
let plugin_config = PluginConfig::new(config, protocol());
Expand Down
11 changes: 7 additions & 4 deletions benches/src/stepper.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use lightyear::prelude::client::{
PredictionConfig, SyncConfig,
};
use lightyear::prelude::server::{
NetConfig, NetServer, NetcodeConfig, ServerConfig, ServerConnection,
NetConfig, NetServer, NetcodeConfig, ServerConfig, ServerConnection, ServerConnections,
};
use lightyear::prelude::*;
use lightyear::server as lightyear_server;
Expand Down Expand Up @@ -68,18 +68,21 @@ impl BevyStepper {
.with_key(private_key);
let config = ServerConfig {
shared: shared_config.clone(),
net: NetConfig::Netcode {
net: vec![NetConfig::Netcode {
config: netcode_config,
io: IoConfig::from_transport(TransportConfig::UdpSocket(local_addr)),
},
}],
..default()
};
let plugin_config = server::PluginConfig::new(config, protocol());
let plugin = server::ServerPlugin::new(plugin_config);
server_app.add_plugins(plugin);
let server_addr = server_app
.world
.resource::<ServerConnection>()
.resource::<ServerConnections>()
.servers
.first()
.unwrap()
.io()
.local_addr();

Expand Down
1 change: 1 addition & 0 deletions book/src/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
- [Serialization](./concepts/transport/serialization.md)
- [Packet](./concepts/transport/packet.md)
- [Connection](./concepts/connection/title.md)
- [Multi Connection](./concepts/connection/multi_connection.md)
- [Reliability](./concepts/reliability/title.md)
- [PacketHeader](./concepts/reliability/packet_header.md)
- [Channels](./concepts/reliability/channels.md)
Expand Down
22 changes: 22 additions & 0 deletions book/src/concepts/connection/multi_connection.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Multi connection


In lightyear, the server can handle multiple connection protocol as the same time.
This means that the server could:
- open a port to establish steam socket connections
- open another port for UDP connections
- open another port for WebTransport connections
- etc.

and have all these connections running at the same time.

You can therefore have cross-play between different platforms.

Another potential usage is to have a "ListenServer" setup where a client acts as the "host":
- the Client and the Server run in the same process
- the Server has multiple connection protocols:
- one is based on local channels to talk to the Client that is running in the same process
- the other could be for example a UDP connection to allow other clients to connect to the server


To achieve this, you can just provide multiple `NetConfig` when creating the `ServerConfig` that will be used to create the server.
40 changes: 26 additions & 14 deletions book/src/concepts/connection/title.md
Original file line number Diff line number Diff line change
@@ -1,23 +1,35 @@
# Netcode

# Connection

## Introduction

I use the term 'netcode' to refer to code that creates an abstraction of a connection between two peers.

Our transport layer only allows us to send/receive raw packets to a remote address.
We want to be able to create a 'connection', which means:
- sending some handshake packets
- sending some keep-alive packets to check that the confirmation is still open
- performing authentication
But we want to be able to create a stateful 'connection' where we know that two peers are connected.

To establish that connection, that needs to be some machinery that runs on top of the transport layer and takes care of:
- sending handshake packets to authenticate the connection
- sending keep-alive packets to check that the connection is still open
- storing the list of connected remote peers
- etc.

In lightyear, it is possible to use different connection types, via the two traits
`NetClient` and `NetServer`.

Multiple implementations are provided:
- Netcode
- Steam

I call this 'netcode' because I am using the [netcode.io](https://github.com/networkprotocol/netcode/blob/master/STANDARD.md) standard created
by Glenn Fiedler (of GafferOnGames fame).

## Netcode

This implementation is based on the [netcode.io](https://github.com/networkprotocol/netcode/blob/master/STANDARD.md) standard created
by Glenn Fiedler (of GafferOnGames fame). It describes a protocol to establish a secure connection between two peers, provided
that there is a transport layer to exchange packets.

For my purpose I am using [this](https://github.com/benny-n/netcode) Rust implementation of the standard.

The standard provides:
- authentication
- encryption
- etc.
You can use the Netcode connection by using the `NetcodeClient` and `NetcodeServer` structs, coupled with any of the available
transports (Udp, WebTransport, etc.)

## Steam

This implementation is based on the Steamworks SDK.
20 changes: 1 addition & 19 deletions book/src/concepts/reliability/channels.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,4 @@ Ordering:

## Direction

The `direction` field can be used to restrict a `Channel` from sending packets from client->server or server->client.

## Priority (TODO)

In case the total bandwidth is limited, you can use the `priority` field to define which channels should be prioritized over others.
Lightyear uses a priority with accumulation scheme:
- Each channel has a priority accumulation value
- Every frame, we try to send as many packets as possible, starting with the highest priority channel (ties are broken randomly)
- If we can't send messages through a channel (because the bandwidth is full), we accumulate the priority value of the channel.
- If we can send messages through a channel, we reset the priority accumulation value to the starting value.

For example, we have channel A with priority 10, and channel B with priority 1; and we only have enough bandwidth to send 1 packet per frame.
- Frame 1: channel A has priority 10, channel B has priority 1. We send a packet through channel A, and reset its priority to 10. We update the priority of channel B to 2.
- Frame 2: channel A has priority 10, channel B has priority 2. We send a packet through channel A, and reset its priority to 10. We update the priority of channel B to 3.
- ...
- Frame 11: channel A has priority 10, channel B has priority 11. We send a packet through channel B, and reset its priority to 1. We update the priority of channel A to 20.


To limit the bandwidth, compute the amount of bytes sent in the last X seconds?
The `direction` field can be used to restrict a `Channel` from sending packets from client->server or server->client.
7 changes: 1 addition & 6 deletions book/src/concepts/reliability/title.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,10 @@

In this layer we add some mechanisms to be able to send and receive messages reliably or in a given order.

It is similar to the [reliable](https://github.com/networkprotocol/reliable) layer created by Glenn Fiedler on top of his
netcode.io code.
It is similar to the [reliable](https://github.com/networkprotocol/reliable) layer created by Glenn Fiedler on top of his netcode.io code.

This layer introduces:
- reliability: make sure a packets is received by the remote peer
- ordering: make sure packets are received in the same order they were sent
- channels: allow to send packets on different channels, which can have different reliability and ordering guarantees
-

## Concepts

-
2 changes: 1 addition & 1 deletion book/src/concepts/title.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
There are several layers that enable lightyear to act as a games networking library.
Let's list them from the bottom up (closer to the wire):
- transport: how do you send/receive unreliable-unordered packets on the network (UDP, QUIC, etc.)
- netcode: abstraction of a connection between two peers
- connection: abstraction of a stateful connection between two peers
- channels/reliability: how do you add ordering and reliability to packets
- replication: how do you replicate components between the client and server
- advanced replication: prediction, interpolation, etc.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[build]
#target = "wasm32-unknown-unknown"
#target = "aarch64-apple-darwin"
# it is a good idea to specify your target here, to avoid losing incremental compilation when compiling to wasm
# target = "aarch64-apple-darwin"
rustflags = ["--cfg", "web_sys_unstable_apis"]

[target.wasm32-unknown-unknown]
Expand Down
1 change: 1 addition & 0 deletions examples/bullet_prespawn/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,4 @@ mock_instant = "0.3"
metrics-exporter-prometheus = { version = "0.13.0", optional = true }
bevy-inspector-egui = "0.23"
cfg-if = "1.0.0"
ron = "0.8.1"
37 changes: 37 additions & 0 deletions examples/bullet_prespawn/assets/settings.ron
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
Settings(
client: ClientSettings(
inspector: true,
client_id: 0,
client_port: 0, // the OS will assign a random open port
server_addr: "127.0.0.1",
server_port: 5000,
transport: WebTransport(
// this is only needed for wasm, the self-signed certificates are only valid for 2 weeks
// the server will print the certificate digest on startup
certificate_digest: "1fd28860bd2010067cee636a64bcbb492142295b297fd8c480e604b70ce4d644",
),
// server_port: 5001,
// transport: Udp,
// server_port: 5002,
// transport: WebSocket,
),
server: ServerSettings(
headless: true,
inspector: false,
transport: [
WebTransport(
local_port: 5000
),
Udp(
local_port: 5001
),
WebSocket(
local_port: 5002
)
],
),
shared: SharedSettings(
protocol_id: 0,
private_key: (0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0),
)
)
Loading

0 comments on commit 28a18db

Please sign in to comment.