1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
use core::fmt::Debug;
use crate::{
enet_packet_create, enet_packet_destroy, Box, ENetPacket, Vec, ENET_PACKET_FLAG_NO_ALLOCATE,
ENET_PACKET_FLAG_RELIABLE, ENET_PACKET_FLAG_SENT, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT,
ENET_PACKET_FLAG_UNSEQUENCED,
};
/// Types of packets supported by ENet, used with [`Packet::new`].
///
/// See [`Sequencing`](`crate#sequencing`).
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum PacketKind {
/// An unreliable packet, with optional sequencing. A sequenced unreliable packet will cause
/// unsequenced packets to simply be discarded if they were to be dispatched out of order.
///
/// Note that packets of this kind will be sent reliably if they are too large to fit within the
/// maximum transmission unit (MTU). To avoid this behavior, use
/// [`PacketKind::AlwaysUnreliable`] instead.
Unreliable {
/// Should the packets be sequenced? Packets received out of order will be discarded.
sequenced: bool,
},
/// An unreliable packet, with optional sequencing. Guaranteed to be unreliable, see
/// [`PacketKind::Unreliable`].
AlwaysUnreliable {
/// Should the packets be sequenced? Packets received out of order will be discarded.
sequenced: bool,
},
/// An reliable packet, with enforced sequencing.
///
/// See [`Reliability`](`crate#reliability`).
Reliable,
}
/// An ENet data packet that may be sent to or received from a peer.
///
/// See [`Fragmentation and Reassembly`](`crate#fragmentation-and-reassembly`).
///
/// For more information on the kinds of ENet packets, see [`PacketKind`].
pub struct Packet {
pub(crate) packet: *mut ENetPacket,
}
unsafe impl Send for Packet {}
unsafe impl Sync for Packet {}
impl Packet {
/// Create a new packet manually from its data and kind.
///
/// Some convenience methods exist that can be used instead:
/// - [`Packet::unreliable`]
/// - [`Packet::unreliable_unsequenced`]
/// - [`Packet::always_unreliable`]
/// - [`Packet::always_unreliable_unsequenced`]
/// - [`Packet::reliable`]
#[must_use]
pub fn new<P: ToRawPacket>(data: P, kind: PacketKind) -> Self {
let kind_flags = match kind {
PacketKind::Unreliable { sequenced: true } => 0,
PacketKind::Unreliable { sequenced: false } => ENET_PACKET_FLAG_UNSEQUENCED,
PacketKind::AlwaysUnreliable { sequenced: true } => {
ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT
}
PacketKind::AlwaysUnreliable { sequenced: false } => {
ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT | ENET_PACKET_FLAG_UNSEQUENCED
}
PacketKind::Reliable => ENET_PACKET_FLAG_RELIABLE,
};
let raw_packet = data.into_packet_data();
let packet = unsafe {
enet_packet_create(
raw_packet.data,
raw_packet.len,
kind_flags | ENET_PACKET_FLAG_NO_ALLOCATE,
)
};
unsafe {
(*packet).free_callback = Some(Self::drop_packet_data::<P>);
(*packet).user_data = raw_packet.user_data as *mut _;
(*packet).reference_count += 1;
}
Self { packet }
}
/// Create a new unreliable packet with
/// [`PacketKind::Unreliable { sequenced: true }`](`PacketKind::Unreliable`)
#[must_use]
pub fn unreliable(data: impl ToRawPacket) -> Self {
Self::new(data, PacketKind::Unreliable { sequenced: true })
}
/// Create a new unreliable packet with
/// [`PacketKind::Unreliable { sequenced: false }`](`PacketKind::Unreliable`)
#[must_use]
pub fn unreliable_unsequenced(data: impl ToRawPacket) -> Self {
Self::new(data, PacketKind::Unreliable { sequenced: false })
}
/// Create a new always unreliable packet with
/// [`PacketKind::AlwaysUnreliable { sequenced: true }`](`PacketKind::AlwaysUnreliable`)
#[must_use]
pub fn always_unreliable(data: impl ToRawPacket) -> Self {
Self::new(data, PacketKind::AlwaysUnreliable { sequenced: true })
}
/// Create a new always unreliable packet with
/// [`PacketKind::AlwaysUnreliable { sequenced: false }`](`PacketKind::AlwaysUnreliable`)
#[must_use]
pub fn always_unreliable_unsequenced(data: impl ToRawPacket) -> Self {
Self::new(data, PacketKind::AlwaysUnreliable { sequenced: false })
}
/// Create a new unreliable packet with [`PacketKind::Reliable`]
#[must_use]
pub fn reliable(data: impl ToRawPacket) -> Self {
Self::new(data, PacketKind::Reliable)
}
/// Get this packet's [`PacketKind`].
#[must_use]
pub fn kind(&self) -> PacketKind {
let flags = unsafe { (*self.packet).flags | !ENET_PACKET_FLAG_SENT };
let sequenced = flags & ENET_PACKET_FLAG_UNSEQUENCED == 0;
if flags & ENET_PACKET_FLAG_RELIABLE != 0 {
PacketKind::Reliable
} else if flags & ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT != 0 {
PacketKind::AlwaysUnreliable { sequenced }
} else {
PacketKind::Unreliable { sequenced }
}
}
/// Get the byte array contained in this packet.
#[must_use]
pub fn data(&self) -> &[u8] {
unsafe { super::from_raw_parts_or_empty((*self.packet).data, (*self.packet).data_length) }
}
pub(crate) fn new_from_ptr(packet: *mut ENetPacket) -> Self {
unsafe {
(*packet).reference_count += 1;
}
Self { packet }
}
unsafe fn drop_packet_data<P: ToRawPacket>(packet: *mut ENetPacket) {
P::drop_packet_data(RawPacket {
data: (*packet).data,
len: (*packet).data_length,
user_data: (*packet).user_data as usize,
});
}
}
impl Clone for Packet {
fn clone(&self) -> Self {
unsafe {
(*self.packet).reference_count += 1;
}
Self {
packet: self.packet,
}
}
}
impl Drop for Packet {
fn drop(&mut self) {
unsafe {
(*self.packet).reference_count -= 1;
if (*self.packet).reference_count == 0 {
enet_packet_destroy(self.packet);
}
}
}
}
impl Debug for Packet {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
let packet = unsafe { &(*self.packet) };
f.debug_struct("Packet")
.field("data", &packet.data)
.field("dataLength", &packet.data_length)
.field("flags", &packet.flags)
.field("kind", &self.kind())
.finish()
}
}
/// Denotes a byte buffer that can be wrapped in a [`Packet`].
pub trait ToRawPacket {
/// Takes ownership of this value and converts it into raw packet data.
fn into_packet_data(self) -> RawPacket;
/// Drops packet data that was previously created for this type.
///
/// # Safety
///
/// For this function call to be sound, `packet` must have been previously
/// created with [`Self::into_packet_data`].
unsafe fn drop_packet_data(packet: RawPacket);
}
impl ToRawPacket for &[u8] {
fn into_packet_data(self) -> RawPacket {
self.to_vec().into_packet_data()
}
unsafe fn drop_packet_data(packet: RawPacket) {
Vec::<u8>::drop_packet_data(packet);
}
}
impl ToRawPacket for Vec<u8> {
fn into_packet_data(mut self) -> RawPacket {
let data = self.as_mut_ptr();
let len = self.len();
let user_data = self.capacity();
core::mem::forget(self);
RawPacket {
data,
len,
user_data,
}
}
unsafe fn drop_packet_data(packet: RawPacket) {
Vec::from_raw_parts(packet.data, packet.len, packet.user_data);
}
}
impl ToRawPacket for Box<[u8]> {
fn into_packet_data(self) -> RawPacket {
let len = self.len();
let data = Box::into_raw(self).cast();
RawPacket {
data,
len,
user_data: 0,
}
}
unsafe fn drop_packet_data(packet: RawPacket) {
let _ = Box::from_raw(core::slice::from_raw_parts_mut(packet.data, packet.len));
}
}
impl<T: AsRef<[u8]> + Sized> ToRawPacket for Box<T> {
fn into_packet_data(self) -> RawPacket {
let slice = (*self).as_ref();
let data = slice.as_ptr().cast_mut();
let len = slice.len();
let user_data = Box::into_raw(self) as usize;
RawPacket {
data,
len,
user_data,
}
}
unsafe fn drop_packet_data(packet: RawPacket) {
let _ = Box::<T>::from_raw(packet.user_data as *mut _);
}
}
/// Describes a raw, Rust-owned packet object.
pub struct RawPacket {
/// The underlying data.
pub data: *mut u8,
/// The length of the data in bytes.
pub len: usize,
/// Extra data identifying the object.
pub user_data: usize,
}