1 /**
2 @file protocol.c
3 @brief ENet protocol functions
4 */
5 #include <stdio.h>
6 #include <string.h>
7 #define ENET_BUILDING_LIB 1
8 #include "enet/utility.h"
9 #include "enet/time.h"
10 #include "enet/enet.h"
11
12 static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
13 {
14 0,
15 sizeof (ENetProtocolAcknowledge),
16 sizeof (ENetProtocolConnect),
17 sizeof (ENetProtocolVerifyConnect),
18 sizeof (ENetProtocolDisconnect),
19 sizeof (ENetProtocolPing),
20 sizeof (ENetProtocolSendReliable),
21 sizeof (ENetProtocolSendUnreliable),
22 sizeof (ENetProtocolSendFragment),
23 sizeof (ENetProtocolSendUnsequenced),
24 sizeof (ENetProtocolBandwidthLimit),
25 sizeof (ENetProtocolThrottleConfigure),
26 sizeof (ENetProtocolSendFragment)
27 };
28
29 size_t
enet_protocol_command_size(enet_uint8 commandNumber)30 enet_protocol_command_size (enet_uint8 commandNumber)
31 {
32 return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK];
33 }
34
35 static int
enet_protocol_dispatch_incoming_commands(ENetHost * host,ENetEvent * event)36 enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
37 {
38 while (! enet_list_empty (& host -> dispatchQueue))
39 {
40 ENetPeer * peer = (ENetPeer *) enet_list_remove (enet_list_begin (& host -> dispatchQueue));
41
42 peer -> needsDispatch = 0;
43
44 switch (peer -> state)
45 {
46 case ENET_PEER_STATE_CONNECTION_PENDING:
47 case ENET_PEER_STATE_CONNECTION_SUCCEEDED:
48 peer -> state = ENET_PEER_STATE_CONNECTED;
49
50 event -> type = ENET_EVENT_TYPE_CONNECT;
51 event -> peer = peer;
52 event -> data = peer -> eventData;
53
54 return 1;
55
56 case ENET_PEER_STATE_ZOMBIE:
57 host -> recalculateBandwidthLimits = 1;
58
59 event -> type = ENET_EVENT_TYPE_DISCONNECT;
60 event -> peer = peer;
61 event -> data = peer -> eventData;
62
63 enet_peer_reset (peer);
64
65 return 1;
66
67 case ENET_PEER_STATE_CONNECTED:
68 if (enet_list_empty (& peer -> dispatchedCommands))
69 continue;
70
71 event -> packet = enet_peer_receive (peer, & event -> channelID);
72 if (event -> packet == NULL)
73 continue;
74
75 event -> type = ENET_EVENT_TYPE_RECEIVE;
76 event -> peer = peer;
77
78 if (! enet_list_empty (& peer -> dispatchedCommands))
79 {
80 peer -> needsDispatch = 1;
81
82 enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
83 }
84
85 return 1;
86
87 default:
88 break;
89 }
90 }
91
92 return 0;
93 }
94
95 static void
enet_protocol_dispatch_state(ENetHost * host,ENetPeer * peer,ENetPeerState state)96 enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state)
97 {
98 peer -> state = state;
99
100 if (! peer -> needsDispatch)
101 {
102 enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
103
104 peer -> needsDispatch = 1;
105 }
106 }
107
108 static void
enet_protocol_notify_connect(ENetHost * host,ENetPeer * peer,ENetEvent * event)109 enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
110 {
111 host -> recalculateBandwidthLimits = 1;
112
113 if (event != NULL)
114 {
115 peer -> state = ENET_PEER_STATE_CONNECTED;
116
117 event -> type = ENET_EVENT_TYPE_CONNECT;
118 event -> peer = peer;
119 event -> data = peer -> eventData;
120 }
121 else
122 enet_protocol_dispatch_state (host, peer, peer -> state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING);
123 }
124
125 static void
enet_protocol_notify_disconnect(ENetHost * host,ENetPeer * peer,ENetEvent * event)126 enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
127 {
128 if (peer -> state >= ENET_PEER_STATE_CONNECTION_PENDING)
129 host -> recalculateBandwidthLimits = 1;
130
131 if (peer -> state != ENET_PEER_STATE_CONNECTING && peer -> state < ENET_PEER_STATE_CONNECTION_SUCCEEDED)
132 enet_peer_reset (peer);
133 else
134 if (event != NULL)
135 {
136 event -> type = ENET_EVENT_TYPE_DISCONNECT;
137 event -> peer = peer;
138 event -> data = 0;
139
140 enet_peer_reset (peer);
141 }
142 else
143 {
144 peer -> eventData = 0;
145
146 enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
147 }
148 }
149
150 static void
enet_protocol_remove_sent_unreliable_commands(ENetPeer * peer)151 enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
152 {
153 ENetOutgoingCommand * outgoingCommand;
154
155 while (! enet_list_empty (& peer -> sentUnreliableCommands))
156 {
157 outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
158
159 enet_list_remove (& outgoingCommand -> outgoingCommandList);
160
161 if (outgoingCommand -> packet != NULL)
162 {
163 -- outgoingCommand -> packet -> referenceCount;
164
165 if (outgoingCommand -> packet -> referenceCount == 0)
166 enet_packet_destroy (outgoingCommand -> packet);
167 }
168
169 enet_free (outgoingCommand);
170 }
171 }
172
173 static ENetProtocolCommand
enet_protocol_remove_sent_reliable_command(ENetPeer * peer,enet_uint16 reliableSequenceNumber,enet_uint8 channelID)174 enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
175 {
176 ENetOutgoingCommand * outgoingCommand = NULL;
177 ENetListIterator currentCommand;
178 ENetProtocolCommand commandNumber;
179 int wasSent = 1;
180
181 for (currentCommand = enet_list_begin (& peer -> sentReliableCommands);
182 currentCommand != enet_list_end (& peer -> sentReliableCommands);
183 currentCommand = enet_list_next (currentCommand))
184 {
185 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
186
187 if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
188 outgoingCommand -> command.header.channelID == channelID)
189 break;
190 }
191
192 if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
193 {
194 for (currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
195 currentCommand != enet_list_end (& peer -> outgoingReliableCommands);
196 currentCommand = enet_list_next (currentCommand))
197 {
198 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
199
200 if (outgoingCommand -> sendAttempts < 1) return ENET_PROTOCOL_COMMAND_NONE;
201
202 if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
203 outgoingCommand -> command.header.channelID == channelID)
204 break;
205 }
206
207 if (currentCommand == enet_list_end (& peer -> outgoingReliableCommands))
208 return ENET_PROTOCOL_COMMAND_NONE;
209
210 wasSent = 0;
211 }
212
213 if (outgoingCommand == NULL)
214 return ENET_PROTOCOL_COMMAND_NONE;
215
216 if (channelID < peer -> channelCount)
217 {
218 ENetChannel * channel = & peer -> channels [channelID];
219 enet_uint16 reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
220 if (channel -> reliableWindows [reliableWindow] > 0)
221 {
222 -- channel -> reliableWindows [reliableWindow];
223 if (! channel -> reliableWindows [reliableWindow])
224 channel -> usedReliableWindows &= ~ (1 << reliableWindow);
225 }
226 }
227
228 commandNumber = (ENetProtocolCommand) (outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK);
229
230 enet_list_remove (& outgoingCommand -> outgoingCommandList);
231
232 if (outgoingCommand -> packet != NULL)
233 {
234 if (wasSent)
235 peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
236
237 -- outgoingCommand -> packet -> referenceCount;
238
239 if (outgoingCommand -> packet -> referenceCount == 0)
240 enet_packet_destroy (outgoingCommand -> packet);
241 }
242
243 enet_free (outgoingCommand);
244
245 if (enet_list_empty (& peer -> sentReliableCommands))
246 return commandNumber;
247
248 outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentReliableCommands);
249
250 peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
251
252 return commandNumber;
253 }
254
255 static ENetPeer *
enet_protocol_handle_connect(ENetHost * host,ENetProtocolHeader * header,ENetProtocol * command)256 enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENetProtocol * command)
257 {
258 enet_uint8 incomingSessionID, outgoingSessionID;
259 enet_uint32 mtu, windowSize;
260 ENetChannel * channel;
261 size_t channelCount;
262 ENetPeer * currentPeer;
263 ENetProtocol verifyCommand;
264
265 channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount);
266
267 if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT ||
268 channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
269 return NULL;
270
271 for (currentPeer = host -> peers;
272 currentPeer < & host -> peers [host -> peerCount];
273 ++ currentPeer)
274 {
275 if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED &&
276 currentPeer -> address.host == host -> receivedAddress.host &&
277 currentPeer -> address.port == host -> receivedAddress.port &&
278 currentPeer -> connectID == command -> connect.connectID)
279 return NULL;
280 }
281
282 for (currentPeer = host -> peers;
283 currentPeer < & host -> peers [host -> peerCount];
284 ++ currentPeer)
285 {
286 if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
287 break;
288 }
289
290 if (currentPeer >= & host -> peers [host -> peerCount])
291 return NULL;
292
293 if (channelCount > host -> channelLimit)
294 channelCount = host -> channelLimit;
295 currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
296 if (currentPeer -> channels == NULL)
297 return NULL;
298 currentPeer -> channelCount = channelCount;
299 currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
300 currentPeer -> connectID = command -> connect.connectID;
301 currentPeer -> address = host -> receivedAddress;
302 currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
303 currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
304 currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth);
305 currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval);
306 currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration);
307 currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration);
308 currentPeer -> eventData = ENET_NET_TO_HOST_32 (command -> connect.data);
309
310 incomingSessionID = command -> connect.incomingSessionID == 0xFF ? currentPeer -> outgoingSessionID : command -> connect.incomingSessionID;
311 incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
312 if (incomingSessionID == currentPeer -> outgoingSessionID)
313 incomingSessionID = (incomingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
314 currentPeer -> outgoingSessionID = incomingSessionID;
315
316 outgoingSessionID = command -> connect.outgoingSessionID == 0xFF ? currentPeer -> incomingSessionID : command -> connect.outgoingSessionID;
317 outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
318 if (outgoingSessionID == currentPeer -> incomingSessionID)
319 outgoingSessionID = (outgoingSessionID + 1) & (ENET_PROTOCOL_HEADER_SESSION_MASK >> ENET_PROTOCOL_HEADER_SESSION_SHIFT);
320 currentPeer -> incomingSessionID = outgoingSessionID;
321
322 for (channel = currentPeer -> channels;
323 channel < & currentPeer -> channels [channelCount];
324 ++ channel)
325 {
326 channel -> outgoingReliableSequenceNumber = 0;
327 channel -> outgoingUnreliableSequenceNumber = 0;
328 channel -> incomingReliableSequenceNumber = 0;
329 channel -> incomingUnreliableSequenceNumber = 0;
330
331 enet_list_clear (& channel -> incomingReliableCommands);
332 enet_list_clear (& channel -> incomingUnreliableCommands);
333
334 channel -> usedReliableWindows = 0;
335 memset (channel -> reliableWindows, 0, sizeof (channel -> reliableWindows));
336 }
337
338 mtu = ENET_NET_TO_HOST_32 (command -> connect.mtu);
339
340 if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
341 mtu = ENET_PROTOCOL_MINIMUM_MTU;
342 else
343 if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
344 mtu = ENET_PROTOCOL_MAXIMUM_MTU;
345
346 currentPeer -> mtu = mtu;
347
348 if (host -> outgoingBandwidth == 0 &&
349 currentPeer -> incomingBandwidth == 0)
350 currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
351 else
352 if (host -> outgoingBandwidth == 0 ||
353 currentPeer -> incomingBandwidth == 0)
354 currentPeer -> windowSize = (ENET_MAX (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) /
355 ENET_PEER_WINDOW_SIZE_SCALE) *
356 ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
357 else
358 currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) /
359 ENET_PEER_WINDOW_SIZE_SCALE) *
360 ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
361
362 if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
363 currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
364 else
365 if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
366 currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
367
368 if (host -> incomingBandwidth == 0)
369 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
370 else
371 windowSize = (host -> incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) *
372 ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
373
374 if (windowSize > ENET_NET_TO_HOST_32 (command -> connect.windowSize))
375 windowSize = ENET_NET_TO_HOST_32 (command -> connect.windowSize);
376
377 if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
378 windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
379 else
380 if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
381 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
382
383 verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
384 verifyCommand.header.channelID = 0xFF;
385 verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
386 verifyCommand.verifyConnect.incomingSessionID = incomingSessionID;
387 verifyCommand.verifyConnect.outgoingSessionID = outgoingSessionID;
388 verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_32 (currentPeer -> mtu);
389 verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize);
390 verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
391 verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
392 verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
393 verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
394 verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
395 verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
396 verifyCommand.verifyConnect.connectID = currentPeer -> connectID;
397
398 enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0);
399
400 return currentPeer;
401 }
402
403 static int
enet_protocol_handle_send_reliable(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)404 enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
405 {
406 ENetPacket * packet;
407 size_t dataLength;
408
409 if (command -> header.channelID >= peer -> channelCount ||
410 (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
411 return -1;
412
413 dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength);
414 * currentData += dataLength;
415 if (dataLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE ||
416 * currentData < host -> receivedData ||
417 * currentData > & host -> receivedData [host -> receivedDataLength])
418 return -1;
419
420 packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable),
421 dataLength,
422 ENET_PACKET_FLAG_RELIABLE);
423 if (packet == NULL ||
424 enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL)
425 return -1;
426
427 return 0;
428 }
429
430 static int
enet_protocol_handle_send_unsequenced(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)431 enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
432 {
433 ENetPacket * packet;
434 enet_uint32 unsequencedGroup, index;
435 size_t dataLength;
436
437 if (command -> header.channelID >= peer -> channelCount ||
438 (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
439 return -1;
440
441 dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength);
442 * currentData += dataLength;
443 if (dataLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE ||
444 * currentData < host -> receivedData ||
445 * currentData > & host -> receivedData [host -> receivedDataLength])
446 return -1;
447
448 unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup);
449 index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE;
450
451 if (unsequencedGroup < peer -> incomingUnsequencedGroup)
452 unsequencedGroup += 0x10000;
453
454 if (unsequencedGroup >= (enet_uint32) peer -> incomingUnsequencedGroup + ENET_PEER_FREE_UNSEQUENCED_WINDOWS * ENET_PEER_UNSEQUENCED_WINDOW_SIZE)
455 return 0;
456
457 unsequencedGroup &= 0xFFFF;
458
459 if (unsequencedGroup - index != peer -> incomingUnsequencedGroup)
460 {
461 peer -> incomingUnsequencedGroup = unsequencedGroup - index;
462
463 memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
464 }
465 else
466 if (peer -> unsequencedWindow [index / 32] & (1 << (index % 32)))
467 return 0;
468
469 packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced),
470 dataLength,
471 ENET_PACKET_FLAG_UNSEQUENCED);
472 if (packet == NULL ||
473 enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL)
474 return -1;
475
476 peer -> unsequencedWindow [index / 32] |= 1 << (index % 32);
477
478 return 0;
479 }
480
481 static int
enet_protocol_handle_send_unreliable(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)482 enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
483 {
484 ENetPacket * packet;
485 size_t dataLength;
486
487 if (command -> header.channelID >= peer -> channelCount ||
488 (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
489 return -1;
490
491 dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength);
492 * currentData += dataLength;
493 if (dataLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE ||
494 * currentData < host -> receivedData ||
495 * currentData > & host -> receivedData [host -> receivedDataLength])
496 return -1;
497
498 packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable),
499 dataLength,
500 0);
501 if (packet == NULL ||
502 enet_peer_queue_incoming_command (peer, command, packet, 0) == NULL)
503 return -1;
504
505 return 0;
506 }
507
508 static int
enet_protocol_handle_send_fragment(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)509 enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
510 {
511 enet_uint32 fragmentNumber,
512 fragmentCount,
513 fragmentOffset,
514 fragmentLength,
515 startSequenceNumber,
516 totalLength;
517 ENetChannel * channel;
518 enet_uint16 startWindow, currentWindow;
519 ENetListIterator currentCommand;
520 ENetIncomingCommand * startCommand = NULL;
521
522 if (command -> header.channelID >= peer -> channelCount ||
523 (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
524 return -1;
525
526 fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
527 * currentData += fragmentLength;
528 if (fragmentLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE ||
529 * currentData < host -> receivedData ||
530 * currentData > & host -> receivedData [host -> receivedDataLength])
531 return -1;
532
533 channel = & peer -> channels [command -> header.channelID];
534 startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber);
535 startWindow = startSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
536 currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
537
538 if (startSequenceNumber < channel -> incomingReliableSequenceNumber)
539 startWindow += ENET_PEER_RELIABLE_WINDOWS;
540
541 if (startWindow < currentWindow || startWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
542 return 0;
543
544 fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
545 fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
546 fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
547 totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
548
549 if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
550 fragmentNumber >= fragmentCount ||
551 totalLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE ||
552 fragmentOffset >= totalLength ||
553 fragmentLength > totalLength - fragmentOffset)
554 return -1;
555
556 for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
557 currentCommand != enet_list_end (& channel -> incomingReliableCommands);
558 currentCommand = enet_list_previous (currentCommand))
559 {
560 ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
561
562 if (startSequenceNumber >= channel -> incomingReliableSequenceNumber)
563 {
564 if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
565 continue;
566 }
567 else
568 if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
569 break;
570
571 if (incomingCommand -> reliableSequenceNumber <= startSequenceNumber)
572 {
573 if (incomingCommand -> reliableSequenceNumber < startSequenceNumber)
574 break;
575
576 if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_FRAGMENT ||
577 totalLength != incomingCommand -> packet -> dataLength ||
578 fragmentCount != incomingCommand -> fragmentCount)
579 return -1;
580
581 startCommand = incomingCommand;
582 break;
583 }
584 }
585
586 if (startCommand == NULL)
587 {
588 ENetProtocol hostCommand = * command;
589 ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE);
590 if (packet == NULL)
591 return -1;
592
593 hostCommand.header.reliableSequenceNumber = startSequenceNumber;
594
595 startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, packet, fragmentCount);
596 if (startCommand == NULL)
597 return -1;
598 }
599
600 if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0)
601 {
602 -- startCommand -> fragmentsRemaining;
603
604 startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
605
606 if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
607 fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
608
609 memcpy (startCommand -> packet -> data + fragmentOffset,
610 (enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
611 fragmentLength);
612
613 if (startCommand -> fragmentsRemaining <= 0)
614 enet_peer_dispatch_incoming_reliable_commands (peer, channel);
615 }
616
617 return 0;
618 }
619
620 static int
enet_protocol_handle_send_unreliable_fragment(ENetHost * host,ENetPeer * peer,const ENetProtocol * command,enet_uint8 ** currentData)621 enet_protocol_handle_send_unreliable_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
622 {
623 enet_uint32 fragmentNumber,
624 fragmentCount,
625 fragmentOffset,
626 fragmentLength,
627 reliableSequenceNumber,
628 startSequenceNumber,
629 totalLength;
630 enet_uint16 reliableWindow, currentWindow;
631 ENetChannel * channel;
632 ENetListIterator currentCommand;
633 ENetIncomingCommand * startCommand = NULL;
634
635 if (command -> header.channelID >= peer -> channelCount ||
636 (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
637 return -1;
638
639 fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
640 * currentData += fragmentLength;
641 if (fragmentLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE ||
642 * currentData < host -> receivedData ||
643 * currentData > & host -> receivedData [host -> receivedDataLength])
644 return -1;
645
646 channel = & peer -> channels [command -> header.channelID];
647 reliableSequenceNumber = command -> header.reliableSequenceNumber;
648 startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber);
649
650 reliableWindow = reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
651 currentWindow = channel -> incomingReliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
652
653 if (reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
654 reliableWindow += ENET_PEER_RELIABLE_WINDOWS;
655
656 if (reliableWindow < currentWindow || reliableWindow >= currentWindow + ENET_PEER_FREE_RELIABLE_WINDOWS - 1)
657 return 0;
658
659 if (reliableSequenceNumber == channel -> incomingReliableSequenceNumber &&
660 startSequenceNumber <= channel -> incomingUnreliableSequenceNumber)
661 return 0;
662
663 fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
664 fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
665 fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
666 totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
667
668 if (fragmentCount > ENET_PROTOCOL_MAXIMUM_FRAGMENT_COUNT ||
669 fragmentNumber >= fragmentCount ||
670 totalLength > ENET_PROTOCOL_MAXIMUM_PACKET_SIZE ||
671 fragmentOffset >= totalLength ||
672 fragmentLength > totalLength - fragmentOffset)
673 return -1;
674
675 for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingUnreliableCommands));
676 currentCommand != enet_list_end (& channel -> incomingUnreliableCommands);
677 currentCommand = enet_list_previous (currentCommand))
678 {
679 ENetIncomingCommand * incomingCommand = (ENetIncomingCommand *) currentCommand;
680
681 if (reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
682 {
683 if (incomingCommand -> reliableSequenceNumber < channel -> incomingReliableSequenceNumber)
684 continue;
685 }
686 else
687 if (incomingCommand -> reliableSequenceNumber >= channel -> incomingReliableSequenceNumber)
688 break;
689
690 if (incomingCommand -> reliableSequenceNumber < reliableSequenceNumber)
691 break;
692
693 if (incomingCommand -> reliableSequenceNumber > reliableSequenceNumber)
694 continue;
695
696 if (incomingCommand -> unreliableSequenceNumber <= startSequenceNumber)
697 {
698 if (incomingCommand -> unreliableSequenceNumber < startSequenceNumber)
699 break;
700
701 if ((incomingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) != ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT ||
702 totalLength != incomingCommand -> packet -> dataLength ||
703 fragmentCount != incomingCommand -> fragmentCount)
704 return -1;
705
706 startCommand = incomingCommand;
707 break;
708 }
709 }
710
711 if (startCommand == NULL)
712 {
713 ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_UNRELIABLE_FRAGMENT);
714 if (packet == NULL)
715 return -1;
716
717 startCommand = enet_peer_queue_incoming_command (peer, command, packet, fragmentCount);
718 if (startCommand == NULL)
719 return -1;
720 }
721
722 if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0)
723 {
724 -- startCommand -> fragmentsRemaining;
725
726 startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
727
728 if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
729 fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
730
731 memcpy (startCommand -> packet -> data + fragmentOffset,
732 (enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
733 fragmentLength);
734
735 if (startCommand -> fragmentsRemaining <= 0)
736 enet_peer_dispatch_incoming_unreliable_commands (peer, channel);
737 }
738
739 return 0;
740 }
741
742 static int
enet_protocol_handle_ping(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)743 enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
744 {
745 return 0;
746 }
747
748 static int
enet_protocol_handle_bandwidth_limit(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)749 enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
750 {
751 peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth);
752 peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth);
753
754 if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0)
755 peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
756 else
757 peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) /
758 ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
759
760 if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
761 peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
762 else
763 if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
764 peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
765
766 return 0;
767 }
768
769 static int
enet_protocol_handle_throttle_configure(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)770 enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
771 {
772 peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval);
773 peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration);
774 peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration);
775
776 return 0;
777 }
778
779 static int
enet_protocol_handle_disconnect(ENetHost * host,ENetPeer * peer,const ENetProtocol * command)780 enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
781 {
782 if (peer -> state == ENET_PEER_STATE_ZOMBIE || peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT)
783 return 0;
784
785 enet_peer_reset_queues (peer);
786
787 if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED || peer -> state == ENET_PEER_STATE_DISCONNECTING)
788 enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
789 else
790 if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
791 {
792 if (peer -> state == ENET_PEER_STATE_CONNECTION_PENDING) host -> recalculateBandwidthLimits = 1;
793
794 enet_peer_reset (peer);
795 }
796 else
797 if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
798 peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT;
799 else
800 enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
801
802 if (peer -> state != ENET_PEER_STATE_DISCONNECTED)
803 peer -> eventData = ENET_NET_TO_HOST_32 (command -> disconnect.data);
804
805 return 0;
806 }
807
808 static int
enet_protocol_handle_acknowledge(ENetHost * host,ENetEvent * event,ENetPeer * peer,const ENetProtocol * command)809 enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
810 {
811 enet_uint32 roundTripTime,
812 receivedSentTime,
813 receivedReliableSequenceNumber;
814 ENetProtocolCommand commandNumber;
815
816 receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime);
817 receivedSentTime |= host -> serviceTime & 0xFFFF0000;
818 if ((receivedSentTime & 0x8000) > (host -> serviceTime & 0x8000))
819 receivedSentTime -= 0x10000;
820
821 if (ENET_TIME_LESS (host -> serviceTime, receivedSentTime))
822 return 0;
823
824 peer -> lastReceiveTime = host -> serviceTime;
825 peer -> earliestTimeout = 0;
826
827 roundTripTime = ENET_TIME_DIFFERENCE (host -> serviceTime, receivedSentTime);
828
829 enet_peer_throttle (peer, roundTripTime);
830
831 peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
832
833 if (roundTripTime >= peer -> roundTripTime)
834 {
835 peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
836 peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
837 }
838 else
839 {
840 peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
841 peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
842 }
843
844 if (peer -> roundTripTime < peer -> lowestRoundTripTime)
845 peer -> lowestRoundTripTime = peer -> roundTripTime;
846
847 if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance)
848 peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
849
850 if (peer -> packetThrottleEpoch == 0 ||
851 ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
852 {
853 peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
854 peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
855 peer -> lowestRoundTripTime = peer -> roundTripTime;
856 peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
857 peer -> packetThrottleEpoch = host -> serviceTime;
858 }
859
860 receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber);
861
862 commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
863
864 switch (peer -> state)
865 {
866 case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
867 if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT)
868 return -1;
869
870 enet_protocol_notify_connect (host, peer, event);
871 break;
872
873 case ENET_PEER_STATE_DISCONNECTING:
874 if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT)
875 return -1;
876
877 enet_protocol_notify_disconnect (host, peer, event);
878 break;
879
880 case ENET_PEER_STATE_DISCONNECT_LATER:
881 if (enet_list_empty (& peer -> outgoingReliableCommands) &&
882 enet_list_empty (& peer -> outgoingUnreliableCommands) &&
883 enet_list_empty (& peer -> sentReliableCommands))
884 enet_peer_disconnect (peer, peer -> eventData);
885 break;
886
887 default:
888 break;
889 }
890
891 return 0;
892 }
893
894 static int
enet_protocol_handle_verify_connect(ENetHost * host,ENetEvent * event,ENetPeer * peer,const ENetProtocol * command)895 enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
896 {
897 enet_uint32 mtu, windowSize;
898 size_t channelCount;
899
900 if (peer -> state != ENET_PEER_STATE_CONNECTING)
901 return 0;
902
903 channelCount = ENET_NET_TO_HOST_32 (command -> verifyConnect.channelCount);
904
905 if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT || channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT ||
906 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval ||
907 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleAcceleration) != peer -> packetThrottleAcceleration ||
908 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration ||
909 command -> verifyConnect.connectID != peer -> connectID)
910 {
911 peer -> eventData = 0;
912
913 enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
914
915 return -1;
916 }
917
918 enet_protocol_remove_sent_reliable_command (peer, 1, 0xFF);
919
920 if (channelCount < peer -> channelCount)
921 peer -> channelCount = channelCount;
922
923 peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID);
924 peer -> incomingSessionID = command -> verifyConnect.incomingSessionID;
925 peer -> outgoingSessionID = command -> verifyConnect.outgoingSessionID;
926
927 mtu = ENET_NET_TO_HOST_32 (command -> verifyConnect.mtu);
928
929 if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
930 mtu = ENET_PROTOCOL_MINIMUM_MTU;
931 else
932 if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
933 mtu = ENET_PROTOCOL_MAXIMUM_MTU;
934
935 if (mtu < peer -> mtu)
936 peer -> mtu = mtu;
937
938 windowSize = ENET_NET_TO_HOST_32 (command -> verifyConnect.windowSize);
939
940 if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
941 windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
942
943 if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
944 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
945
946 if (windowSize < peer -> windowSize)
947 peer -> windowSize = windowSize;
948
949 peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.incomingBandwidth);
950 peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.outgoingBandwidth);
951
952 enet_protocol_notify_connect (host, peer, event);
953 return 0;
954 }
955
956 static int
enet_protocol_handle_incoming_commands(ENetHost * host,ENetEvent * event)957 enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
958 {
959 ENetProtocolHeader * header;
960 ENetProtocol * command;
961 ENetPeer * peer;
962 enet_uint8 * currentData;
963 size_t headerSize;
964 enet_uint16 peerID, flags;
965 enet_uint8 sessionID;
966
967 if (host -> receivedDataLength < (size_t) & ((ENetProtocolHeader *) 0) -> sentTime)
968 return 0;
969
970 header = (ENetProtocolHeader *) host -> receivedData;
971
972 peerID = ENET_NET_TO_HOST_16 (header -> peerID);
973 sessionID = (peerID & ENET_PROTOCOL_HEADER_SESSION_MASK) >> ENET_PROTOCOL_HEADER_SESSION_SHIFT;
974 flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK;
975 peerID &= ~ (ENET_PROTOCOL_HEADER_FLAG_MASK | ENET_PROTOCOL_HEADER_SESSION_MASK);
976
977 headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof (ENetProtocolHeader) : (size_t) & ((ENetProtocolHeader *) 0) -> sentTime);
978 if (host -> checksum != NULL)
979 headerSize += sizeof (enet_uint32);
980
981 if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID)
982 peer = NULL;
983 else
984 if (peerID >= host -> peerCount)
985 return 0;
986 else
987 {
988 peer = & host -> peers [peerID];
989
990 if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
991 peer -> state == ENET_PEER_STATE_ZOMBIE ||
992 ((host -> receivedAddress.host != peer -> address.host ||
993 host -> receivedAddress.port != peer -> address.port) &&
994 peer -> address.host != ENET_HOST_BROADCAST) ||
995 (peer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID &&
996 sessionID != peer -> incomingSessionID))
997 return 0;
998 }
999
1000 if (flags & ENET_PROTOCOL_HEADER_FLAG_COMPRESSED)
1001 {
1002 size_t originalSize;
1003 if (host -> compressor.context == NULL || host -> compressor.decompress == NULL)
1004 return 0;
1005
1006 originalSize = host -> compressor.decompress (host -> compressor.context,
1007 host -> receivedData + headerSize,
1008 host -> receivedDataLength - headerSize,
1009 host -> packetData [1] + headerSize,
1010 sizeof (host -> packetData [1]) - headerSize);
1011 if (originalSize <= 0 || originalSize > sizeof (host -> packetData [1]) - headerSize)
1012 return 0;
1013
1014 memcpy (host -> packetData [1], header, headerSize);
1015 host -> receivedData = host -> packetData [1];
1016 host -> receivedDataLength = headerSize + originalSize;
1017 }
1018
1019 if (host -> checksum != NULL)
1020 {
1021 enet_uint32 * checksum = (enet_uint32 *) & host -> receivedData [headerSize - sizeof (enet_uint32)],
1022 desiredChecksum = * checksum;
1023 ENetBuffer buffer;
1024
1025 * checksum = peer != NULL ? peer -> connectID : 0;
1026
1027 buffer.data = host -> receivedData;
1028 buffer.dataLength = host -> receivedDataLength;
1029
1030 if (host -> checksum (& buffer, 1) != desiredChecksum)
1031 return 0;
1032 }
1033
1034 if (peer != NULL)
1035 {
1036 peer -> address.host = host -> receivedAddress.host;
1037 peer -> address.port = host -> receivedAddress.port;
1038 peer -> incomingDataTotal += host -> receivedDataLength;
1039 }
1040
1041 currentData = host -> receivedData + headerSize;
1042
1043 while (currentData < & host -> receivedData [host -> receivedDataLength])
1044 {
1045 enet_uint8 commandNumber;
1046 size_t commandSize;
1047
1048 command = (ENetProtocol *) currentData;
1049
1050 if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength])
1051 break;
1052
1053 commandNumber = command -> header.command & ENET_PROTOCOL_COMMAND_MASK;
1054 if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT)
1055 break;
1056
1057 commandSize = commandSizes [commandNumber];
1058 if (commandSize == 0 || currentData + commandSize > & host -> receivedData [host -> receivedDataLength])
1059 break;
1060
1061 currentData += commandSize;
1062
1063 if (peer == NULL && commandNumber != ENET_PROTOCOL_COMMAND_CONNECT)
1064 break;
1065
1066 command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber);
1067
1068 switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
1069 {
1070 case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE:
1071 if (enet_protocol_handle_acknowledge (host, event, peer, command))
1072 goto commandError;
1073 break;
1074
1075 case ENET_PROTOCOL_COMMAND_CONNECT:
1076 peer = enet_protocol_handle_connect (host, header, command);
1077 if (peer == NULL)
1078 goto commandError;
1079 break;
1080
1081 case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT:
1082 if (enet_protocol_handle_verify_connect (host, event, peer, command))
1083 goto commandError;
1084 break;
1085
1086 case ENET_PROTOCOL_COMMAND_DISCONNECT:
1087 if (enet_protocol_handle_disconnect (host, peer, command))
1088 goto commandError;
1089 break;
1090
1091 case ENET_PROTOCOL_COMMAND_PING:
1092 if (enet_protocol_handle_ping (host, peer, command))
1093 goto commandError;
1094 break;
1095
1096 case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
1097 if (enet_protocol_handle_send_reliable (host, peer, command, & currentData))
1098 goto commandError;
1099 break;
1100
1101 case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
1102 if (enet_protocol_handle_send_unreliable (host, peer, command, & currentData))
1103 goto commandError;
1104 break;
1105
1106 case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
1107 if (enet_protocol_handle_send_unsequenced (host, peer, command, & currentData))
1108 goto commandError;
1109 break;
1110
1111 case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
1112 if (enet_protocol_handle_send_fragment (host, peer, command, & currentData))
1113 goto commandError;
1114 break;
1115
1116 case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT:
1117 if (enet_protocol_handle_bandwidth_limit (host, peer, command))
1118 goto commandError;
1119 break;
1120
1121 case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE:
1122 if (enet_protocol_handle_throttle_configure (host, peer, command))
1123 goto commandError;
1124 break;
1125
1126 case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE_FRAGMENT:
1127 if (enet_protocol_handle_send_unreliable_fragment (host, peer, command, & currentData))
1128 goto commandError;
1129 break;
1130
1131 default:
1132 goto commandError;
1133 }
1134
1135 if (peer != NULL &&
1136 (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0)
1137 {
1138 enet_uint16 sentTime;
1139
1140 if (! (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME))
1141 break;
1142
1143 sentTime = ENET_NET_TO_HOST_16 (header -> sentTime);
1144
1145 switch (peer -> state)
1146 {
1147 case ENET_PEER_STATE_DISCONNECTING:
1148 case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
1149 break;
1150
1151 case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT:
1152 if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
1153 enet_peer_queue_acknowledgement (peer, command, sentTime);
1154 break;
1155
1156 default:
1157 enet_peer_queue_acknowledgement (peer, command, sentTime);
1158 break;
1159 }
1160 }
1161 }
1162
1163 commandError:
1164 if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1165 return 1;
1166
1167 return 0;
1168 }
1169
1170 static int
enet_protocol_receive_incoming_commands(ENetHost * host,ENetEvent * event)1171 enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
1172 {
1173 for (;;)
1174 {
1175 int receivedLength;
1176 ENetBuffer buffer;
1177
1178 buffer.data = host -> packetData [0];
1179 buffer.dataLength = sizeof (host -> packetData [0]);
1180
1181 receivedLength = enet_socket_receive (host -> socket,
1182 & host -> receivedAddress,
1183 & buffer,
1184 1);
1185
1186 if (receivedLength < 0)
1187 return -1;
1188
1189 if (receivedLength == 0)
1190 return 0;
1191
1192 host -> receivedData = host -> packetData [0];
1193 host -> receivedDataLength = receivedLength;
1194
1195 host -> totalReceivedData += receivedLength;
1196 host -> totalReceivedPackets ++;
1197
1198 if (host -> intercept != NULL)
1199 {
1200 switch (host -> intercept (host, event))
1201 {
1202 case 1:
1203 if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1204 return 1;
1205
1206 continue;
1207
1208 case -1:
1209 return -1;
1210
1211 default:
1212 break;
1213 }
1214 }
1215
1216 switch (enet_protocol_handle_incoming_commands (host, event))
1217 {
1218 case 1:
1219 return 1;
1220
1221 case -1:
1222 return -1;
1223
1224 default:
1225 break;
1226 }
1227 }
1228
1229 return -1;
1230 }
1231
1232 static void
enet_protocol_send_acknowledgements(ENetHost * host,ENetPeer * peer)1233 enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
1234 {
1235 ENetProtocol * command = & host -> commands [host -> commandCount];
1236 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1237 ENetAcknowledgement * acknowledgement;
1238 ENetListIterator currentAcknowledgement;
1239
1240 currentAcknowledgement = enet_list_begin (& peer -> acknowledgements);
1241
1242 while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements))
1243 {
1244 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1245 buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1246 peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
1247 {
1248 host -> continueSending = 1;
1249
1250 break;
1251 }
1252
1253 acknowledgement = (ENetAcknowledgement *) currentAcknowledgement;
1254
1255 currentAcknowledgement = enet_list_next (currentAcknowledgement);
1256
1257 buffer -> data = command;
1258 buffer -> dataLength = sizeof (ENetProtocolAcknowledge);
1259
1260 host -> packetSize += buffer -> dataLength;
1261
1262 command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE;
1263 command -> header.channelID = acknowledgement -> command.header.channelID;
1264 command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber);
1265 command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime);
1266
1267 if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
1268 enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
1269
1270 enet_list_remove (& acknowledgement -> acknowledgementList);
1271 enet_free (acknowledgement);
1272
1273 ++ command;
1274 ++ buffer;
1275 }
1276
1277 host -> commandCount = command - host -> commands;
1278 host -> bufferCount = buffer - host -> buffers;
1279 }
1280
1281 static void
enet_protocol_send_unreliable_outgoing_commands(ENetHost * host,ENetPeer * peer)1282 enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
1283 {
1284 ENetProtocol * command = & host -> commands [host -> commandCount];
1285 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1286 ENetOutgoingCommand * outgoingCommand;
1287 ENetListIterator currentCommand;
1288
1289 currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
1290
1291 while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
1292 {
1293 size_t commandSize;
1294
1295 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1296 commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
1297
1298 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1299 buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1300 peer -> mtu - host -> packetSize < commandSize ||
1301 (outgoingCommand -> packet != NULL &&
1302 peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> fragmentLength))
1303 {
1304 host -> continueSending = 1;
1305
1306 break;
1307 }
1308
1309 currentCommand = enet_list_next (currentCommand);
1310
1311 if (outgoingCommand -> packet != NULL && outgoingCommand -> fragmentOffset == 0)
1312 {
1313 peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
1314 peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
1315
1316 if (peer -> packetThrottleCounter > peer -> packetThrottle)
1317 {
1318 enet_uint16 reliableSequenceNumber = outgoingCommand -> reliableSequenceNumber,
1319 unreliableSequenceNumber = outgoingCommand -> unreliableSequenceNumber;
1320 for (;;)
1321 {
1322 -- outgoingCommand -> packet -> referenceCount;
1323
1324 if (outgoingCommand -> packet -> referenceCount == 0)
1325 enet_packet_destroy (outgoingCommand -> packet);
1326
1327 enet_list_remove (& outgoingCommand -> outgoingCommandList);
1328 enet_free (outgoingCommand);
1329
1330 if (currentCommand == enet_list_end (& peer -> outgoingUnreliableCommands))
1331 break;
1332
1333 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1334 if (outgoingCommand -> reliableSequenceNumber != reliableSequenceNumber ||
1335 outgoingCommand -> unreliableSequenceNumber != unreliableSequenceNumber)
1336 break;
1337
1338 currentCommand = enet_list_next (currentCommand);
1339 }
1340
1341 continue;
1342 }
1343 }
1344
1345 buffer -> data = command;
1346 buffer -> dataLength = commandSize;
1347
1348 host -> packetSize += buffer -> dataLength;
1349
1350 * command = outgoingCommand -> command;
1351
1352 enet_list_remove (& outgoingCommand -> outgoingCommandList);
1353
1354 if (outgoingCommand -> packet != NULL)
1355 {
1356 ++ buffer;
1357
1358 buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1359 buffer -> dataLength = outgoingCommand -> fragmentLength;
1360
1361 host -> packetSize += buffer -> dataLength;
1362
1363 enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
1364 }
1365 else
1366 enet_free (outgoingCommand);
1367
1368 ++ command;
1369 ++ buffer;
1370 }
1371
1372 host -> commandCount = command - host -> commands;
1373 host -> bufferCount = buffer - host -> buffers;
1374
1375 if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER &&
1376 enet_list_empty (& peer -> outgoingReliableCommands) &&
1377 enet_list_empty (& peer -> outgoingUnreliableCommands) &&
1378 enet_list_empty (& peer -> sentReliableCommands))
1379 enet_peer_disconnect (peer, peer -> eventData);
1380 }
1381
1382 static int
enet_protocol_check_timeouts(ENetHost * host,ENetPeer * peer,ENetEvent * event)1383 enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
1384 {
1385 ENetOutgoingCommand * outgoingCommand;
1386 ENetListIterator currentCommand, insertPosition;
1387
1388 currentCommand = enet_list_begin (& peer -> sentReliableCommands);
1389 insertPosition = enet_list_begin (& peer -> outgoingReliableCommands);
1390
1391 while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
1392 {
1393 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1394
1395 currentCommand = enet_list_next (currentCommand);
1396
1397 if (ENET_TIME_DIFFERENCE (host -> serviceTime, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
1398 continue;
1399
1400 if (peer -> earliestTimeout == 0 ||
1401 ENET_TIME_LESS (outgoingCommand -> sentTime, peer -> earliestTimeout))
1402 peer -> earliestTimeout = outgoingCommand -> sentTime;
1403
1404 if (peer -> earliestTimeout != 0 &&
1405 (ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMaximum ||
1406 (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
1407 ENET_TIME_DIFFERENCE (host -> serviceTime, peer -> earliestTimeout) >= peer -> timeoutMinimum)))
1408 {
1409 enet_protocol_notify_disconnect (host, peer, event);
1410
1411 return 1;
1412 }
1413
1414 if (outgoingCommand -> packet != NULL)
1415 peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
1416
1417 ++ peer -> packetsLost;
1418
1419 outgoingCommand -> roundTripTimeout *= 2;
1420
1421 enet_list_insert (insertPosition, enet_list_remove (& outgoingCommand -> outgoingCommandList));
1422
1423 if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
1424 ! enet_list_empty (& peer -> sentReliableCommands))
1425 {
1426 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1427
1428 peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
1429 }
1430 }
1431
1432 return 0;
1433 }
1434
1435 static int
enet_protocol_send_reliable_outgoing_commands(ENetHost * host,ENetPeer * peer)1436 enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
1437 {
1438 ENetProtocol * command = & host -> commands [host -> commandCount];
1439 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1440 ENetOutgoingCommand * outgoingCommand;
1441 ENetListIterator currentCommand;
1442 ENetChannel *channel;
1443 enet_uint16 reliableWindow;
1444 size_t commandSize;
1445 int windowExceeded = 0, windowWrap = 0, canPing = 1;
1446
1447 currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
1448
1449 while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
1450 {
1451 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1452
1453 channel = outgoingCommand -> command.header.channelID < peer -> channelCount ? & peer -> channels [outgoingCommand -> command.header.channelID] : NULL;
1454 reliableWindow = outgoingCommand -> reliableSequenceNumber / ENET_PEER_RELIABLE_WINDOW_SIZE;
1455 if (channel != NULL)
1456 {
1457 if (! windowWrap &&
1458 outgoingCommand -> sendAttempts < 1 &&
1459 ! (outgoingCommand -> reliableSequenceNumber % ENET_PEER_RELIABLE_WINDOW_SIZE) &&
1460 (channel -> reliableWindows [(reliableWindow + ENET_PEER_RELIABLE_WINDOWS - 1) % ENET_PEER_RELIABLE_WINDOWS] >= ENET_PEER_RELIABLE_WINDOW_SIZE ||
1461 channel -> usedReliableWindows & ((((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) << reliableWindow) |
1462 (((1 << ENET_PEER_FREE_RELIABLE_WINDOWS) - 1) >> (ENET_PEER_RELIABLE_WINDOW_SIZE - reliableWindow)))))
1463 windowWrap = 1;
1464 if (windowWrap)
1465 {
1466 currentCommand = enet_list_next (currentCommand);
1467
1468 continue;
1469 }
1470 }
1471
1472 if (outgoingCommand -> packet != NULL)
1473 {
1474 if (! windowExceeded)
1475 {
1476 enet_uint32 windowSize = (peer -> packetThrottle * peer -> windowSize) / ENET_PEER_PACKET_THROTTLE_SCALE;
1477
1478 if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > ENET_MAX (windowSize, peer -> mtu))
1479 windowExceeded = 1;
1480 }
1481 if (windowExceeded)
1482 {
1483 currentCommand = enet_list_next (currentCommand);
1484
1485 continue;
1486 }
1487 }
1488
1489 canPing = 0;
1490
1491 commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
1492 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1493 buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1494 peer -> mtu - host -> packetSize < commandSize ||
1495 (outgoingCommand -> packet != NULL &&
1496 (enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength)))
1497 {
1498 host -> continueSending = 1;
1499
1500 break;
1501 }
1502
1503 currentCommand = enet_list_next (currentCommand);
1504
1505 if (channel != NULL && outgoingCommand -> sendAttempts < 1)
1506 {
1507 channel -> usedReliableWindows |= 1 << reliableWindow;
1508 ++ channel -> reliableWindows [reliableWindow];
1509 }
1510
1511 ++ outgoingCommand -> sendAttempts;
1512
1513 if (outgoingCommand -> roundTripTimeout == 0)
1514 {
1515 outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
1516 outgoingCommand -> roundTripTimeoutLimit = peer -> timeoutLimit * outgoingCommand -> roundTripTimeout;
1517 }
1518
1519 if (enet_list_empty (& peer -> sentReliableCommands))
1520 peer -> nextTimeout = host -> serviceTime + outgoingCommand -> roundTripTimeout;
1521
1522 enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
1523 enet_list_remove (& outgoingCommand -> outgoingCommandList));
1524
1525 outgoingCommand -> sentTime = host -> serviceTime;
1526
1527 buffer -> data = command;
1528 buffer -> dataLength = commandSize;
1529
1530 host -> packetSize += buffer -> dataLength;
1531 host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
1532
1533 * command = outgoingCommand -> command;
1534
1535 if (outgoingCommand -> packet != NULL)
1536 {
1537 ++ buffer;
1538
1539 buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1540 buffer -> dataLength = outgoingCommand -> fragmentLength;
1541
1542 host -> packetSize += outgoingCommand -> fragmentLength;
1543
1544 peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
1545 }
1546
1547 ++ peer -> packetsSent;
1548
1549 ++ command;
1550 ++ buffer;
1551 }
1552
1553 host -> commandCount = command - host -> commands;
1554 host -> bufferCount = buffer - host -> buffers;
1555
1556 return canPing;
1557 }
1558
1559 static int
enet_protocol_send_outgoing_commands(ENetHost * host,ENetEvent * event,int checkForTimeouts)1560 enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
1561 {
1562 enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
1563 ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
1564 ENetPeer * currentPeer;
1565 int sentLength;
1566 size_t shouldCompress = 0;
1567
1568 host -> continueSending = 1;
1569
1570 while (host -> continueSending)
1571 for (host -> continueSending = 0,
1572 currentPeer = host -> peers;
1573 currentPeer < & host -> peers [host -> peerCount];
1574 ++ currentPeer)
1575 {
1576 if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
1577 currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
1578 continue;
1579
1580 host -> headerFlags = 0;
1581 host -> commandCount = 0;
1582 host -> bufferCount = 1;
1583 host -> packetSize = sizeof (ENetProtocolHeader);
1584
1585 if (! enet_list_empty (& currentPeer -> acknowledgements))
1586 enet_protocol_send_acknowledgements (host, currentPeer);
1587
1588 if (checkForTimeouts != 0 &&
1589 ! enet_list_empty (& currentPeer -> sentReliableCommands) &&
1590 ENET_TIME_GREATER_EQUAL (host -> serviceTime, currentPeer -> nextTimeout) &&
1591 enet_protocol_check_timeouts (host, currentPeer, event) == 1)
1592 {
1593 if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
1594 return 1;
1595 else
1596 continue;
1597 }
1598
1599 if ((enet_list_empty (& currentPeer -> outgoingReliableCommands) ||
1600 enet_protocol_send_reliable_outgoing_commands (host, currentPeer)) &&
1601 enet_list_empty (& currentPeer -> sentReliableCommands) &&
1602 ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> lastReceiveTime) >= currentPeer -> pingInterval &&
1603 currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
1604 {
1605 enet_peer_ping (currentPeer);
1606 enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1607 }
1608
1609 if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
1610 enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
1611
1612 if (host -> commandCount == 0)
1613 continue;
1614
1615 if (currentPeer -> packetLossEpoch == 0)
1616 currentPeer -> packetLossEpoch = host -> serviceTime;
1617 else
1618 if (ENET_TIME_DIFFERENCE (host -> serviceTime, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
1619 currentPeer -> packetsSent > 0)
1620 {
1621 enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
1622
1623 #ifdef ENET_DEBUG
1624 #ifdef WIN32
1625 printf (
1626 #else
1627 fprintf (stderr,
1628 #endif
1629 "peer %u: %f%%+-%f%% packet loss, %u+-%u ms round trip time, %f%% throttle, %u/%u outgoing, %u/%u incoming\n", currentPeer -> incomingPeerID, currentPeer -> packetLoss / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> packetLossVariance / (float) ENET_PEER_PACKET_LOSS_SCALE, currentPeer -> roundTripTime, currentPeer -> roundTripTimeVariance, currentPeer -> packetThrottle / (float) ENET_PEER_PACKET_THROTTLE_SCALE, enet_list_size (& currentPeer -> outgoingReliableCommands), enet_list_size (& currentPeer -> outgoingUnreliableCommands), currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingReliableCommands) : 0, currentPeer -> channels != NULL ? enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands) : 0);
1630 #endif
1631
1632 currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
1633
1634 if (packetLoss >= currentPeer -> packetLoss)
1635 {
1636 currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
1637 currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
1638 }
1639 else
1640 {
1641 currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
1642 currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
1643 }
1644
1645 currentPeer -> packetLossEpoch = host -> serviceTime;
1646 currentPeer -> packetsSent = 0;
1647 currentPeer -> packetsLost = 0;
1648 }
1649
1650 host -> buffers -> data = headerData;
1651 if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)
1652 {
1653 header -> sentTime = ENET_HOST_TO_NET_16 (host -> serviceTime & 0xFFFF);
1654
1655 host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
1656 }
1657 else
1658 host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime;
1659
1660 shouldCompress = 0;
1661 if (host -> compressor.context != NULL && host -> compressor.compress != NULL)
1662 {
1663 size_t originalSize = host -> packetSize - sizeof(ENetProtocolHeader),
1664 compressedSize = host -> compressor.compress (host -> compressor.context,
1665 & host -> buffers [1], host -> bufferCount - 1,
1666 originalSize,
1667 host -> packetData [1],
1668 originalSize);
1669 if (compressedSize > 0 && compressedSize < originalSize)
1670 {
1671 host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_COMPRESSED;
1672 shouldCompress = compressedSize;
1673 #ifdef ENET_DEBUG_COMPRESS
1674 #ifdef WIN32
1675 printf (
1676 #else
1677 fprintf (stderr,
1678 #endif
1679 "peer %u: compressed %u -> %u (%u%%)\n", currentPeer -> incomingPeerID, originalSize, compressedSize, (compressedSize * 100) / originalSize);
1680 #endif
1681 }
1682 }
1683
1684 if (currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID)
1685 host -> headerFlags |= currentPeer -> outgoingSessionID << ENET_PROTOCOL_HEADER_SESSION_SHIFT;
1686 header -> peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags);
1687 if (host -> checksum != NULL)
1688 {
1689 enet_uint32 * checksum = (enet_uint32 *) & headerData [host -> buffers -> dataLength];
1690 * checksum = currentPeer -> outgoingPeerID < ENET_PROTOCOL_MAXIMUM_PEER_ID ? currentPeer -> connectID : 0;
1691 host -> buffers -> dataLength += sizeof (enet_uint32);
1692 * checksum = host -> checksum (host -> buffers, host -> bufferCount);
1693 }
1694
1695 if (shouldCompress > 0)
1696 {
1697 host -> buffers [1].data = host -> packetData [1];
1698 host -> buffers [1].dataLength = shouldCompress;
1699 host -> bufferCount = 2;
1700 }
1701
1702 currentPeer -> lastSendTime = host -> serviceTime;
1703
1704 sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
1705
1706 enet_protocol_remove_sent_unreliable_commands (currentPeer);
1707
1708 if (sentLength < 0)
1709 return -1;
1710
1711 host -> totalSentData += sentLength;
1712 host -> totalSentPackets ++;
1713 }
1714
1715 return 0;
1716 }
1717
1718 /** Sends any queued packets on the host specified to its designated peers.
1719
1720 @param host host to flush
1721 @remarks this function need only be used in circumstances where one wishes to send queued packets earlier than in a call to enet_host_service().
1722 @ingroup host
1723 */
1724 void
enet_host_flush(ENetHost * host)1725 enet_host_flush (ENetHost * host)
1726 {
1727 host -> serviceTime = enet_time_get ();
1728
1729 enet_protocol_send_outgoing_commands (host, NULL, 0);
1730 }
1731
1732 /** Checks for any queued events on the host and dispatches one if available.
1733
1734 @param host host to check for events
1735 @param event an event structure where event details will be placed if available
1736 @retval > 0 if an event was dispatched
1737 @retval 0 if no events are available
1738 @retval < 0 on failure
1739 @ingroup host
1740 */
1741 int
enet_host_check_events(ENetHost * host,ENetEvent * event)1742 enet_host_check_events (ENetHost * host, ENetEvent * event)
1743 {
1744 if (event == NULL) return -1;
1745
1746 event -> type = ENET_EVENT_TYPE_NONE;
1747 event -> peer = NULL;
1748 event -> packet = NULL;
1749
1750 return enet_protocol_dispatch_incoming_commands (host, event);
1751 }
1752
1753 /** Waits for events on the host specified and shuttles packets between
1754 the host and its peers.
1755
1756 @param host host to service
1757 @param event an event structure where event details will be placed if one occurs
1758 if event == NULL then no events will be delivered
1759 @param timeout number of milliseconds that ENet should wait for events
1760 @retval > 0 if an event occurred within the specified time limit
1761 @retval 0 if no event occurred
1762 @retval < 0 on failure
1763 @remarks enet_host_service should be called fairly regularly for adequate performance
1764 @ingroup host
1765 */
1766 int
enet_host_service(ENetHost * host,ENetEvent * event,enet_uint32 timeout)1767 enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
1768 {
1769 enet_uint32 waitCondition;
1770
1771 if (event != NULL)
1772 {
1773 event -> type = ENET_EVENT_TYPE_NONE;
1774 event -> peer = NULL;
1775 event -> packet = NULL;
1776
1777 switch (enet_protocol_dispatch_incoming_commands (host, event))
1778 {
1779 case 1:
1780 return 1;
1781
1782 case -1:
1783 perror ("Error dispatching incoming packets");
1784
1785 return -1;
1786
1787 default:
1788 break;
1789 }
1790 }
1791
1792 host -> serviceTime = enet_time_get ();
1793
1794 timeout += host -> serviceTime;
1795
1796 do
1797 {
1798 if (ENET_TIME_DIFFERENCE (host -> serviceTime, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
1799 enet_host_bandwidth_throttle (host);
1800
1801 switch (enet_protocol_send_outgoing_commands (host, event, 1))
1802 {
1803 case 1:
1804 return 1;
1805
1806 case -1:
1807 perror ("Error sending outgoing packets");
1808
1809 return -1;
1810
1811 default:
1812 break;
1813 }
1814
1815 switch (enet_protocol_receive_incoming_commands (host, event))
1816 {
1817 case 1:
1818 return 1;
1819
1820 case -1:
1821 perror ("Error receiving incoming packets");
1822
1823 return -1;
1824
1825 default:
1826 break;
1827 }
1828
1829 switch (enet_protocol_send_outgoing_commands (host, event, 1))
1830 {
1831 case 1:
1832 return 1;
1833
1834 case -1:
1835 perror ("Error sending outgoing packets");
1836
1837 return -1;
1838
1839 default:
1840 break;
1841 }
1842
1843 if (event != NULL)
1844 {
1845 switch (enet_protocol_dispatch_incoming_commands (host, event))
1846 {
1847 case 1:
1848 return 1;
1849
1850 case -1:
1851 perror ("Error dispatching incoming packets");
1852
1853 return -1;
1854
1855 default:
1856 break;
1857 }
1858 }
1859
1860 host -> serviceTime = enet_time_get ();
1861
1862 if (ENET_TIME_GREATER_EQUAL (host -> serviceTime, timeout))
1863 return 0;
1864
1865 waitCondition = ENET_SOCKET_WAIT_RECEIVE;
1866
1867 if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, host -> serviceTime)) != 0)
1868 return -1;
1869
1870 host -> serviceTime = enet_time_get ();
1871 } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE);
1872
1873 return 0;
1874 }
1875
1876