rak_rs/protocol/packet/
online.rs

1//! Online packets are packets that are sent when the client is connected to the server
2//! and are used to keep the connection alive, and to send game packets to the server.
3//!
4//! The following module provides the following packets:
5//! - [`ConnectedPing`]
6//! - [`ConnectedPong`]
7//! - [`LostConnection`]
8//! - [`ConnectionRequest`]
9//! - [`ConnectionAccept`]
10//! - [`NewConnection`]
11//! - [`Disconnect`]
12//!
13//! During this stage, the client and server are exchanging information about each other,
14//! to initialize the connection within raknet, and completing the connection handshake.
15use std::net::SocketAddr;
16
17use super::RakPacket;
18use crate::register_packets;
19
20use binary_util::interfaces::{Reader, Writer};
21use binary_util::io::{ByteReader, ByteWriter};
22use binary_util::BinaryIo;
23
24/// An enum of all Online packets.
25///
26/// You can use this to read and write online packets,
27/// with the `binary_util` traits `Reader` and `Writer`.
28#[derive(BinaryIo, Clone, Debug)]
29#[repr(u8)]
30pub enum OnlinePacket {
31    ConnectedPing(ConnectedPing) = 0x00,
32    ConnectedPong(ConnectedPong) = 0x03,
33    LostConnection(LostConnection) = 0x04,
34    ConnectionRequest(ConnectionRequest) = 0x09,
35    ConnectionAccept(ConnectionAccept) = 0x10,
36    NewConnection(NewConnection) = 0x13,
37    Disconnect(Disconnect) = 0x15,
38}
39
40register_packets! {
41    Online is OnlinePacket,
42    ConnectedPing,
43    ConnectedPong,
44    LostConnection,
45    ConnectionRequest,
46    ConnectionAccept,
47    NewConnection,
48    Disconnect
49}
50
51/// This packet is sent by either the client or the server to the other peer.
52/// The other peer should respond with a [`ConnectedPong`] packet. In general
53/// you should be sending this packet every 5 seconds to keep the connection alive.
54/// <br />
55/// <br />
56/// If you do not continue to send this packet, the connection will be closed after
57/// the other peer does not receive a [`ConnectedPong`] packet for the configured timeout option.
58#[derive(Clone, Debug, BinaryIo)]
59pub struct ConnectedPing {
60    /// The time you sent the packet to the peer.
61    pub time: i64,
62}
63
64/// Sent in response to a [`ConnectedPing`] packet.
65///
66/// This packet is sent by the other peer in response to a [`ConnectedPing`] packet as
67/// an acknowledgement that the connection is still alive. It contains the time of the
68/// round trip from the time that the initiator sent the [`ConnectedPing`] packet.
69#[derive(Clone, Debug, BinaryIo)]
70pub struct ConnectedPong {
71    /// The time that the peer sent the [`ConnectedPing`] packet.
72    pub ping_time: i64,
73    /// The time that you sent the [`ConnectedPong`] packet to the peer.
74    pub pong_time: i64,
75}
76
77/// A connection Request Request, this contains information about the client. Like it's
78/// current time and the client id.
79#[derive(Clone, Debug, BinaryIo)]
80pub struct ConnectionRequest {
81    pub client_id: i64,
82    pub time: i64,
83    pub security: bool,
84}
85
86/// A connection Accept packet, this is sent by the server to the client.
87/// This is sent by the server and contains information about the server.
88#[derive(Clone, Debug)]
89pub struct ConnectionAccept {
90    /// The address of the client connecting (locally?).
91    pub client_address: SocketAddr,
92    /// The system index of the server.
93    pub system_index: i16,
94    /// The internal id's of the server or alternative IP's of the server.
95    /// These are addresses the client will use if it can't connect to the server.
96    /// (Not sure why this is useful)
97    pub internal_ids: Vec<SocketAddr>,
98    /// The time of the timestamp the client sent with `ConnectionRequest`.
99    pub request_time: i64,
100    /// The time on the server.
101    pub timestamp: i64,
102}
103
104impl Reader<ConnectionAccept> for ConnectionAccept {
105    fn read(buf: &mut ByteReader) -> std::io::Result<Self> {
106        let client_address = buf.read_type::<SocketAddr>()?;
107
108        // read the system index, this is
109        let system_index = buf.read_i16()?;
110        let mut internal_ids = Vec::<SocketAddr>::new();
111
112        for _ in 0..20 {
113            // we only have the request time and timestamp left...
114            if buf.as_slice().len() <= 16 {
115                break;
116            }
117            internal_ids.push(buf.read_type::<SocketAddr>()?);
118        }
119
120        let request_time = buf.read_i64()?;
121        let timestamp = buf.read_i64()?;
122
123        Ok(Self {
124            client_address,
125            system_index,
126            internal_ids,
127            request_time,
128            timestamp,
129        })
130    }
131}
132
133impl Writer for ConnectionAccept {
134    fn write(&self, buf: &mut ByteWriter) -> std::io::Result<()> {
135        buf.write_type::<SocketAddr>(&self.client_address)?;
136        buf.write_i16(self.system_index)?;
137
138        if self.internal_ids.len() > 20 {
139            return Err(std::io::Error::new(
140                std::io::ErrorKind::InvalidInput,
141                "Too many internal id's",
142            ));
143        }
144
145        for internal_id in &self.internal_ids {
146            buf.write_type::<SocketAddr>(internal_id)?;
147        }
148
149        buf.write_i64(self.request_time)?;
150        buf.write_i64(self.timestamp)?;
151
152        Ok(())
153    }
154}
155
156/// Going to be completely Honest here, I have no idea what this is used for right now,
157/// even after reading the source code.
158#[derive(Clone, Debug)]
159pub struct NewConnection {
160    /// The external IP Address of the server.
161    pub server_address: SocketAddr,
162    /// The internal IP Address of the server.
163    pub system_address: Vec<SocketAddr>,
164    /// The time of the timestamp the client sent with `ConnectionRequest`.
165    pub request_time: i64,
166    /// The time on the server.
167    pub timestamp: i64,
168}
169
170impl Reader<NewConnection> for NewConnection {
171    fn read(buf: &mut ByteReader) -> std::io::Result<Self> {
172        let server_address = buf.read_type::<SocketAddr>()?;
173
174        let mut system_address = Vec::<SocketAddr>::new();
175
176        for _ in 0..20 {
177            // we only have the request time and timestamp left...
178            if buf.as_slice().len() < 16 {
179                break;
180            }
181            system_address.push(buf.read_type::<SocketAddr>()?);
182        }
183
184        let request_time = buf.read_i64()?;
185        let timestamp = buf.read_i64()?;
186
187        Ok(Self {
188            server_address,
189            system_address,
190            request_time,
191            timestamp,
192        })
193    }
194}
195
196impl Writer for NewConnection {
197    fn write(&self, buf: &mut ByteWriter) -> std::io::Result<()> {
198        buf.write_type::<SocketAddr>(&self.server_address)?;
199
200        if self.system_address.len() > 20 {
201            return Err(std::io::Error::new(
202                std::io::ErrorKind::InvalidInput,
203                "Too many internal id's",
204            ));
205        }
206
207        for system_address in &self.system_address {
208            buf.write_type::<SocketAddr>(system_address)?;
209        }
210
211        buf.write_i64(self.request_time)?;
212        buf.write_i64(self.timestamp)?;
213
214        Ok(())
215    }
216}
217
218/// A disconnect notification. Tells the client to disconnect.
219#[derive(Clone, Debug, BinaryIo)]
220pub struct Disconnect {}
221
222/// A connection lost notification.
223/// This is sent by the client when it loses connection to the server.
224#[derive(Clone, Debug, BinaryIo)]
225pub struct LostConnection {}