netcode/lib.rs
1//! # netcode
2//!
3//! The `netcode` crate implements the [netcode](https://github.com/networkprotocol/netcode)
4//! network protocol created by [Glenn Fiedler](https://gafferongames.com).
5//!
6//! `netcode` is a UDP-based protocol that provides secure, connection-based data transfer.
7//!
8//! Since the protocol is meant to be used to implement multiplayer games, its API is designed
9//! to be used in a game loop, where the server and client are updated at a fixed rate (e.g., 60Hz).
10//!
11//! ## Protocol
12//!
13//! The three main components of the netcode protocol are:
14//! * Dedicated [`Servers`](Server).
15//! * [`Clients`](Client).
16//! * The web backend - a service that authenticates clients and generates [`ConnectTokens`](ConnectToken).
17//!
18//! The protocol does not specify how the web backend should be implemented, but it should probably be a typical HTTPS server
19//! that provides a means for clients to authenticate and request connection tokens.
20//!
21//! The sequence of operations for a client to connect to a server is as follows:
22//!
23//! 1. The `Client` authenticates with the web backend service. (e.g., by OAuth or some other means)
24//! 2. The authenticated `Client` requests a connection token from the web backend.
25//! 3. The web backend generates a [`ConnectToken`] and sends it to the `Client`. (e.g., as a JSON response)
26//! 4. The `Client` uses the token to connect to a dedicated `Server`.
27//! 5. The `Server` makes sure the token is valid and allows the `Client` to connect.
28//! 6. The `Client` and `Server` can now exchange encrypted and signed UDP packets.
29//!
30//! To learn more about the netcode protocol, see the upstream [specification](https://github.com/networkprotocol/netcode/blob/master/STANDARD.md).
31//!
32//! ## Server
33//!
34//! The netcode server is responsible for managing the state of the clients and sending/receiving packets.
35//!
36//! The server should run as a part of the game loop, process incoming packets and send updates to the clients.
37//!
38//! To create a server:
39//! * Provide the address you intend to bind to.
40//! * Provide the protocol id - a `u64` that uniquely identifies your app.
41//! * Provide a private key - a `u8` array of length 32. If you don't have one, you can generate one with `netcode::generate_key()`.
42//! * Optionally provide a [`ServerConfig`] - a struct that allows you to customize the server's behavior.
43//!
44//! ```
45//! use std::{thread, time::{Instant, Duration}};
46//! use netcode::{Server, MAX_PACKET_SIZE};
47//!
48//! // Create a server
49//! let protocol_id = 0x11223344;
50//! let private_key = netcode::generate_key(); // you can also provide your own key
51//! let mut server = Server::new("127.0.0.1:12345", protocol_id, private_key).unwrap();
52//!
53//! // Run the server at 60Hz
54//! let start = Instant::now();
55//! let tick_rate = Duration::from_secs_f64(1.0 / 60.0);
56//! loop {
57//! let elapsed = start.elapsed().as_secs_f64();
58//! server.update(elapsed);
59//! while let Some((packet, from)) = server.recv() {
60//! // ...
61//! }
62//! # break;
63//! thread::sleep(tick_rate);
64//! }
65//! ```
66//!
67//! ## Client
68//!
69//! The netcode client connects to the server and communicates using the same protocol.
70//!
71//! Like the server, the game client should run in a loop to process incoming data,
72//! send updates to the server, and maintain a stable connection.
73//!
74//! To create a client:
75//! * Provide a **connect token** - a `u8` array of length 2048 serialized from a [`ConnectToken`].
76//! * Optionally provide a [`ClientConfig`] - a struct that allows you to customize the client's behavior.
77//!
78//! ```
79//! use std::{thread, time::{Instant, Duration}};
80//! use netcode::{ConnectToken, Client, MAX_PACKET_SIZE};
81//!
82//! // Generate a connection token for the client
83//! let protocol_id = 0x11223344;
84//! let private_key = netcode::generate_key(); // you can also provide your own key
85//! let client_id = 123u64; // globally unique identifier for an authenticated client
86//! let server_address = "127.0.0.1:12345"; // the server's public address (can also be multiple addresses)
87//! let connect_token = ConnectToken::build("127.0.0.1:12345", protocol_id, client_id, private_key)
88//! .generate()
89//! .unwrap();
90//!
91//! // Start the client
92//! let token_bytes = connect_token.try_into_bytes().unwrap();
93//! let mut client = Client::new(&token_bytes).unwrap();
94//! client.connect();
95//!
96//! // Run the client at 60Hz
97//! let start = Instant::now();
98//! let tick_rate = Duration::from_secs_f64(1.0 / 60.0);
99//! loop {
100//! let elapsed = start.elapsed().as_secs_f64();
101//! client.try_update(elapsed).ok();
102//! if let Some(packet) = client.recv() {
103//! // ...
104//! }
105//! # break;
106//! thread::sleep(tick_rate);
107//! }
108//! ```
109
110mod bytes;
111mod client;
112mod crypto;
113mod error;
114mod free_list;
115mod packet;
116mod replay;
117mod server;
118mod socket;
119mod token;
120mod transceiver;
121
122#[cfg(test)]
123mod simulator;
124
125pub(crate) const MAC_BYTES: usize = 16;
126pub(crate) const MAX_PKT_BUF_SIZE: usize = 1300;
127pub(crate) const CONNECTION_TIMEOUT_SEC: i32 = 15;
128pub(crate) const PACKET_SEND_RATE_SEC: f64 = 1.0 / 10.0;
129
130pub use crate::client::{Client, ClientConfig, ClientState};
131pub use crate::crypto::{generate_key, try_generate_key, Key};
132pub use crate::error::{Error, Result};
133pub use crate::server::{ClientId, ClientIndex, Server, ServerConfig};
134pub use crate::socket::NetcodeSocket;
135pub use crate::token::{ConnectToken, ConnectTokenBuilder, InvalidTokenError};
136pub use crate::transceiver::Transceiver;
137
138/// The size of a private key in bytes.
139pub const PRIVATE_KEY_BYTES: usize = 32;
140/// The size of the user data in a connect token in bytes.
141pub const USER_DATA_BYTES: usize = 256;
142/// The size of the connect token in bytes.
143pub const CONNECT_TOKEN_BYTES: usize = 2048;
144/// The maximum size of a packet in bytes.
145pub const MAX_PACKET_SIZE: usize = 1200;
146/// The version of the netcode protocol implemented by this crate.
147pub const NETCODE_VERSION: &[u8; 13] = b"NETCODE 1.02\0";