Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/enet/peer.c
9902 views
1
/**
2
@file peer.c
3
@brief ENet peer management functions
4
*/
5
#include <string.h>
6
#define ENET_BUILDING_LIB 1
7
#include "enet/enet.h"
8
9
/** @defgroup peer ENet peer functions
10
@{
11
*/
12
13
/** Configures throttle parameter for a peer.
14
15
Unreliable packets are dropped by ENet in response to the varying conditions
16
of the Internet connection to the peer. The throttle represents a probability
17
that an unreliable packet should not be dropped and thus sent by ENet to the peer.
18
The lowest mean round trip time from the sending of a reliable packet to the
19
receipt of its acknowledgement is measured over an amount of time specified by
20
the interval parameter in milliseconds. If a measured round trip time happens to
21
be significantly less than the mean round trip time measured over the interval,
22
then the throttle probability is increased to allow more traffic by an amount
23
specified in the acceleration parameter, which is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE
24
constant. If a measured round trip time happens to be significantly greater than
25
the mean round trip time measured over the interval, then the throttle probability
26
is decreased to limit traffic by an amount specified in the deceleration parameter, which
27
is a ratio to the ENET_PEER_PACKET_THROTTLE_SCALE constant. When the throttle has
28
a value of ENET_PEER_PACKET_THROTTLE_SCALE, no unreliable packets are dropped by
29
ENet, and so 100% of all unreliable packets will be sent. When the throttle has a
30
value of 0, all unreliable packets are dropped by ENet, and so 0% of all unreliable
31
packets will be sent. Intermediate values for the throttle represent intermediate
32
probabilities between 0% and 100% of unreliable packets being sent. The bandwidth
33
limits of the local and foreign hosts are taken into account to determine a
34
sensible limit for the throttle probability above which it should not raise even in
35
the best of conditions.
36
37
@param peer peer to configure
38
@param interval interval, in milliseconds, over which to measure lowest mean RTT; the default value is ENET_PEER_PACKET_THROTTLE_INTERVAL.
39
@param acceleration rate at which to increase the throttle probability as mean RTT declines
40
@param deceleration rate at which to decrease the throttle probability as mean RTT increases
41
*/
42
void
43
enet_peer_throttle_configure (ENetPeer * peer, enet_uint32 interval, enet_uint32 acceleration, enet_uint32 deceleration)
44
{
45
ENetProtocol command;
46
47
peer -> packetThrottleInterval = interval;
48
peer -> packetThrottleAcceleration = acceleration;
49
peer -> packetThrottleDeceleration = deceleration;
50
51
command.header.command = ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
52
command.header.channelID = 0xFF;
53
54
command.throttleConfigure.packetThrottleInterval = ENET_HOST_TO_NET_32 (interval);
55
command.throttleConfigure.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (acceleration);
56
command.throttleConfigure.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (deceleration);
57
58
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
59
}
60
61
int
62
enet_peer_throttle (ENetPeer * peer, enet_uint32 rtt)
63
{
64
if (peer -> lastRoundTripTime <= peer -> lastRoundTripTimeVariance)
65
{
66
peer -> packetThrottle = peer -> packetThrottleLimit;
67
}
68
else
69
if (rtt <= peer -> lastRoundTripTime)
70
{
71
peer -> packetThrottle += peer -> packetThrottleAcceleration;
72
73
if (peer -> packetThrottle > peer -> packetThrottleLimit)
74
peer -> packetThrottle = peer -> packetThrottleLimit;
75
76
return 1;
77
}
78
else
79
if (rtt > peer -> lastRoundTripTime + 2 * peer -> lastRoundTripTimeVariance)
80
{
81
if (peer -> packetThrottle > peer -> packetThrottleDeceleration)
82
peer -> packetThrottle -= peer -> packetThrottleDeceleration;
83
else
84
peer -> packetThrottle = 0;
85
86
return -1;
87
}
88
89
return 0;
90
}
91
92
/** Queues a packet to be sent.
93
94
On success, ENet will assume ownership of the packet, and so enet_packet_destroy
95
should not be called on it thereafter. On failure, the caller still must destroy
96
the packet on its own as ENet has not queued the packet. The caller can also
97
check the packet's referenceCount field after sending to check if ENet queued
98
the packet and thus incremented the referenceCount.
99
100
@param peer destination for the packet
101
@param channelID channel on which to send
102
@param packet packet to send
103
@retval 0 on success
104
@retval < 0 on failure
105
*/
106
int
107
enet_peer_send (ENetPeer * peer, enet_uint8 channelID, ENetPacket * packet)
108
{
109
ENetChannel * channel;
110
ENetProtocol command;
111
size_t fragmentLength;
112
113
if (peer -> state != ENET_PEER_STATE_CONNECTED ||
114
channelID >= peer -> channelCount ||
115
packet -> dataLength > peer -> host -> maximumPacketSize)
116
return -1;
117
118
channel = & peer -> channels [channelID];
119
fragmentLength = peer -> mtu - sizeof (ENetProtocolHeader) - sizeof (ENetProtocolSendFragment);
120
if (peer -> host -> checksum != NULL)
121
fragmentLength -= sizeof(enet_uint32);
122
123
if (packet -> dataLength > fragmentLength)
124
{
125
enet_uint32 fragmentCount = (packet -> dataLength + fragmentLength - 1) / fragmentLength,
126
fragmentNumber,
127
fragmentOffset;
128
enet_uint8 commandNumber;
129
enet_uint16 startSequenceNumber;
130
ENetList fragments;
131
ENetOutgoingCommand * fragment;
132
133
if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT)
134
return -1;
135
136
if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT)) == ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT &&
137
channel -> outgoingUnreliableSequenceNumber < 0xFFFF)
138
{
139
commandNumber = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT;
140
startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingUnreliableSequenceNumber + 1);
141
}
142
else
143
{
144
commandNumber = ENET_PROTOCOL_COMMAND_SEND_FRAGMENT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
145
startSequenceNumber = ENET_HOST_TO_NET_16 (channel -> outgoingReliableSequenceNumber + 1);
146
}
147
148
enet_list_clear (& fragments);
149
150
for (fragmentNumber = 0,
151
fragmentOffset = 0;
152
fragmentOffset < packet -> dataLength;
153
++ fragmentNumber,
154
fragmentOffset += fragmentLength)
155
{
156
if (packet -> dataLength - fragmentOffset < fragmentLength)
157
fragmentLength = packet -> dataLength - fragmentOffset;
158
159
fragment = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
160
if (fragment == NULL)
161
{
162
while (! enet_list_empty (& fragments))
163
{
164
fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
165
166
enet_free (fragment);
167
}
168
169
return -1;
170
}
171
172
fragment -> fragmentOffset = fragmentOffset;
173
fragment -> fragmentLength = fragmentLength;
174
fragment -> packet = packet;
175
fragment -> command.header.command = commandNumber;
176
fragment -> command.header.channelID = channelID;
177
fragment -> command.sendFragment.startSequenceNumber = startSequenceNumber;
178
fragment -> command.sendFragment.dataLength = ENET_HOST_TO_NET_16 (fragmentLength);
179
fragment -> command.sendFragment.fragmentCount = ENET_HOST_TO_NET_32 (fragmentCount);
180
fragment -> command.sendFragment.fragmentNumber = ENET_HOST_TO_NET_32 (fragmentNumber);
181
fragment -> command.sendFragment.totalLength = ENET_HOST_TO_NET_32 (packet -> dataLength);
182
fragment -> command.sendFragment.fragmentOffset = ENET_NET_TO_HOST_32 (fragmentOffset);
183
184
enet_list_insert (enet_list_end (& fragments), fragment);
185
}
186
187
packet -> referenceCount += fragmentNumber;
188
189
while (! enet_list_empty (& fragments))
190
{
191
fragment = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (& fragments));
192
193
enet_peer_setup_outgoing_command (peer, fragment);
194
}
195
196
return 0;
197
}
198
199
command.header.channelID = channelID;
200
201
if ((packet -> flags & (ENET_PACKET_FLAG_RELIABLE | ENET_PACKET_FLAG_UNSEQUENCED)) == ENET_PACKET_FLAG_UNSEQUENCED)
202
{
203
command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
204
command.sendUnsequenced.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
205
}
206
else
207
if (packet -> flags & ENET_PACKET_FLAG_RELIABLE || channel -> outgoingUnreliableSequenceNumber >= 0xFFFF)
208
{
209
command.header.command = ENET_PROTOCOL_COMMAND_SEND_RELIABLE | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
210
command.sendReliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
211
}
212
else
213
{
214
command.header.command = ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE;
215
command.sendUnreliable.dataLength = ENET_HOST_TO_NET_16 (packet -> dataLength);
216
}
217
218
if (enet_peer_queue_outgoing_command (peer, & command, packet, 0, packet -> dataLength) == NULL)
219
return -1;
220
221
return 0;
222
}
223
224
/** Attempts to dequeue any incoming queued packet.
225
@param peer peer to dequeue packets from
226
@param channelID holds the channel ID of the channel the packet was received on success
227
@returns a pointer to the packet, or NULL if there are no available incoming queued packets
228
*/
229
ENetPacket *
230
enet_peer_receive (ENetPeer * peer, enet_uint8 * channelID)
231
{
232
ENetIncomingCommand * incomingCommand;
233
ENetPacket * packet;
234
235
if (enet_list_empty (& peer -> dispatchedCommands))
236
return NULL;
237
238
incomingCommand = (ENetIncomingCommand *) enet_list_remove (enet_list_begin (& peer -> dispatchedCommands));
239
240
if (channelID != NULL)
241
* channelID = incomingCommand -> command.header.channelID;
242
243
packet = incomingCommand -> packet;
244
245
-- packet -> referenceCount;
246
247
if (incomingCommand -> fragments != NULL)
248
enet_free (incomingCommand -> fragments);
249
250
enet_free (incomingCommand);
251
252
peer -> totalWaitingData -= packet -> dataLength;
253
254
return packet;
255
}
256
257
static void
258
enet_peer_reset_outgoing_commands (ENetList * queue)
259
{
260
ENetOutgoingCommand * outgoingCommand;
261
262
while (! enet_list_empty (queue))
263
{
264
outgoingCommand = (ENetOutgoingCommand *) enet_list_remove (enet_list_begin (queue));
265
266
if (outgoingCommand -> packet != NULL)
267
{
268
-- outgoingCommand -> packet -> referenceCount;
269
270
if (outgoingCommand -> packet -> referenceCount == 0)
271
enet_packet_destroy (outgoingCommand -> packet);
272
}
273
274
enet_free (outgoingCommand);
275
}
276
}
277
278
static void
279
enet_peer_remove_incoming_commands (ENetList * queue, ENetListIterator startCommand, ENetListIterator endCommand, ENetIncomingCommand * excludeCommand)
280
{
281
ENetListIterator currentCommand;
282
283
for (currentCommand = startCommand; currentCommand != endCommand; )
284
{
285
ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
286
287
currentCommand = enet_list_next (currentCommand);
288
289
if (incomingCommand == excludeCommand)
290
continue;
291
292
enet_list_remove (& incomingCommand -> incomingCommandList);
293
294
if (incomingCommand -> packet != NULL)
295
{
296
-- incomingCommand -> packet -> referenceCount;
297
298
if (incomingCommand -> packet -> referenceCount == 0)
299
enet_packet_destroy (incomingCommand -> packet);
300
}
301
302
if (incomingCommand -> fragments != NULL)
303
enet_free (incomingCommand -> fragments);
304
305
enet_free (incomingCommand);
306
}
307
}
308
309
static void
310
enet_peer_reset_incoming_commands (ENetList * queue)
311
{
312
enet_peer_remove_incoming_commands(queue, enet_list_begin (queue), enet_list_end (queue), NULL);
313
}
314
315
void
316
enet_peer_reset_queues (ENetPeer * peer)
317
{
318
ENetChannel * channel;
319
320
if (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH)
321
{
322
enet_list_remove (& peer -> dispatchList);
323
324
peer -> flags &= ~ ENET_PEER_FLAG_NEEDS_DISPATCH;
325
}
326
327
while (! enet_list_empty (& peer -> acknowledgements))
328
enet_free (enet_list_remove (enet_list_begin (& peer -> acknowledgements)));
329
330
enet_peer_reset_outgoing_commands (& peer -> sentReliableCommands);
331
enet_peer_reset_outgoing_commands (& peer -> outgoingCommands);
332
enet_peer_reset_outgoing_commands (& peer -> outgoingSendReliableCommands);
333
enet_peer_reset_incoming_commands (& peer -> dispatchedCommands);
334
335
if (peer -> channels != NULL && peer -> channelCount > 0)
336
{
337
for (channel = peer -> channels;
338
channel < & peer -> channels [peer -> channelCount];
339
++ channel)
340
{
341
enet_peer_reset_incoming_commands (& channel -> incomingReliableCommands);
342
enet_peer_reset_incoming_commands (& channel -> incomingUnreliableCommands);
343
}
344
345
enet_free (peer -> channels);
346
}
347
348
peer -> channels = NULL;
349
peer -> channelCount = 0;
350
}
351
352
void
353
enet_peer_on_connect (ENetPeer * peer)
354
{
355
if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
356
{
357
if (peer -> incomingBandwidth != 0)
358
++ peer -> host -> bandwidthLimitedPeers;
359
360
++ peer -> host -> connectedPeers;
361
}
362
}
363
364
void
365
enet_peer_on_disconnect (ENetPeer * peer)
366
{
367
if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
368
{
369
if (peer -> incomingBandwidth != 0)
370
-- peer -> host -> bandwidthLimitedPeers;
371
372
-- peer -> host -> connectedPeers;
373
}
374
}
375
376
/** Forcefully disconnects a peer.
377
@param peer peer to forcefully disconnect
378
@remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
379
on its connection to the local host.
380
*/
381
void
382
enet_peer_reset (ENetPeer * peer)
383
{
384
enet_peer_on_disconnect (peer);
385
386
peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
387
peer -> connectID = 0;
388
389
peer -> state = ENET_PEER_STATE_DISCONNECTED;
390
391
peer -> incomingBandwidth = 0;
392
peer -> outgoingBandwidth = 0;
393
peer -> incomingBandwidthThrottleEpoch = 0;
394
peer -> outgoingBandwidthThrottleEpoch = 0;
395
peer -> incomingDataTotal = 0;
396
peer -> outgoingDataTotal = 0;
397
peer -> lastSendTime = 0;
398
peer -> lastReceiveTime = 0;
399
peer -> nextTimeout = 0;
400
peer -> earliestTimeout = 0;
401
peer -> packetLossEpoch = 0;
402
peer -> packetsSent = 0;
403
peer -> packetsLost = 0;
404
peer -> packetLoss = 0;
405
peer -> packetLossVariance = 0;
406
peer -> packetThrottle = ENET_PEER_DEFAULT_PACKET_THROTTLE;
407
peer -> packetThrottleLimit = ENET_PEER_PACKET_THROTTLE_SCALE;
408
peer -> packetThrottleCounter = 0;
409
peer -> packetThrottleEpoch = 0;
410
peer -> packetThrottleAcceleration = ENET_PEER_PACKET_THROTTLE_ACCELERATION;
411
peer -> packetThrottleDeceleration = ENET_PEER_PACKET_THROTTLE_DECELERATION;
412
peer -> packetThrottleInterval = ENET_PEER_PACKET_THROTTLE_INTERVAL;
413
peer -> pingInterval = ENET_PEER_PING_INTERVAL;
414
peer -> timeoutLimit = ENET_PEER_TIMEOUT_LIMIT;
415
peer -> timeoutMinimum = ENET_PEER_TIMEOUT_MINIMUM;
416
peer -> timeoutMaximum = ENET_PEER_TIMEOUT_MAXIMUM;
417
peer -> lastRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
418
peer -> lowestRoundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
419
peer -> lastRoundTripTimeVariance = 0;
420
peer -> highestRoundTripTimeVariance = 0;
421
peer -> roundTripTime = ENET_PEER_DEFAULT_ROUND_TRIP_TIME;
422
peer -> roundTripTimeVariance = 0;
423
peer -> mtu = peer -> host -> mtu;
424
peer -> reliableDataInTransit = 0;
425
peer -> outgoingReliableSequenceNumber = 0;
426
peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
427
peer -> incomingUnsequencedGroup = 0;
428
peer -> outgoingUnsequencedGroup = 0;
429
peer -> eventData = 0;
430
peer -> totalWaitingData = 0;
431
peer -> flags = 0;
432
433
memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
434
435
enet_peer_reset_queues (peer);
436
}
437
438
/** Sends a ping request to a peer.
439
@param peer destination for the ping request
440
@remarks ping requests factor into the mean round trip time as designated by the
441
roundTripTime field in the ENetPeer structure. ENet automatically pings all connected
442
peers at regular intervals, however, this function may be called to ensure more
443
frequent ping requests.
444
*/
445
void
446
enet_peer_ping (ENetPeer * peer)
447
{
448
ENetProtocol command;
449
450
if (peer -> state != ENET_PEER_STATE_CONNECTED)
451
return;
452
453
command.header.command = ENET_PROTOCOL_COMMAND_PING | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
454
command.header.channelID = 0xFF;
455
456
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
457
}
458
459
/** Sets the interval at which pings will be sent to a peer.
460
461
Pings are used both to monitor the liveness of the connection and also to dynamically
462
adjust the throttle during periods of low traffic so that the throttle has reasonable
463
responsiveness during traffic spikes.
464
465
@param peer the peer to adjust
466
@param pingInterval the interval at which to send pings; defaults to ENET_PEER_PING_INTERVAL if 0
467
*/
468
void
469
enet_peer_ping_interval (ENetPeer * peer, enet_uint32 pingInterval)
470
{
471
peer -> pingInterval = pingInterval ? pingInterval : ENET_PEER_PING_INTERVAL;
472
}
473
474
/** Sets the timeout parameters for a peer.
475
476
The timeout parameter control how and when a peer will timeout from a failure to acknowledge
477
reliable traffic. Timeout values use an exponential backoff mechanism, where if a reliable
478
packet is not acknowledge within some multiple of the average RTT plus a variance tolerance,
479
the timeout will be doubled until it reaches a set limit. If the timeout is thus at this
480
limit and reliable packets have been sent but not acknowledged within a certain minimum time
481
period, the peer will be disconnected. Alternatively, if reliable packets have been sent
482
but not acknowledged for a certain maximum time period, the peer will be disconnected regardless
483
of the current timeout limit value.
484
485
@param peer the peer to adjust
486
@param timeoutLimit the timeout limit; defaults to ENET_PEER_TIMEOUT_LIMIT if 0
487
@param timeoutMinimum the timeout minimum; defaults to ENET_PEER_TIMEOUT_MINIMUM if 0
488
@param timeoutMaximum the timeout maximum; defaults to ENET_PEER_TIMEOUT_MAXIMUM if 0
489
*/
490
491
void
492
enet_peer_timeout (ENetPeer * peer, enet_uint32 timeoutLimit, enet_uint32 timeoutMinimum, enet_uint32 timeoutMaximum)
493
{
494
peer -> timeoutLimit = timeoutLimit ? timeoutLimit : ENET_PEER_TIMEOUT_LIMIT;
495
peer -> timeoutMinimum = timeoutMinimum ? timeoutMinimum : ENET_PEER_TIMEOUT_MINIMUM;
496
peer -> timeoutMaximum = timeoutMaximum ? timeoutMaximum : ENET_PEER_TIMEOUT_MAXIMUM;
497
}
498
499
/** Force an immediate disconnection from a peer.
500
@param peer peer to disconnect
501
@param data data describing the disconnection
502
@remarks No ENET_EVENT_DISCONNECT event will be generated. The foreign peer is not
503
guaranteed to receive the disconnect notification, and is reset immediately upon
504
return from this function.
505
*/
506
void
507
enet_peer_disconnect_now (ENetPeer * peer, enet_uint32 data)
508
{
509
ENetProtocol command;
510
511
if (peer -> state == ENET_PEER_STATE_DISCONNECTED)
512
return;
513
514
if (peer -> state != ENET_PEER_STATE_ZOMBIE &&
515
peer -> state != ENET_PEER_STATE_DISCONNECTING)
516
{
517
enet_peer_reset_queues (peer);
518
519
command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT | ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
520
command.header.channelID = 0xFF;
521
command.disconnect.data = ENET_HOST_TO_NET_32 (data);
522
523
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
524
525
enet_host_flush (peer -> host);
526
}
527
528
enet_peer_reset (peer);
529
}
530
531
/** Request a disconnection from a peer.
532
@param peer peer to request a disconnection
533
@param data data describing the disconnection
534
@remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
535
once the disconnection is complete.
536
*/
537
void
538
enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
539
{
540
ENetProtocol command;
541
542
if (peer -> state == ENET_PEER_STATE_DISCONNECTING ||
543
peer -> state == ENET_PEER_STATE_DISCONNECTED ||
544
peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT ||
545
peer -> state == ENET_PEER_STATE_ZOMBIE)
546
return;
547
548
enet_peer_reset_queues (peer);
549
550
command.header.command = ENET_PROTOCOL_COMMAND_DISCONNECT;
551
command.header.channelID = 0xFF;
552
command.disconnect.data = ENET_HOST_TO_NET_32 (data);
553
554
if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
555
command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
556
else
557
command.header.command |= ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED;
558
559
enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
560
561
if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
562
{
563
enet_peer_on_disconnect (peer);
564
565
peer -> state = ENET_PEER_STATE_DISCONNECTING;
566
}
567
else
568
{
569
enet_host_flush (peer -> host);
570
enet_peer_reset (peer);
571
}
572
}
573
574
int
575
enet_peer_has_outgoing_commands (ENetPeer * peer)
576
{
577
if (enet_list_empty (& peer -> outgoingCommands) &&
578
enet_list_empty (& peer -> outgoingSendReliableCommands) &&
579
enet_list_empty (& peer -> sentReliableCommands))
580
return 0;
581
582
return 1;
583
}
584
585
/** Request a disconnection from a peer, but only after all queued outgoing packets are sent.
586
@param peer peer to request a disconnection
587
@param data data describing the disconnection
588
@remarks An ENET_EVENT_DISCONNECT event will be generated by enet_host_service()
589
once the disconnection is complete.
590
*/
591
void
592
enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
593
{
594
if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
595
enet_peer_has_outgoing_commands (peer))
596
{
597
peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
598
peer -> eventData = data;
599
}
600
else
601
enet_peer_disconnect (peer, data);
602
}
603
604
ENetAcknowledgement *
605
enet_peer_queue_acknowledgement (ENetPeer * peer, const ENetProtocol * command, enet_uint16 sentTime)
606
{
607
ENetAcknowledgement * acknowledgement;
608
609
if (command -> header.channelID < peer -> channelCount)
610
{
611
ENetChannel * channel = & peer -> channels [command -> header.channelID];
612
enet_uint16 reliableWindow = command -> header.reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE,
613
currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
614
615
if (command -> header.reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
616
reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
617
618
if (reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1 && reliableWindow <= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS)
619
return NULL;
620
}
621
622
acknowledgement = (ENetAcknowledgement *) enet_malloc (sizeof (ENetAcknowledgement));
623
if (acknowledgement == NULL)
624
return NULL;
625
626
peer -> outgoingDataTotal += sizeof (ENetProtocolAcknowledge);
627
628
acknowledgement -> sentTime = sentTime;
629
acknowledgement -> command = * command;
630
631
enet_list_insert (enet_list_end (& peer -> acknowledgements), acknowledgement);
632
633
return acknowledgement;
634
}
635
636
void
637
enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
638
{
639
peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
640
641
if (outgoingCommand -> command.header.channelID == 0xFF)
642
{
643
++ peer -> outgoingReliableSequenceNumber;
644
645
outgoingCommand -> reliableSequenceNumber = peer -> outgoingReliableSequenceNumber;
646
outgoingCommand -> unreliableSequenceNumber = 0;
647
}
648
else
649
{
650
ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
651
652
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
653
{
654
++ channel -> outgoingReliableSequenceNumber;
655
channel -> outgoingUnreliableSequenceNumber = 0;
656
657
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
658
outgoingCommand -> unreliableSequenceNumber = 0;
659
}
660
else
661
if (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_UNSEQUENCED)
662
{
663
++ peer -> outgoingUnsequencedGroup;
664
665
outgoingCommand -> reliableSequenceNumber = 0;
666
outgoingCommand -> unreliableSequenceNumber = 0;
667
}
668
else
669
{
670
if (outgoingCommand -> fragmentOffset == 0)
671
++ channel -> outgoingUnreliableSequenceNumber;
672
673
outgoingCommand -> reliableSequenceNumber = channel -> outgoingReliableSequenceNumber;
674
outgoingCommand -> unreliableSequenceNumber = channel -> outgoingUnreliableSequenceNumber;
675
}
676
}
677
678
outgoingCommand -> sendAttempts = 0;
679
outgoingCommand -> sentTime = 0;
680
outgoingCommand -> roundTripTimeout = 0;
681
outgoingCommand -> command.header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> reliableSequenceNumber);
682
outgoingCommand -> queueTime = ++ peer -> host -> totalQueued;
683
684
switch (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK)
685
{
686
case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
687
outgoingCommand -> command.sendUnreliable.unreliableSequenceNumber = ENET_HOST_TO_NET_16 (outgoingCommand -> unreliableSequenceNumber);
688
break;
689
690
case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
691
outgoingCommand -> command.sendUnsequenced.unsequencedGroup = ENET_HOST_TO_NET_16 (peer -> outgoingUnsequencedGroup);
692
break;
693
694
default:
695
break;
696
}
697
698
if ((outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0 &&
699
outgoingCommand -> packet != NULL)
700
enet_list_insert (enet_list_end (& peer -> outgoingSendReliableCommands), outgoingCommand);
701
else
702
enet_list_insert (enet_list_end (& peer -> outgoingCommands), outgoingCommand);
703
}
704
705
ENetOutgoingCommand *
706
enet_peer_queue_outgoing_command (ENetPeer * peer, const ENetProtocol * command, ENetPacket * packet, enet_uint32 offset, enet_uint16 length)
707
{
708
ENetOutgoingCommand * outgoingCommand = (ENetOutgoingCommand *) enet_malloc (sizeof (ENetOutgoingCommand));
709
if (outgoingCommand == NULL)
710
return NULL;
711
712
outgoingCommand -> command = * command;
713
outgoingCommand -> fragmentOffset = offset;
714
outgoingCommand -> fragmentLength = length;
715
outgoingCommand -> packet = packet;
716
if (packet != NULL)
717
++ packet -> referenceCount;
718
719
enet_peer_setup_outgoing_command (peer, outgoingCommand);
720
721
return outgoingCommand;
722
}
723
724
void
725
enet_peer_dispatch_incoming_unreliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand)
726
{
727
ENetListIterator droppedCommand, startCommand, currentCommand;
728
729
for (droppedCommand = startCommand = currentCommand = enet_list_begin (& channel -> incomingUnreliableCommands);
730
currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
731
currentCommand = enet_list_next (currentCommand))
732
{
733
ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
734
735
if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
736
continue;
737
738
if (incomingCommand -> reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
739
{
740
if (incomingCommand -> fragmentsRemaining <= 0)
741
{
742
channel -> incomingUnreliableSequenceNumber = incomingCommand -> unreliableSequenceNumber;
743
continue;
744
}
745
746
if (startCommand != currentCommand)
747
{
748
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
749
750
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
751
{
752
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
753
754
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
755
}
756
757
droppedCommand = currentCommand;
758
}
759
else
760
if (droppedCommand != currentCommand)
761
droppedCommand = enet_list_previous (currentCommand);
762
}
763
else
764
{
765
enet_uint16 reliableWindow = incomingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE,
766
currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
767
if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
768
reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
769
if (reliableWindow >= currentWindow && reliableWindow < currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
770
break;
771
772
droppedCommand = enet_list_next (currentCommand);
773
774
if (startCommand != currentCommand)
775
{
776
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
777
778
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
779
{
780
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
781
782
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
783
}
784
}
785
}
786
787
startCommand = enet_list_next (currentCommand);
788
}
789
790
if (startCommand != currentCommand)
791
{
792
enet_list_move (enet_list_end (& peer -> dispatchedCommands), startCommand, enet_list_previous (currentCommand));
793
794
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
795
{
796
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
797
798
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
799
}
800
801
droppedCommand = currentCommand;
802
}
803
804
enet_peer_remove_incoming_commands (& channel -> incomingUnreliableCommands, enet_list_begin (& channel -> incomingUnreliableCommands), droppedCommand, queuedCommand);
805
}
806
807
void
808
enet_peer_dispatch_incoming_reliable_commands (ENetPeer * peer, ENetChannel * channel, ENetIncomingCommand * queuedCommand)
809
{
810
ENetListIterator currentCommand;
811
812
for (currentCommand = enet_list_begin (& channel -> incomingReliableCommands);
813
currentCommand != enet_list_end (& channel -> incomingReliableCommands);
814
currentCommand = enet_list_next (currentCommand))
815
{
816
ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
817
818
if (incomingCommand -> fragmentsRemaining > 0 ||
819
incomingCommand -> reliableSequenceNumber != (enet_uint16) (channel -> incomingReliableSequenceNumber + 1))
820
break;
821
822
channel -> incomingReliableSequenceNumber = incomingCommand -> reliableSequenceNumber;
823
824
if (incomingCommand -> fragmentCount > 0)
825
channel -> incomingReliableSequenceNumber += incomingCommand -> fragmentCount - 1;
826
}
827
828
if (currentCommand == enet_list_begin (& channel -> incomingReliableCommands))
829
return;
830
831
channel -> incomingUnreliableSequenceNumber = 0;
832
833
enet_list_move (enet_list_end (& peer -> dispatchedCommands), enet_list_begin (& channel -> incomingReliableCommands), enet_list_previous (currentCommand));
834
835
if (! (peer -> flags & ENET_PEER_FLAG_NEEDS_DISPATCH))
836
{
837
enet_list_insert (enet_list_end (& peer -> host -> dispatchQueue), & peer -> dispatchList);
838
839
peer -> flags |= ENET_PEER_FLAG_NEEDS_DISPATCH;
840
}
841
842
if (! enet_list_empty (& channel -> incomingUnreliableCommands))
843
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, queuedCommand);
844
}
845
846
ENetIncomingCommand *
847
enet_peer_queue_incoming_command (ENetPeer * peer, const ENetProtocol * command, const void * data, size_t dataLength, enet_uint32 flags, enet_uint32 fragmentCount)
848
{
849
static ENetIncomingCommand dummyCommand;
850
851
ENetChannel * channel = & peer -> channels [command -> header.channelID];
852
enet_uint32 unreliableSequenceNumber = 0, reliableSequenceNumber = 0;
853
enet_uint16 reliableWindow, currentWindow;
854
ENetIncomingCommand * incomingCommand;
855
ENetListIterator currentCommand;
856
ENetPacket * packet = NULL;
857
858
if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
859
goto discardCommand;
860
861
if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
862
{
863
reliableSequenceNumber = command -> header.reliableSequenceNumber;
864
reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
865
currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
866
867
if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
868
reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
869
870
if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
871
goto discardCommand;
872
}
873
874
switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
875
{
876
case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
877
case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
878
if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber)
879
goto discardCommand;
880
881
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
882
currentCommand != enet_list_end (& channel -> incomingReliableCommands);
883
currentCommand = enet_list_previous (currentCommand))
884
{
885
incomingCommand = (ENetIncomingCommand *) currentCommand;
886
887
if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
888
{
889
if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
890
continue;
891
}
892
else
893
if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
894
break;
895
896
if (incomingCommand -> reliableSequenceNumber <= reliableSequenceNumber)
897
{
898
if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
899
break;
900
901
goto discardCommand;
902
}
903
}
904
break;
905
906
case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
907
case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT:
908
unreliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendUnreliable.unreliableSequenceNumber);
909
910
if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber &&
911
unreliableSequenceNumber <= channel -> incomingUnreliableSequenceNumber)
912
goto discardCommand;
913
914
for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
915
currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
916
currentCommand = enet_list_previous (currentCommand))
917
{
918
incomingCommand = (ENetIncomingCommand *) currentCommand;
919
920
if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED)
921
continue;
922
923
if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
924
{
925
if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
926
continue;
927
}
928
else
929
if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
930
break;
931
932
if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
933
break;
934
935
if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber)
936
continue;
937
938
if (incomingCommand -> unreliableSequenceNumber <= unreliableSequenceNumber)
939
{
940
if (incomingCommand -> unreliableSequenceNumber < unreliableSequenceNumber)
941
break;
942
943
goto discardCommand;
944
}
945
}
946
break;
947
948
case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
949
currentCommand = enet_list_end (& channel -> incomingUnreliableCommands);
950
break;
951
952
default:
953
goto discardCommand;
954
}
955
956
if (peer -> totalWaitingData >= peer -> host -> maximumWaitingData)
957
goto notifyError;
958
959
packet = enet_packet_create (data, dataLength, flags);
960
if (packet == NULL)
961
goto notifyError;
962
963
incomingCommand = (ENetIncomingCommand *) enet_malloc (sizeof (ENetIncomingCommand));
964
if (incomingCommand == NULL)
965
goto notifyError;
966
967
incomingCommand -> reliableSequenceNumber = command -> header.reliableSequenceNumber;
968
incomingCommand -> unreliableSequenceNumber = unreliableSequenceNumber & 0xFFFF;
969
incomingCommand -> command = * command;
970
incomingCommand -> fragmentCount = fragmentCount;
971
incomingCommand -> fragmentsRemaining = fragmentCount;
972
incomingCommand -> packet = packet;
973
incomingCommand -> fragments = NULL;
974
975
if (fragmentCount > 0)
976
{
977
if (fragmentCount <= ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT)
978
incomingCommand -> fragments = (enet_uint32 *) enet_malloc ((fragmentCount + 31) / 32 * sizeof (enet_uint32));
979
if (incomingCommand -> fragments == NULL)
980
{
981
enet_free (incomingCommand);
982
983
goto notifyError;
984
}
985
memset (incomingCommand -> fragments, 0, (fragmentCount + 31) / 32 * sizeof (enet_uint32));
986
}
987
988
if (packet != NULL)
989
{
990
++ packet -> referenceCount;
991
992
peer -> totalWaitingData += packet -> dataLength;
993
}
994
995
enet_list_insert (enet_list_next (currentCommand), incomingCommand);
996
997
switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
998
{
999
case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
1000
case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
1001
enet_peer_dispatch_incoming_reliable_commands (peer, channel, incomingCommand);
1002
break;
1003
1004
default:
1005
enet_peer_dispatch_incoming_unreliable_commands (peer, channel, incomingCommand);
1006
break;
1007
}
1008
1009
return incomingCommand;
1010
1011
discardCommand:
1012
if (fragmentCount > 0)
1013
goto notifyError;
1014
1015
if (packet != NULL && packet -> referenceCount == 0)
1016
enet_packet_destroy (packet);
1017
1018
return & dummyCommand;
1019
1020
notifyError:
1021
if (packet != NULL && packet -> referenceCount == 0)
1022
enet_packet_destroy (packet);
1023
1024
return NULL;
1025
}
1026
1027
/** @} */
1028
1029