Forgot to commit changelog with my last set of changes
[crack-attack.git] / enet / protocol.c
blob75cdd6405b6226b49c00404d0e10fd541c881b72
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"
12 static enet_uint32 timeCurrent;
14 static int
15 enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
17 ENetPeer * currentPeer = host -> lastServicedPeer;
18 ENetChannel * channel;
22 ++ currentPeer;
24 if (currentPeer >= & host -> peers [host -> peerCount])
25 currentPeer = host -> peers;
27 switch (currentPeer -> state)
29 case ENET_PEER_STATE_CONNECTION_PENDING:
30 currentPeer -> state = ENET_PEER_STATE_CONNECTED;
32 event -> type = ENET_EVENT_TYPE_CONNECT;
33 event -> peer = currentPeer;
35 return 1;
37 case ENET_PEER_STATE_ZOMBIE:
38 host -> recalculateBandwidthLimits = 1;
40 event -> type = ENET_EVENT_TYPE_DISCONNECT;
41 event -> peer = currentPeer;
42 event -> data = currentPeer -> disconnectData;
44 enet_peer_reset (currentPeer);
46 host -> lastServicedPeer = currentPeer;
48 return 1;
51 if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
52 continue;
54 for (channel = currentPeer -> channels;
55 channel < & currentPeer -> channels [currentPeer -> channelCount];
56 ++ channel)
58 if (enet_list_empty (& channel -> incomingReliableCommands) &&
59 enet_list_empty (& channel -> incomingUnreliableCommands))
60 continue;
62 event -> packet = enet_peer_receive (currentPeer, channel - currentPeer -> channels);
63 if (event -> packet == NULL)
64 continue;
66 event -> type = ENET_EVENT_TYPE_RECEIVE;
67 event -> peer = currentPeer;
68 event -> channelID = (enet_uint8) (channel - currentPeer -> channels);
70 host -> lastServicedPeer = currentPeer;
72 return 1;
74 } while (currentPeer != host -> lastServicedPeer);
76 return 0;
79 static void
80 enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
82 host -> recalculateBandwidthLimits = 1;
84 if (event == NULL)
85 peer -> state = ENET_PEER_STATE_CONNECTION_PENDING;
86 else
88 peer -> state = ENET_PEER_STATE_CONNECTED;
90 event -> type = ENET_EVENT_TYPE_CONNECT;
91 event -> peer = peer;
95 static void
96 enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
98 if (peer -> state >= ENET_PEER_STATE_CONNECTION_PENDING)
99 host -> recalculateBandwidthLimits = 1;
101 if (peer -> state < ENET_PEER_STATE_CONNECTED)
102 enet_peer_reset (peer);
103 else
104 if (event == NULL)
105 peer -> state = ENET_PEER_STATE_ZOMBIE;
106 else
108 event -> type = ENET_EVENT_TYPE_DISCONNECT;
109 event -> peer = peer;
110 event -> data = 0;
112 enet_peer_reset (peer);
116 static void
117 enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
119 ENetOutgoingCommand * outgoingCommand;
121 while (enet_list_empty (& peer -> sentUnreliableCommands) == 0)
123 outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
125 enet_list_remove (& outgoingCommand -> outgoingCommandList);
127 if (outgoingCommand -> packet != NULL)
129 -- outgoingCommand -> packet -> referenceCount;
131 if (outgoingCommand -> packet -> referenceCount == 0)
132 enet_packet_destroy (outgoingCommand -> packet);
135 enet_free (outgoingCommand);
139 static ENetProtocolCommand
140 enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint32 reliableSequenceNumber, enet_uint8 channelID)
142 ENetOutgoingCommand * outgoingCommand;
143 ENetListIterator currentCommand;
144 ENetProtocolCommand commandNumber;
146 for (currentCommand = enet_list_begin (& peer -> sentReliableCommands);
147 currentCommand != enet_list_end (& peer -> sentReliableCommands);
148 currentCommand = enet_list_next (currentCommand))
150 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
152 if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
153 outgoingCommand -> command.header.channelID == channelID)
154 break;
157 if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
158 return ENET_PROTOCOL_COMMAND_NONE;
160 commandNumber = outgoingCommand -> command.header.command;
162 enet_list_remove (& outgoingCommand -> outgoingCommandList);
164 if (outgoingCommand -> packet != NULL)
166 peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
168 -- outgoingCommand -> packet -> referenceCount;
170 if (outgoingCommand -> packet -> referenceCount == 0)
171 enet_packet_destroy (outgoingCommand -> packet);
174 enet_free (outgoingCommand);
176 if (enet_list_empty (& peer -> sentReliableCommands))
177 return commandNumber;
179 outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentReliableCommands);
181 peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
183 return commandNumber;
186 static ENetPeer *
187 enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header, const ENetProtocol * command)
189 enet_uint16 mtu;
190 enet_uint32 windowSize;
191 ENetChannel * channel;
192 size_t channelCount;
193 ENetPeer * currentPeer;
194 ENetProtocol verifyCommand;
196 if (command -> header.commandLength < sizeof (ENetProtocolConnect))
197 return NULL;
199 channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount);
201 if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT ||
202 channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
203 return NULL;
205 for (currentPeer = host -> peers;
206 currentPeer < & host -> peers [host -> peerCount];
207 ++ currentPeer)
209 if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED &&
210 currentPeer -> address.host == host -> receivedAddress.host &&
211 currentPeer -> address.port == host -> receivedAddress.port &&
212 currentPeer -> challenge == header -> challenge)
213 return NULL;
216 for (currentPeer = host -> peers;
217 currentPeer < & host -> peers [host -> peerCount];
218 ++ currentPeer)
220 if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
221 break;
224 if (currentPeer >= & host -> peers [host -> peerCount])
225 return NULL;
227 currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
228 currentPeer -> challenge = header -> challenge;
229 currentPeer -> address = host -> receivedAddress;
230 currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
231 currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
232 currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth);
233 currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval);
234 currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration);
235 currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration);
236 currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
237 currentPeer -> channelCount = channelCount;
239 for (channel = currentPeer -> channels;
240 channel < & currentPeer -> channels [channelCount];
241 ++ channel)
243 channel -> outgoingReliableSequenceNumber = 0;
244 channel -> outgoingUnreliableSequenceNumber = 0;
245 channel -> incomingReliableSequenceNumber = 0;
246 channel -> incomingUnreliableSequenceNumber = 0;
248 enet_list_clear (& channel -> incomingReliableCommands);
249 enet_list_clear (& channel -> incomingUnreliableCommands);
252 mtu = ENET_NET_TO_HOST_16 (command -> connect.mtu);
254 if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
255 mtu = ENET_PROTOCOL_MINIMUM_MTU;
256 else
257 if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
258 mtu = ENET_PROTOCOL_MAXIMUM_MTU;
260 currentPeer -> mtu = mtu;
262 if (host -> outgoingBandwidth == 0 &&
263 currentPeer -> incomingBandwidth == 0)
264 currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
265 else
266 currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) /
267 ENET_PEER_WINDOW_SIZE_SCALE) *
268 ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
270 if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
271 currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
272 else
273 if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
274 currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
276 if (host -> incomingBandwidth == 0)
277 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
278 else
279 windowSize = (host -> incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) *
280 ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
282 if (windowSize > ENET_NET_TO_HOST_32 (command -> connect.windowSize))
283 windowSize = ENET_NET_TO_HOST_32 (command -> connect.windowSize);
285 if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
286 windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
287 else
288 if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
289 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
291 verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT;
292 verifyCommand.header.channelID = 0xFF;
293 verifyCommand.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
294 verifyCommand.header.commandLength = sizeof (ENetProtocolVerifyConnect);
295 verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
296 verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu);
297 verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize);
298 verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
299 verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
300 verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
301 verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
302 verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
303 verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
305 enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0);
307 return currentPeer;
310 static void
311 enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
313 ENetPacket * packet;
315 if (command -> header.commandLength <= sizeof (ENetProtocolSendReliable) ||
316 command -> header.channelID >= peer -> channelCount ||
317 peer -> state != ENET_PEER_STATE_CONNECTED)
318 return;
320 packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable),
321 command -> header.commandLength - sizeof (ENetProtocolSendReliable),
322 ENET_PACKET_FLAG_RELIABLE);
324 enet_peer_queue_incoming_command (peer, command, packet, 0);
327 static void
328 enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
330 ENetPacket * packet;
331 enet_uint32 unsequencedGroup, index;
333 if (command -> header.commandLength <= sizeof (ENetProtocolSendUnsequenced) ||
334 command -> header.channelID >= peer -> channelCount ||
335 peer -> state != ENET_PEER_STATE_CONNECTED)
336 return;
338 unsequencedGroup = ENET_NET_TO_HOST_32 (command -> sendUnsequenced.unsequencedGroup);
339 index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE;
341 if (unsequencedGroup >= peer -> incomingUnsequencedGroup + ENET_PEER_UNSEQUENCED_WINDOW_SIZE)
343 peer -> incomingUnsequencedGroup = unsequencedGroup - index;
345 memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
347 else
348 if (unsequencedGroup < peer -> incomingUnsequencedGroup ||
349 peer -> unsequencedWindow [index / 32] & (1 << (index % 32)))
350 return;
352 peer -> unsequencedWindow [index / 32] |= 1 << (index % 32);
355 packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced),
356 command -> header.commandLength - sizeof (ENetProtocolSendUnsequenced),
357 ENET_PACKET_FLAG_UNSEQUENCED);
359 enet_peer_queue_incoming_command (peer, command, packet, 0);
362 static void
363 enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
365 ENetPacket * packet;
367 if (command -> header.commandLength <= sizeof (ENetProtocolSendUnreliable) ||
368 command -> header.channelID >= peer -> channelCount ||
369 peer -> state != ENET_PEER_STATE_CONNECTED)
370 return;
372 packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable),
373 command -> header.commandLength - sizeof (ENetProtocolSendUnreliable),
376 enet_peer_queue_incoming_command (peer, command, packet, 0);
379 static void
380 enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
382 enet_uint32 fragmentNumber,
383 fragmentCount,
384 fragmentOffset,
385 fragmentLength,
386 startSequenceNumber,
387 totalLength;
388 ENetChannel * channel;
389 ENetListIterator currentCommand;
390 ENetIncomingCommand * startCommand;
392 if (command -> header.commandLength <= sizeof (ENetProtocolSendFragment) ||
393 command -> header.channelID >= peer -> channelCount ||
394 peer -> state != ENET_PEER_STATE_CONNECTED)
395 return;
397 startSequenceNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.startSequenceNumber);
398 fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
399 fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
400 fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
401 totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
402 fragmentLength = command -> header.commandLength - sizeof (ENetProtocolSendFragment);
404 if (fragmentOffset >= totalLength ||
405 fragmentOffset + fragmentLength > totalLength ||
406 fragmentNumber >= fragmentCount)
407 return;
409 channel = & peer -> channels [command -> header.channelID];
411 if (startSequenceNumber <= channel -> incomingReliableSequenceNumber)
412 return;
414 for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
415 currentCommand != enet_list_end (& channel -> incomingReliableCommands);
416 currentCommand = enet_list_previous (currentCommand))
418 startCommand = (ENetIncomingCommand *) currentCommand;
420 if (startCommand -> command.header.command == ENET_PROTOCOL_COMMAND_SEND_FRAGMENT &&
421 startCommand -> command.sendFragment.startSequenceNumber == startSequenceNumber)
422 break;
425 if (currentCommand == enet_list_end (& channel -> incomingReliableCommands))
427 ENetProtocol hostCommand = * command;
429 hostCommand.header.reliableSequenceNumber = startSequenceNumber;
430 hostCommand.sendFragment.startSequenceNumber = startSequenceNumber;
431 hostCommand.sendFragment.fragmentNumber = fragmentNumber;
432 hostCommand.sendFragment.fragmentCount = fragmentCount;
433 hostCommand.sendFragment.fragmentOffset = fragmentOffset;
434 hostCommand.sendFragment.totalLength = totalLength;
436 startCommand = enet_peer_queue_incoming_command (peer,
437 & hostCommand,
438 enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE),
439 fragmentCount);
441 else
442 if (totalLength != startCommand -> packet -> dataLength ||
443 fragmentCount != startCommand -> fragmentCount)
444 return;
446 if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0)
448 -- startCommand -> fragmentsRemaining;
450 startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
452 if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
453 fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
455 memcpy (startCommand -> packet -> data + fragmentOffset,
456 (enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
457 fragmentLength);
461 static void
462 enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
464 if (command -> header.commandLength < sizeof (ENetProtocolPing))
465 return;
468 static void
469 enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
471 if (command -> header.commandLength < sizeof (ENetProtocolBandwidthLimit))
472 return;
474 peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth);
475 peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth);
477 if (peer -> incomingBandwidth == 0 &&
478 host -> outgoingBandwidth == 0)
479 peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
480 else
481 peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) /
482 ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
484 if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
485 peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
486 else
487 if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
488 peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
491 static void
492 enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
494 if (command -> header.commandLength < sizeof (ENetProtocolThrottleConfigure))
495 return;
497 peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval);
498 peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration);
499 peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration);
502 static void
503 enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
505 if (command -> header.commandLength < sizeof (ENetProtocolDisconnect))
506 return;
508 enet_peer_reset_queues (peer);
510 if (peer -> state != ENET_PEER_STATE_CONNECTED)
512 if (peer -> state == ENET_PEER_STATE_CONNECTION_PENDING) host -> recalculateBandwidthLimits = 1;
514 enet_peer_reset (peer);
516 else
517 if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE)
518 peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT;
519 else
520 peer -> state = ENET_PEER_STATE_ZOMBIE;
522 peer -> disconnectData = command -> disconnect.data;
525 static int
526 enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
528 enet_uint32 roundTripTime,
529 receivedSentTime,
530 receivedReliableSequenceNumber;
531 ENetProtocolCommand commandNumber;
533 if (command -> header.commandLength < sizeof (ENetProtocolAcknowledge))
534 return 0;
536 receivedSentTime = ENET_NET_TO_HOST_32 (command -> acknowledge.receivedSentTime);
538 if (ENET_TIME_LESS (timeCurrent, receivedSentTime))
539 return 0;
541 peer -> lastReceiveTime = timeCurrent;
542 peer -> earliestTimeout = 0;
544 roundTripTime = ENET_TIME_DIFFERENCE (timeCurrent, receivedSentTime);
546 enet_peer_throttle (peer, roundTripTime);
548 peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
550 if (roundTripTime >= peer -> roundTripTime)
552 peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
553 peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
555 else
557 peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
558 peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
561 if (peer -> roundTripTime < peer -> lowestRoundTripTime)
562 peer -> lowestRoundTripTime = peer -> roundTripTime;
564 if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance)
565 peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
567 if (peer -> packetThrottleEpoch == 0 ||
568 ENET_TIME_DIFFERENCE(timeCurrent, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
570 peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
571 peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
572 peer -> lowestRoundTripTime = peer -> roundTripTime;
573 peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
574 peer -> packetThrottleEpoch = timeCurrent;
577 receivedReliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> acknowledge.receivedReliableSequenceNumber);
579 commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
581 switch (peer -> state)
583 case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
584 if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT)
585 return 0;
587 enet_protocol_notify_connect (host, peer, event);
589 return 1;
591 case ENET_PEER_STATE_DISCONNECTING:
592 if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT)
593 return 0;
595 enet_protocol_notify_disconnect (host, peer, event);
597 return 1;
600 return 0;
603 static void
604 enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
606 enet_uint16 mtu;
607 enet_uint32 windowSize;
609 if (event == NULL ||
610 command -> header.commandLength < sizeof (ENetProtocolVerifyConnect) ||
611 peer -> state != ENET_PEER_STATE_CONNECTING)
612 return;
614 if (ENET_NET_TO_HOST_32 (command -> verifyConnect.channelCount) != peer -> channelCount ||
615 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval ||
616 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleAcceleration) != peer -> packetThrottleAcceleration ||
617 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration)
619 peer -> state = ENET_PEER_STATE_ZOMBIE;
621 return;
624 peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID);
626 mtu = ENET_NET_TO_HOST_16 (command -> verifyConnect.mtu);
628 if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
629 mtu = ENET_PROTOCOL_MINIMUM_MTU;
630 else
631 if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
632 mtu = ENET_PROTOCOL_MAXIMUM_MTU;
634 if (mtu < peer -> mtu)
635 peer -> mtu = mtu;
637 windowSize = ENET_NET_TO_HOST_32 (command -> verifyConnect.windowSize);
639 if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
640 windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
642 if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
643 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
645 if (windowSize < peer -> windowSize)
646 peer -> windowSize = windowSize;
648 peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.incomingBandwidth);
649 peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.outgoingBandwidth);
651 enet_protocol_notify_connect (host, peer, event);
654 static int
655 enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
657 ENetProtocolHeader * header;
658 ENetProtocol * command;
659 ENetPeer * peer;
660 enet_uint8 * currentData;
661 size_t commandCount;
663 if (host -> receivedDataLength < sizeof (ENetProtocolHeader))
664 return 0;
666 header = (ENetProtocolHeader *) host -> receivedData;
668 header -> peerID = ENET_NET_TO_HOST_16 (header -> peerID);
669 header -> sentTime = ENET_NET_TO_HOST_32 (header -> sentTime);
671 if (header -> peerID == 0xFFFF)
672 peer = NULL;
673 else
674 if (header -> peerID >= host -> peerCount)
675 return 0;
676 else
678 peer = & host -> peers [header -> peerID];
680 if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
681 peer -> state == ENET_PEER_STATE_ZOMBIE ||
682 (host -> receivedAddress.host != peer -> address.host &&
683 peer -> address.host != ENET_HOST_BROADCAST) ||
684 header -> challenge != peer -> challenge)
685 return 0;
686 else
688 peer -> address.host = host -> receivedAddress.host;
689 peer -> address.port = host -> receivedAddress.port;
693 if (peer != NULL)
694 peer -> incomingDataTotal += host -> receivedDataLength;
696 commandCount = header -> commandCount;
697 currentData = host -> receivedData + sizeof (ENetProtocolHeader);
699 while (commandCount > 0 &&
700 currentData < & host -> receivedData [host -> receivedDataLength])
702 command = (ENetProtocol *) currentData;
704 if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength])
705 break;
707 command -> header.commandLength = ENET_NET_TO_HOST_32 (command -> header.commandLength);
709 if (command -> header.commandLength <= 0 ||
710 command -> header.commandLength > & host -> receivedData [host -> receivedDataLength] - currentData)
711 break;
713 -- commandCount;
714 currentData += command -> header.commandLength;
716 if (peer == NULL && command -> header.command != ENET_PROTOCOL_COMMAND_CONNECT)
717 break;
719 command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> header.reliableSequenceNumber);
721 switch (command -> header.command)
723 case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE:
724 enet_protocol_handle_acknowledge (host, event, peer, command);
726 break;
728 case ENET_PROTOCOL_COMMAND_CONNECT:
729 peer = enet_protocol_handle_connect (host, header, command);
731 break;
733 case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT:
734 enet_protocol_handle_verify_connect (host, event, peer, command);
736 break;
738 case ENET_PROTOCOL_COMMAND_DISCONNECT:
739 enet_protocol_handle_disconnect (host, peer, command);
741 break;
743 case ENET_PROTOCOL_COMMAND_PING:
744 enet_protocol_handle_ping (host, peer, command);
746 break;
748 case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
749 enet_protocol_handle_send_reliable (host, peer, command);
751 break;
753 case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
754 enet_protocol_handle_send_unreliable (host, peer, command);
756 break;
758 case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
759 enet_protocol_handle_send_unsequenced (host, peer, command);
761 break;
763 case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
764 enet_protocol_handle_send_fragment (host, peer, command);
766 break;
768 case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT:
769 enet_protocol_handle_bandwidth_limit (host, peer, command);
771 break;
773 case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE:
774 enet_protocol_handle_throttle_configure (host, peer, command);
776 break;
778 default:
779 break;
782 if (peer != NULL &&
783 (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE) != 0)
785 switch (peer -> state)
787 case ENET_PEER_STATE_DISCONNECTING:
788 break;
790 case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT:
791 if (command -> header.command != ENET_PROTOCOL_COMMAND_DISCONNECT)
792 break;
794 default:
795 enet_peer_queue_acknowledgement (peer, command, header -> sentTime);
797 break;
802 if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
803 return 1;
805 return 0;
808 static int
809 enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
811 for (;;)
813 int receivedLength;
814 ENetBuffer buffer;
816 buffer.data = host -> receivedData;
817 buffer.dataLength = sizeof (host -> receivedData);
819 receivedLength = enet_socket_receive (host -> socket,
820 & host -> receivedAddress,
821 & buffer,
824 if (receivedLength < 0)
825 return -1;
827 if (receivedLength == 0)
828 return 0;
830 host -> receivedDataLength = receivedLength;
832 switch (enet_protocol_handle_incoming_commands (host, event))
834 case 1:
835 return 1;
837 case -1:
838 return -1;
840 default:
841 break;
845 return -1;
848 static void
849 enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
851 ENetProtocol * command = & host -> commands [host -> commandCount];
852 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
853 ENetAcknowledgement * acknowledgement;
854 ENetListIterator currentAcknowledgement;
856 currentAcknowledgement = enet_list_begin (& peer -> acknowledgements);
858 while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements))
860 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
861 buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
862 peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
863 break;
865 acknowledgement = (ENetAcknowledgement *) currentAcknowledgement;
867 currentAcknowledgement = enet_list_next (currentAcknowledgement);
869 buffer -> data = command;
870 buffer -> dataLength = sizeof (ENetProtocolAcknowledge);
872 host -> packetSize += buffer -> dataLength;
874 command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE;
875 command -> header.channelID = acknowledgement -> command.header.channelID;
876 command -> header.flags = 0;
877 command -> header.commandLength = ENET_HOST_TO_NET_32 (sizeof (ENetProtocolAcknowledge));
878 command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_32 (acknowledgement -> command.header.reliableSequenceNumber);
879 command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_32 (acknowledgement -> sentTime);
881 if (acknowledgement -> command.header.command == ENET_PROTOCOL_COMMAND_DISCONNECT)
882 peer -> state = ENET_PEER_STATE_ZOMBIE;
884 enet_list_remove (& acknowledgement -> acknowledgementList);
885 enet_free (acknowledgement);
887 ++ command;
888 ++ buffer;
891 host -> commandCount = command - host -> commands;
892 host -> bufferCount = buffer - host -> buffers;
895 static void
896 enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
898 ENetProtocol * command = & host -> commands [host -> commandCount];
899 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
900 ENetOutgoingCommand * outgoingCommand;
901 ENetListIterator currentCommand;
903 currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
905 while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
907 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
909 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
910 buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
911 peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength ||
912 (outgoingCommand -> packet != NULL &&
913 peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength +
914 outgoingCommand -> packet -> dataLength))
915 break;
917 currentCommand = enet_list_next (currentCommand);
919 if (outgoingCommand -> packet != NULL)
921 peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
922 peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
924 if (peer -> packetThrottleCounter > peer -> packetThrottle)
926 -- outgoingCommand -> packet -> referenceCount;
928 if (outgoingCommand -> packet -> referenceCount == 0)
929 enet_packet_destroy (outgoingCommand -> packet);
931 enet_list_remove (& outgoingCommand -> outgoingCommandList);
932 enet_free (outgoingCommand);
934 continue;
938 buffer -> data = command;
939 buffer -> dataLength = outgoingCommand -> command.header.commandLength;
941 host -> packetSize += buffer -> dataLength;
943 * command = outgoingCommand -> command;
945 enet_list_remove (& outgoingCommand -> outgoingCommandList);
947 if (outgoingCommand -> packet != NULL)
949 ++ buffer;
951 buffer -> data = outgoingCommand -> packet -> data;
952 buffer -> dataLength = outgoingCommand -> packet -> dataLength;
954 command -> header.commandLength += buffer -> dataLength;
956 host -> packetSize += buffer -> dataLength;
958 enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
960 else
961 enet_free (outgoingCommand);
963 command -> header.commandLength = ENET_HOST_TO_NET_32 (command -> header.commandLength);
965 ++ command;
966 ++ buffer;
969 host -> commandCount = command - host -> commands;
970 host -> bufferCount = buffer - host -> buffers;
973 static int
974 enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
976 ENetOutgoingCommand * outgoingCommand;
977 ENetListIterator currentCommand;
979 currentCommand = enet_list_begin (& peer -> sentReliableCommands);
981 while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
983 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
985 currentCommand = enet_list_next (currentCommand);
987 if (ENET_TIME_DIFFERENCE (timeCurrent, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
988 continue;
990 if(peer -> earliestTimeout == 0 ||
991 ENET_TIME_LESS(outgoingCommand -> sentTime, peer -> earliestTimeout))
992 peer -> earliestTimeout = outgoingCommand -> sentTime;
994 if (peer -> earliestTimeout != 0 &&
995 (ENET_TIME_DIFFERENCE(timeCurrent, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MAXIMUM ||
996 (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
997 ENET_TIME_DIFFERENCE(timeCurrent, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MINIMUM)))
999 enet_protocol_notify_disconnect (host, peer, event);
1001 return 1;
1004 if (outgoingCommand -> packet != NULL)
1005 peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
1007 ++ peer -> packetsLost;
1009 outgoingCommand -> roundTripTimeout *= 2;
1011 enet_list_insert (enet_list_begin (& peer -> outgoingReliableCommands),
1012 enet_list_remove (& outgoingCommand -> outgoingCommandList));
1014 if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
1015 enet_list_empty (& peer -> sentReliableCommands) == 0)
1017 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1019 peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
1023 return 0;
1026 static void
1027 enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
1029 ENetProtocol * command = & host -> commands [host -> commandCount];
1030 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
1031 ENetOutgoingCommand * outgoingCommand;
1032 ENetListIterator currentCommand;
1034 currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
1036 while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
1038 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
1040 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
1041 buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
1042 peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength)
1043 break;
1045 currentCommand = enet_list_next (currentCommand);
1047 if (outgoingCommand -> packet != NULL)
1049 if ((enet_uint16) (peer -> mtu - host -> packetSize) <
1050 (enet_uint16) (outgoingCommand -> command.header.commandLength +
1051 outgoingCommand -> fragmentLength) ||
1052 peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > peer -> windowSize)
1053 break;
1056 if (outgoingCommand -> roundTripTimeout == 0)
1058 outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
1059 outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout;
1062 if (enet_list_empty (& peer -> sentReliableCommands))
1063 peer -> nextTimeout = timeCurrent + outgoingCommand -> roundTripTimeout;
1065 enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
1066 enet_list_remove (& outgoingCommand -> outgoingCommandList));
1068 outgoingCommand -> sentTime = timeCurrent;
1070 buffer -> data = command;
1071 buffer -> dataLength = outgoingCommand -> command.header.commandLength;
1073 host -> packetSize += buffer -> dataLength;
1075 * command = outgoingCommand -> command;
1077 if (outgoingCommand -> packet != NULL)
1079 ++ buffer;
1081 buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1082 buffer -> dataLength = outgoingCommand -> fragmentLength;
1084 command -> header.commandLength += outgoingCommand -> fragmentLength;
1086 host -> packetSize += outgoingCommand -> fragmentLength;
1088 peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
1091 command -> header.commandLength = ENET_HOST_TO_NET_32 (command -> header.commandLength);
1093 ++ peer -> packetsSent;
1095 ++ command;
1096 ++ buffer;
1099 host -> commandCount = command - host -> commands;
1100 host -> bufferCount = buffer - host -> buffers;
1103 static int
1104 enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
1106 size_t packetsSent = 1;
1107 ENetProtocolHeader header;
1108 ENetPeer * currentPeer;
1109 int sentLength;
1111 while (packetsSent > 0)
1112 for (currentPeer = host -> peers,
1113 packetsSent = 0;
1114 currentPeer < & host -> peers [host -> peerCount];
1115 ++ currentPeer)
1117 if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
1118 currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
1119 continue;
1121 host -> commandCount = 0;
1122 host -> bufferCount = 1;
1123 host -> packetSize = sizeof (ENetProtocolHeader);
1125 if (enet_list_empty (& currentPeer -> acknowledgements) == 0)
1126 enet_protocol_send_acknowledgements (host, currentPeer);
1128 if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol))
1130 if (checkForTimeouts != 0 &&
1131 enet_list_empty (& currentPeer -> sentReliableCommands) == 0 &&
1132 ENET_TIME_GREATER_EQUAL (timeCurrent, currentPeer -> nextTimeout) &&
1133 enet_protocol_check_timeouts (host, currentPeer, event) == 1)
1134 return 1;
1136 if (enet_list_empty (& currentPeer -> outgoingReliableCommands) == 0)
1137 enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1138 else
1139 if (enet_list_empty (& currentPeer -> sentReliableCommands) &&
1140 ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL &&
1141 currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
1143 enet_peer_ping (currentPeer);
1144 enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1147 if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol) &&
1148 enet_list_empty (& currentPeer -> outgoingUnreliableCommands) == 0)
1149 enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
1151 if (host -> commandCount == 0)
1152 continue;
1154 if (currentPeer -> packetLossEpoch == 0)
1155 currentPeer -> packetLossEpoch = timeCurrent;
1156 else
1157 if (ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
1158 currentPeer -> packetsSent > 0)
1160 enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
1162 #ifdef ENET_DEBUG
1163 #ifdef WIN32
1164 printf (
1165 #else
1166 fprintf (stderr,
1167 #endif
1168 "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, enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands));
1169 #endif
1171 currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
1173 if (packetLoss >= currentPeer -> packetLoss)
1175 currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
1176 currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
1178 else
1180 currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
1181 currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
1184 currentPeer -> packetLossEpoch = timeCurrent;
1185 currentPeer -> packetsSent = 0;
1186 currentPeer -> packetsLost = 0;
1189 header.peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID);
1190 header.flags = 0;
1191 header.commandCount = host -> commandCount;
1192 header.sentTime = ENET_HOST_TO_NET_32 (timeCurrent);
1193 header.challenge = currentPeer -> challenge;
1195 host -> buffers -> data = & header;
1196 host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
1198 currentPeer -> lastSendTime = timeCurrent;
1200 ++ packetsSent;
1202 sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
1204 enet_protocol_remove_sent_unreliable_commands (currentPeer);
1206 if (sentLength < 0)
1207 return -1;
1210 return 0;
1213 /** Sends any queued packets on the host specified to its designated peers.
1215 @param host host to flush
1216 @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().
1217 @ingroup host
1219 void
1220 enet_host_flush (ENetHost * host)
1222 timeCurrent = enet_time_get ();
1224 enet_protocol_send_outgoing_commands (host, NULL, 0);
1227 /** Waits for events on the host specified and shuttles packets between
1228 the host and its peers.
1230 @param host host to service
1231 @param event an event structure where event details will be placed if one occurs
1232 if event == NULL then no events will be delivered
1233 @param timeout number of milliseconds that ENet should wait for events
1234 @retval > 0 if an event occurred within the specified time limit
1235 @retval 0 if no event occurred
1236 @retval < 0 on failure
1237 @remarks enet_host_service should be called fairly regularly for adequate performance
1238 @ingroup host
1241 enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
1243 enet_uint32 waitCondition;
1245 if (event != NULL)
1247 event -> type = ENET_EVENT_TYPE_NONE;
1248 event -> peer = NULL;
1249 event -> packet = NULL;
1251 switch (enet_protocol_dispatch_incoming_commands (host, event))
1253 case 1:
1254 return 1;
1256 case -1:
1257 perror ("Error dispatching incoming packets");
1259 return -1;
1261 default:
1262 break;
1266 timeCurrent = enet_time_get ();
1268 timeout += timeCurrent;
1272 if (ENET_TIME_DIFFERENCE (timeCurrent, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
1273 enet_host_bandwidth_throttle (host);
1275 switch (enet_protocol_send_outgoing_commands (host, event, 1))
1277 case 1:
1278 return 1;
1280 case -1:
1281 perror ("Error sending outgoing packets");
1283 return -1;
1285 default:
1286 break;
1289 switch (enet_protocol_receive_incoming_commands (host, event))
1291 case 1:
1292 return 1;
1294 case -1:
1295 perror ("Error receiving incoming packets");
1297 return -1;
1299 default:
1300 break;
1303 switch (enet_protocol_send_outgoing_commands (host, event, 1))
1305 case 1:
1306 return 1;
1308 case -1:
1309 perror ("Error sending outgoing packets");
1311 return -1;
1313 default:
1314 break;
1317 if (event != NULL)
1319 switch (enet_protocol_dispatch_incoming_commands (host, event))
1321 case 1:
1322 return 1;
1324 case -1:
1325 perror ("Error dispatching incoming packets");
1327 return -1;
1329 default:
1330 break;
1334 timeCurrent = enet_time_get ();
1336 if (ENET_TIME_GREATER_EQUAL (timeCurrent, timeout))
1337 return 0;
1339 waitCondition = ENET_SOCKET_WAIT_RECEIVE;
1341 if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, timeCurrent)) != 0)
1342 return -1;
1344 timeCurrent = enet_time_get ();
1345 } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE);
1347 return 0;