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
extern crate alloc;
use ;
pub use ;
/// Sets up the IO layer functionality.
///
/// See [`Session`].
;
/// Represents an [`Entity`] which may be establishing, or has already
/// established, a connection to a peer.
///
/// - If a session entity only has [`SessionEndpoint`], it is still connecting.
/// - If a session entity has [`SessionEndpoint`] and [`Session`], it has
/// successfully connected.
;
/// Represents an [`Entity`] which can be used to transfer [packets] over a
/// connection to a peer session, potentially over a network.
///
/// # Overview
///
/// A session can send data over to the other side of its connection - to its
/// peer. The peer may be located on a different machine, on the same machine as
/// this session, or even within the same app. This data is sent in the form of
/// [packets].
///
/// The session API is agnostic to the networking model used: it can be used to
/// represent a client-server, peer-to-peer, or any other kind of network
/// topology. The only constraint is that one session talks to one and only one
/// peer for its lifetime, however you can have multiple sessions within the
/// same world. These different sessions may even be communicating over
/// different protocols, such as raw UDP datagrams alongside Steam networking
/// sockets, so that you can e.g. support crossplay between different platforms.
///
/// # Interaction with IO layer implementation
///
/// The [`Session`] component is created by your chosen IO layer implementation,
/// so you should not create it yourself. See your IO layer's documentation for
/// how to spawn an entity with [`Session`]. There are also constraints on which
/// fields of this component you can modify, and how. See each field's
/// documentation for how you can use it.
///
/// Each entity with a [`Session`] should only ever have a single IO layer
/// implementation that drives it. **Adding multiple transports onto the same
/// entity is not supported**, but you can always have multiple entities each
/// with their own [`Session`] and their own transport.
///
/// # Lifecycle
///
/// After creating a session entity using your chosen IO layer, the entity will
/// have the [`SessionEndpoint`] component (indicating that the session is
/// either *connecting* or *connected*), but may not necessarily have the
/// [`Session`] component (indicating that the session is *connected*). Once
/// this component is added, you can send and receive data.
///
/// Note that [`Session`] is not a *guarantee* that you can send and receive
/// data - it is always possible that operations on OS sockets fail, the network
/// may be suddenly unreachable, etc.
///
/// If the session fails to connect, or loses connection after successfully
/// connecting (this may be a graceful disconnect or a connection error),
/// [`Disconnected`] is [triggered][trigger] on the session entity, and the
/// session is despawned immediately afterwards. You may also [trigger] your own
/// disconnection with a string reason by triggering [`Disconnect`].
///
/// # Packet buffers
///
/// [`Session`] holds the buffers of incoming and outgoing [packets] in
/// [`Session::recv`] and [`Session::send`] respectively. These buffers are
/// [`Vec`]s with unbounded capacity, but are cleared automatically on every
/// update:
/// - [`packet::clear_recv_buffers`] before [`IoSystems::Poll`]
/// - [`packet::clear_send_buffers`] before [`IoSystems::Flush`]
///
/// If there are any unconsumed packets in a buffer when it is cleared, a
/// warning is emitted - all packets should be consumed on every update.
///
/// # MTU
///
/// [`Session`]s are also responsible for tracking the current MTU value (see
/// [`packet`]). If the IO layer has a new value for known path MTU, it should
/// use [`Session::set_mtu`] to update it.
///
/// [trigger]: On
/// [packets]: packet
/// [`Disconnected`]: connection::Disconnected
/// [`Disconnect`]: connection::Disconnect
/// System set for scheduling IO layer systems.