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