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