Development back on the trunk!
[crack-attack.git] / enet / protocol.c
blobb331c9575c00f79502f410e4d44333d1992031ac
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/memory.h"
10 #include "enet/time.h"
11 #include "enet/enet.h"
13 static enet_uint32 timeCurrent;
15 static int
16 enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
18 ENetPeer * currentPeer = host -> lastServicedPeer;
19 ENetChannel * channel;
23 ++ currentPeer;
25 if (currentPeer >= & host -> peers [host -> peerCount])
26 currentPeer = host -> peers;
28 if (currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
30 host -> recalculateBandwidthLimits = 1;
32 event -> type = ENET_EVENT_TYPE_DISCONNECT;
33 event -> peer = currentPeer;
35 enet_peer_reset (currentPeer);
37 host -> lastServicedPeer = currentPeer;
39 return 1;
42 if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
43 continue;
45 for (channel = currentPeer -> channels;
46 channel < & currentPeer -> channels [currentPeer -> channelCount];
47 ++ channel)
49 if (enet_list_empty (& channel -> incomingReliableCommands) &&
50 enet_list_empty (& channel -> incomingUnreliableCommands))
51 continue;
53 event -> packet = enet_peer_receive (currentPeer, channel - currentPeer -> channels);
54 if (event -> packet == NULL)
55 continue;
57 event -> type = ENET_EVENT_TYPE_RECEIVE;
58 event -> peer = currentPeer;
59 event -> channelID = (enet_uint8) (channel - currentPeer -> channels);
61 host -> lastServicedPeer = currentPeer;
63 return 1;
65 } while (currentPeer != host -> lastServicedPeer);
67 return 0;
70 static void
71 enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
73 ENetOutgoingCommand * outgoingCommand;
75 while (enet_list_empty (& peer -> sentUnreliableCommands) == 0)
77 outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
79 enet_list_remove (& outgoingCommand -> outgoingCommandList);
81 if (outgoingCommand -> packet != NULL)
83 -- outgoingCommand -> packet -> referenceCount;
85 if (outgoingCommand -> packet -> referenceCount == 0)
86 enet_packet_destroy (outgoingCommand -> packet);
89 enet_free (outgoingCommand);
93 static ENetProtocolCommand
94 enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint32 reliableSequenceNumber, enet_uint8 channelID)
96 ENetOutgoingCommand * outgoingCommand;
97 ENetListIterator currentCommand;
98 ENetProtocolCommand commandNumber;
100 for (currentCommand = enet_list_begin (& peer -> sentReliableCommands);
101 currentCommand != enet_list_end (& peer -> sentReliableCommands);
102 currentCommand = enet_list_next (currentCommand))
104 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
106 if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
107 outgoingCommand -> command.header.channelID == channelID)
108 break;
111 if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
112 return ENET_PROTOCOL_COMMAND_NONE;
114 commandNumber = (ENetProtocolCommand) outgoingCommand -> command.header.command;
116 enet_list_remove (& outgoingCommand -> outgoingCommandList);
118 if (outgoingCommand -> packet != NULL)
120 peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
122 -- outgoingCommand -> packet -> referenceCount;
124 if (outgoingCommand -> packet -> referenceCount == 0)
125 enet_packet_destroy (outgoingCommand -> packet);
128 enet_free (outgoingCommand);
130 if (enet_list_empty (& peer -> sentReliableCommands))
131 return commandNumber;
133 outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentReliableCommands);
135 peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
137 return commandNumber;
140 static ENetPeer *
141 enet_protocol_handle_connect (ENetHost * host, const ENetProtocolHeader * header, const ENetProtocol * command)
143 enet_uint16 mtu;
144 enet_uint32 windowSize;
145 ENetChannel * channel;
146 size_t channelCount;
147 ENetPeer * currentPeer;
148 ENetProtocol verifyCommand;
150 if (command -> header.commandLength < sizeof (ENetProtocolConnect))
151 return NULL;
153 channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount);
155 if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT ||
156 channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
157 return NULL;
159 for (currentPeer = host -> peers;
160 currentPeer < & host -> peers [host -> peerCount];
161 ++ currentPeer)
163 if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED &&
164 currentPeer -> address.host == host -> receivedAddress.host &&
165 currentPeer -> address.port == host -> receivedAddress.port &&
166 currentPeer -> challenge == header -> challenge)
167 return NULL;
170 for (currentPeer = host -> peers;
171 currentPeer < & host -> peers [host -> peerCount];
172 ++ currentPeer)
174 if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
175 break;
178 if (currentPeer >= & host -> peers [host -> peerCount])
179 return NULL;
181 currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
182 currentPeer -> challenge = header -> challenge;
183 currentPeer -> address = host -> receivedAddress;
184 currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
185 currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
186 currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth);
187 currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval);
188 currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration);
189 currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration);
190 currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
191 currentPeer -> channelCount = channelCount;
193 for (channel = currentPeer -> channels;
194 channel < & currentPeer -> channels [channelCount];
195 ++ channel)
197 channel -> outgoingReliableSequenceNumber = 0;
198 channel -> outgoingUnreliableSequenceNumber = 0;
199 channel -> incomingReliableSequenceNumber = 0;
200 channel -> incomingUnreliableSequenceNumber = 0;
202 enet_list_clear (& channel -> incomingReliableCommands);
203 enet_list_clear (& channel -> incomingUnreliableCommands);
206 mtu = ENET_NET_TO_HOST_16 (command -> connect.mtu);
208 if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
209 mtu = ENET_PROTOCOL_MINIMUM_MTU;
210 else
211 if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
212 mtu = ENET_PROTOCOL_MAXIMUM_MTU;
214 currentPeer -> mtu = mtu;
216 if (host -> outgoingBandwidth == 0 &&
217 currentPeer -> incomingBandwidth == 0)
218 currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
219 else
220 currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) /
221 ENET_PEER_WINDOW_SIZE_SCALE) *
222 ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
224 if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
225 currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
226 else
227 if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
228 currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
230 if (host -> incomingBandwidth == 0)
231 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
232 else
233 windowSize = (host -> incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) *
234 ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
236 if (windowSize > ENET_NET_TO_HOST_32 (command -> connect.windowSize))
237 windowSize = ENET_NET_TO_HOST_32 (command -> connect.windowSize);
239 if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
240 windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
241 else
242 if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
243 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
245 verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT;
246 verifyCommand.header.channelID = 0xFF;
247 verifyCommand.header.flags = ENET_PROTOCOL_FLAG_ACKNOWLEDGE;
248 verifyCommand.header.commandLength = sizeof (ENetProtocolVerifyConnect);
249 verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
250 verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu);
251 verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize);
252 verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
253 verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
254 verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
255 verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
256 verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
257 verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
259 enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0);
261 return currentPeer;
264 static void
265 enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
267 ENetPacket * packet;
269 if (command -> header.commandLength <= sizeof (ENetProtocolSendReliable) ||
270 command -> header.channelID >= peer -> channelCount ||
271 peer -> state != ENET_PEER_STATE_CONNECTED)
272 return;
274 packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable),
275 command -> header.commandLength - sizeof (ENetProtocolSendReliable),
276 ENET_PACKET_FLAG_RELIABLE);
278 enet_peer_queue_incoming_command (peer, command, packet, 0);
281 static void
282 enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
284 ENetPacket * packet;
286 if (command -> header.commandLength <= sizeof (ENetProtocolSendUnreliable) ||
287 command -> header.channelID >= peer -> channelCount ||
288 peer -> state != ENET_PEER_STATE_CONNECTED)
289 return;
291 packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable),
292 command -> header.commandLength - sizeof (ENetProtocolSendUnreliable),
295 enet_peer_queue_incoming_command (peer, command, packet, 0);
298 static void
299 enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
301 enet_uint32 fragmentNumber,
302 fragmentCount,
303 fragmentOffset,
304 fragmentLength,
305 startSequenceNumber,
306 totalLength;
307 ENetChannel * channel;
308 ENetListIterator currentCommand;
309 ENetIncomingCommand * startCommand;
311 if (command -> header.commandLength <= sizeof (ENetProtocolSendFragment) ||
312 command -> header.channelID >= peer -> channelCount ||
313 peer -> state != ENET_PEER_STATE_CONNECTED)
314 return;
316 startSequenceNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.startSequenceNumber);
317 fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
318 fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
319 fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
320 totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
321 fragmentLength = command -> header.commandLength - sizeof (ENetProtocolSendFragment);
323 if (fragmentOffset >= totalLength ||
324 fragmentOffset + fragmentLength > totalLength ||
325 fragmentNumber >= fragmentCount)
326 return;
328 channel = & peer -> channels [command -> header.channelID];
330 if (startSequenceNumber <= channel -> incomingReliableSequenceNumber)
331 return;
333 for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
334 currentCommand != enet_list_end (& channel -> incomingReliableCommands);
335 currentCommand = enet_list_previous (currentCommand))
337 startCommand = (ENetIncomingCommand *) currentCommand;
339 if (startCommand -> command.header.command == ENET_PROTOCOL_COMMAND_SEND_FRAGMENT &&
340 startCommand -> command.sendFragment.startSequenceNumber == startSequenceNumber)
341 break;
344 if (currentCommand == enet_list_end (& channel -> incomingReliableCommands))
346 ENetProtocol hostCommand = * command;
348 hostCommand.sendFragment.startSequenceNumber = startSequenceNumber;
349 hostCommand.sendFragment.fragmentNumber = fragmentNumber;
350 hostCommand.sendFragment.fragmentCount = fragmentCount;
351 hostCommand.sendFragment.fragmentOffset = fragmentOffset;
352 hostCommand.sendFragment.totalLength = totalLength;
354 startCommand = enet_peer_queue_incoming_command (peer,
355 & hostCommand,
356 enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE),
357 fragmentCount);
359 else
360 if (totalLength != startCommand -> packet -> dataLength ||
361 fragmentCount != startCommand -> fragmentCount)
362 return;
364 if ((startCommand -> fragments [fragmentNumber / 32] & (1 << fragmentNumber)) == 0)
365 -- startCommand -> fragmentsRemaining;
367 startCommand -> fragments [fragmentNumber / 32] |= (1 << fragmentNumber);
369 if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
370 fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
372 memcpy (startCommand -> packet -> data + fragmentOffset,
373 (enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
374 fragmentLength);
377 static void
378 enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
380 if (command -> header.commandLength < sizeof (ENetProtocolPing))
381 return;
384 static void
385 enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
387 if (command -> header.commandLength < sizeof (ENetProtocolBandwidthLimit))
388 return;
390 peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth);
391 peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth);
393 if (peer -> incomingBandwidth == 0 &&
394 host -> outgoingBandwidth == 0)
395 peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
396 else
397 peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) /
398 ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
400 if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
401 peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
402 else
403 if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
404 peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
407 static void
408 enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
410 if (command -> header.commandLength < sizeof (ENetProtocolThrottleConfigure))
411 return;
413 peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval);
414 peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration);
415 peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration);
418 static void
419 enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
421 if (command -> header.commandLength < sizeof (ENetProtocolDisconnect))
422 return;
424 enet_peer_reset_queues (peer);
426 if (peer -> state != ENET_PEER_STATE_CONNECTED)
427 enet_peer_reset (peer);
428 else
429 if (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE)
430 peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT;
431 else
432 peer -> state = ENET_PEER_STATE_ZOMBIE;
435 static int
436 enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
438 enet_uint32 roundTripTime,
439 receivedSentTime,
440 receivedReliableSequenceNumber;
441 ENetProtocolCommand commandNumber;
443 if (command -> header.commandLength < sizeof (ENetProtocolAcknowledge))
444 return 0;
446 receivedSentTime = ENET_NET_TO_HOST_32 (command -> acknowledge.receivedSentTime);
448 if (ENET_TIME_LESS (timeCurrent, receivedSentTime))
449 return 0;
451 peer -> lastReceiveTime = timeCurrent;
453 roundTripTime = ENET_TIME_DIFFERENCE (timeCurrent, receivedSentTime);
455 enet_peer_throttle (peer, roundTripTime);
457 peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
459 if (roundTripTime >= peer -> roundTripTime)
461 peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
462 peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
464 else
466 peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
467 peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
470 if (peer -> roundTripTime < peer -> lowestRoundTripTime)
471 peer -> lowestRoundTripTime = peer -> roundTripTime;
473 if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance)
474 peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
476 if (peer -> packetThrottleEpoch == 0 ||
477 ENET_TIME_DIFFERENCE(timeCurrent, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
479 peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
480 peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
481 peer -> lowestRoundTripTime = peer -> roundTripTime;
482 peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
483 peer -> packetThrottleEpoch = timeCurrent;
486 receivedReliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> acknowledge.receivedReliableSequenceNumber);
488 commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
490 switch (peer -> state)
492 case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
493 if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT)
494 return 0;
496 host -> recalculateBandwidthLimits = 1;
498 peer -> state = ENET_PEER_STATE_CONNECTED;
500 event -> type = ENET_EVENT_TYPE_CONNECT;
501 event -> peer = peer;
503 return 1;
505 case ENET_PEER_STATE_DISCONNECTING:
506 if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT)
507 return 0;
509 host -> recalculateBandwidthLimits = 1;
511 event -> type = ENET_EVENT_TYPE_DISCONNECT;
512 event -> peer = peer;
514 enet_peer_reset (peer);
516 return 1;
518 default:
519 break;
522 return 0;
525 static void
526 enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
528 enet_uint16 mtu;
529 enet_uint32 windowSize;
531 if (command -> header.commandLength < sizeof (ENetProtocolVerifyConnect) ||
532 peer -> state != ENET_PEER_STATE_CONNECTING)
533 return;
535 if (ENET_NET_TO_HOST_32 (command -> verifyConnect.channelCount) != peer -> channelCount ||
536 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval ||
537 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleAcceleration) != peer -> packetThrottleAcceleration ||
538 ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration)
540 peer -> state = ENET_PEER_STATE_ZOMBIE;
542 return;
545 peer -> state = ENET_PEER_STATE_CONNECTED;
547 peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID);
549 mtu = ENET_NET_TO_HOST_16 (command -> verifyConnect.mtu);
551 if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
552 mtu = ENET_PROTOCOL_MINIMUM_MTU;
553 else
554 if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
555 mtu = ENET_PROTOCOL_MAXIMUM_MTU;
557 if (mtu < peer -> mtu)
558 peer -> mtu = mtu;
560 windowSize = ENET_NET_TO_HOST_32 (command -> verifyConnect.windowSize);
562 if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
563 windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
565 if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
566 windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
568 if (windowSize < peer -> windowSize)
569 peer -> windowSize = windowSize;
571 peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.incomingBandwidth);
572 peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.outgoingBandwidth);
574 host -> recalculateBandwidthLimits = 1;
576 peer -> state = ENET_PEER_STATE_CONNECTED;
578 event -> type = ENET_EVENT_TYPE_CONNECT;
579 event -> peer = peer;
582 static int
583 enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
585 ENetProtocolHeader * header;
586 ENetProtocol * command;
587 ENetPeer * peer;
588 enet_uint8 * currentData;
589 size_t commandCount;
591 if (host -> receivedDataLength < sizeof (ENetProtocolHeader))
592 return 0;
594 header = (ENetProtocolHeader *) host -> receivedData;
596 header -> peerID = ENET_NET_TO_HOST_16 (header -> peerID);
597 header -> sentTime = ENET_NET_TO_HOST_32 (header -> sentTime);
599 if (header -> peerID == 0xFFFF)
600 peer = NULL;
601 else
602 if (header -> peerID >= host -> peerCount)
603 return 0;
604 else
606 peer = & host -> peers [header -> peerID];
608 if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
609 peer -> state == ENET_PEER_STATE_ZOMBIE ||
610 host -> receivedAddress.host != peer -> address.host ||
611 header -> challenge != peer -> challenge)
612 return 0;
613 else
614 peer -> address.port = host -> receivedAddress.port;
617 if (peer != NULL)
618 peer -> incomingDataTotal += host -> receivedDataLength;
620 commandCount = header -> commandCount;
621 currentData = host -> receivedData + sizeof (ENetProtocolHeader);
623 while (commandCount > 0 &&
624 currentData < & host -> receivedData [host -> receivedDataLength])
626 command = (ENetProtocol *) currentData;
628 if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength])
629 return 0;
631 command -> header.commandLength = ENET_NET_TO_HOST_32 (command -> header.commandLength);
633 if (currentData + command -> header.commandLength > & host -> receivedData [host -> receivedDataLength])
634 return 0;
636 -- commandCount;
637 currentData += command -> header.commandLength;
639 if (peer == NULL)
641 if (command -> header.command != ENET_PROTOCOL_COMMAND_CONNECT)
642 return 0;
645 command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_32 (command -> header.reliableSequenceNumber);
647 switch (command -> header.command)
649 case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE:
650 enet_protocol_handle_acknowledge (host, event, peer, command);
652 break;
654 case ENET_PROTOCOL_COMMAND_CONNECT:
655 peer = enet_protocol_handle_connect (host, header, command);
657 break;
659 case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT:
660 enet_protocol_handle_verify_connect (host, event, peer, command);
662 break;
664 case ENET_PROTOCOL_COMMAND_DISCONNECT:
665 enet_protocol_handle_disconnect (host, peer, command);
667 break;
669 case ENET_PROTOCOL_COMMAND_PING:
670 enet_protocol_handle_ping (host, peer, command);
672 break;
674 case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
675 enet_protocol_handle_send_reliable (host, peer, command);
677 break;
679 case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
680 enet_protocol_handle_send_unreliable (host, peer, command);
682 break;
684 case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
685 enet_protocol_handle_send_fragment (host, peer, command);
687 break;
689 case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT:
690 enet_protocol_handle_bandwidth_limit (host, peer, command);
692 break;
694 case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE:
695 enet_protocol_handle_throttle_configure (host, peer, command);
697 break;
699 default:
700 break;
703 if (peer != NULL &&
704 (command -> header.flags & ENET_PROTOCOL_FLAG_ACKNOWLEDGE) != 0)
706 switch (peer -> state)
708 case ENET_PEER_STATE_DISCONNECTING:
709 break;
711 case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT:
712 if (command -> header.command != ENET_PROTOCOL_COMMAND_DISCONNECT)
713 break;
715 default:
716 enet_peer_queue_acknowledgement (peer, command, header -> sentTime);
718 break;
723 if (event -> type != ENET_EVENT_TYPE_NONE)
724 return 1;
726 return 0;
729 static int
730 enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
732 for (;;)
734 int receivedLength;
735 ENetBuffer buffer;
737 buffer.data = host -> receivedData;
738 buffer.dataLength = sizeof (host -> receivedData);
740 receivedLength = enet_socket_receive (host -> socket,
741 & host -> receivedAddress,
742 & buffer,
745 if (receivedLength < 0)
746 return -1;
748 if (receivedLength == 0)
749 return 0;
751 host -> receivedDataLength = receivedLength;
753 switch (enet_protocol_handle_incoming_commands (host, event))
755 case 1:
756 return 1;
758 case -1:
759 return -1;
761 default:
762 break;
766 return -1;
769 static void
770 enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
772 ENetProtocol * command = & host -> commands [host -> commandCount];
773 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
774 ENetAcknowledgement * acknowledgement;
775 ENetListIterator currentAcknowledgement;
777 currentAcknowledgement = enet_list_begin (& peer -> acknowledgements);
779 while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements))
781 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
782 buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
783 peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
784 break;
786 acknowledgement = (ENetAcknowledgement *) currentAcknowledgement;
788 if (peer -> state == ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT &&
789 acknowledgement -> command.header.command != ENET_PROTOCOL_COMMAND_DISCONNECT)
790 continue;
792 currentAcknowledgement = enet_list_next (currentAcknowledgement);
794 buffer -> data = command;
795 buffer -> dataLength = sizeof (ENetProtocolAcknowledge);
797 host -> packetSize += buffer -> dataLength;
799 command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE;
800 command -> header.channelID = acknowledgement -> command.header.channelID;
801 command -> header.flags = 0;
802 command -> header.commandLength = ENET_HOST_TO_NET_32 (sizeof (ENetProtocolAcknowledge));
803 command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_32 (acknowledgement -> command.header.reliableSequenceNumber);
804 command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_32 (acknowledgement -> sentTime);
806 if (acknowledgement -> command.header.command == ENET_PROTOCOL_COMMAND_DISCONNECT)
807 peer -> state = ENET_PEER_STATE_ZOMBIE;
809 enet_list_remove (& acknowledgement -> acknowledgementList);
810 enet_free (acknowledgement);
812 ++ command;
813 ++ buffer;
816 host -> commandCount = command - host -> commands;
817 host -> bufferCount = buffer - host -> buffers;
820 static void
821 enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
823 ENetProtocol * command = & host -> commands [host -> commandCount];
824 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
825 ENetOutgoingCommand * outgoingCommand;
826 ENetListIterator currentCommand;
828 currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
830 while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
832 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
834 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
835 buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
836 peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength ||
837 (outgoingCommand -> packet != NULL &&
838 peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength +
839 outgoingCommand -> packet -> dataLength))
840 break;
842 currentCommand = enet_list_next (currentCommand);
844 if (outgoingCommand -> packet != NULL)
846 peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
847 peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
849 if (peer -> packetThrottleCounter > peer -> packetThrottle)
851 -- outgoingCommand -> packet -> referenceCount;
853 if (outgoingCommand -> packet -> referenceCount == 0)
854 enet_packet_destroy (outgoingCommand -> packet);
856 enet_list_remove (& outgoingCommand -> outgoingCommandList);
857 enet_free (outgoingCommand);
859 continue;
863 buffer -> data = command;
864 buffer -> dataLength = outgoingCommand -> command.header.commandLength;
866 host -> packetSize += buffer -> dataLength;
868 * command = outgoingCommand -> command;
870 enet_list_remove (& outgoingCommand -> outgoingCommandList);
872 if (outgoingCommand -> packet != NULL)
874 ++ buffer;
876 buffer -> data = outgoingCommand -> packet -> data;
877 buffer -> dataLength = outgoingCommand -> packet -> dataLength;
879 command -> header.commandLength += buffer -> dataLength;
881 host -> packetSize += buffer -> dataLength;
883 enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
885 else
886 enet_free (outgoingCommand);
888 command -> header.commandLength = ENET_HOST_TO_NET_32 (command -> header.commandLength);
890 ++ command;
891 ++ buffer;
894 host -> commandCount = command - host -> commands;
895 host -> bufferCount = buffer - host -> buffers;
898 static int
899 enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
901 ENetOutgoingCommand * outgoingCommand;
902 ENetListIterator currentCommand;
904 currentCommand = enet_list_begin (& peer -> sentReliableCommands);
906 while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
908 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
910 currentCommand = enet_list_next (currentCommand);
912 if (ENET_TIME_DIFFERENCE (timeCurrent, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
913 continue;
915 if (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit)
917 event -> type = ENET_EVENT_TYPE_DISCONNECT;
918 event -> peer = peer;
920 enet_peer_reset (peer);
922 return 1;
925 if (outgoingCommand -> packet != NULL)
926 peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
928 ++ peer -> packetsLost;
930 outgoingCommand -> roundTripTimeout *= 2;
932 enet_list_insert (enet_list_begin (& peer -> outgoingReliableCommands),
933 enet_list_remove (& outgoingCommand -> outgoingCommandList));
935 if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
936 enet_list_empty (& peer -> sentReliableCommands) == 0)
938 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
940 peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
944 return 0;
947 static void
948 enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
950 ENetProtocol * command = & host -> commands [host -> commandCount];
951 ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
952 ENetOutgoingCommand * outgoingCommand;
953 ENetListIterator currentCommand;
955 currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
957 while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
959 outgoingCommand = (ENetOutgoingCommand *) currentCommand;
961 if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
962 buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
963 peer -> mtu - host -> packetSize < outgoingCommand -> command.header.commandLength)
964 break;
966 currentCommand = enet_list_next (currentCommand);
968 if (outgoingCommand -> packet != NULL)
970 if ((enet_uint16) (peer -> mtu - host -> packetSize) <
971 (enet_uint16) (outgoingCommand -> command.header.commandLength +
972 outgoingCommand -> fragmentLength) ||
973 peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > peer -> windowSize)
974 break;
977 if (outgoingCommand -> roundTripTimeout == 0)
979 outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
980 outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout;
983 if (enet_list_empty (& peer -> sentReliableCommands))
984 peer -> nextTimeout = timeCurrent + outgoingCommand -> roundTripTimeout;
986 enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
987 enet_list_remove (& outgoingCommand -> outgoingCommandList));
989 outgoingCommand -> sentTime = timeCurrent;
991 buffer -> data = command;
992 buffer -> dataLength = outgoingCommand -> command.header.commandLength;
994 host -> packetSize += buffer -> dataLength;
996 * command = outgoingCommand -> command;
998 if (outgoingCommand -> packet != NULL)
1000 ++ buffer;
1002 buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
1003 buffer -> dataLength = outgoingCommand -> fragmentLength;
1005 command -> header.commandLength += outgoingCommand -> fragmentLength;
1007 host -> packetSize += outgoingCommand -> fragmentLength;
1009 peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
1012 command -> header.commandLength = ENET_HOST_TO_NET_32 (command -> header.commandLength);
1014 ++ peer -> packetsSent;
1016 ++ command;
1017 ++ buffer;
1020 host -> commandCount = command - host -> commands;
1021 host -> bufferCount = buffer - host -> buffers;
1024 static int
1025 enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
1027 size_t packetsSent = 1;
1028 ENetProtocolHeader header;
1029 ENetPeer * currentPeer;
1030 int sentLength;
1032 while (packetsSent > 0)
1033 for (currentPeer = host -> peers,
1034 packetsSent = 0;
1035 currentPeer < & host -> peers [host -> peerCount];
1036 ++ currentPeer)
1038 if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
1039 currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
1040 continue;
1042 host -> commandCount = 0;
1043 host -> bufferCount = 1;
1044 host -> packetSize = sizeof (ENetProtocolHeader);
1046 if (enet_list_empty (& currentPeer -> acknowledgements) == 0)
1047 enet_protocol_send_acknowledgements (host, currentPeer);
1049 if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol))
1051 if (checkForTimeouts != 0 &&
1052 enet_list_empty (& currentPeer -> sentReliableCommands) == 0 &&
1053 ENET_TIME_GREATER_EQUAL (timeCurrent, currentPeer -> nextTimeout) &&
1054 enet_protocol_check_timeouts (host, currentPeer, event) == 1)
1055 return 1;
1057 if (enet_list_empty (& currentPeer -> outgoingReliableCommands) == 0)
1058 enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1059 else
1060 if (enet_list_empty (& currentPeer -> sentReliableCommands) &&
1061 ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL &&
1062 currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
1064 enet_peer_ping (currentPeer);
1065 enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
1068 if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol) &&
1069 enet_list_empty (& currentPeer -> outgoingUnreliableCommands) == 0)
1070 enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
1072 if (host -> commandCount == 0)
1073 continue;
1075 if (currentPeer -> packetLossEpoch == 0)
1076 currentPeer -> packetLossEpoch = timeCurrent;
1077 else
1078 if (ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
1079 currentPeer -> packetsSent > 0)
1081 enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
1083 #ifdef ENET_DEBUG
1084 #ifdef WIN32
1085 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, enet_list_size (& currentPeer -> channels -> incomingUnreliableCommands));
1086 #else
1087 fprintf (stderr, "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));
1088 #endif
1089 #endif
1091 currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
1093 if (packetLoss >= currentPeer -> packetLoss)
1095 currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
1096 currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
1098 else
1100 currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
1101 currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
1104 currentPeer -> packetLossEpoch = timeCurrent;
1105 currentPeer -> packetsSent = 0;
1106 currentPeer -> packetsLost = 0;
1109 header.peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID);
1110 header.flags = 0;
1111 header.commandCount = host -> commandCount;
1112 header.sentTime = ENET_HOST_TO_NET_32 (timeCurrent);
1113 header.challenge = currentPeer -> challenge;
1115 host -> buffers -> data = & header;
1116 host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
1118 currentPeer -> lastSendTime = timeCurrent;
1120 ++ packetsSent;
1122 sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
1124 enet_protocol_remove_sent_unreliable_commands (currentPeer);
1126 if (sentLength < 0)
1127 return -1;
1130 return 0;
1133 /** Sends any queued packets on the host specified to its designated peers.
1135 @param host host to flush
1136 @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().
1137 @ingroup host
1139 void
1140 enet_host_flush (ENetHost * host)
1142 timeCurrent = enet_time_get ();
1144 enet_protocol_send_outgoing_commands (host, NULL, 0);
1147 /** Waits for events on the host specified and shuttles packets between
1148 the host and its peers.
1150 @param host host to service
1151 @param event an event structure where event details will be placed if one occurs
1152 @param timeout number of milliseconds that ENet should wait for events
1153 @retval > 1 if an event occurred within the specified time limit
1154 @retval 0 if no event occurred
1155 @retval < 1 on failure
1156 @remarks enet_host_service should be called fairly regularly for adequate performance
1157 @ingroup host
1160 enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
1162 enet_uint32 waitCondition;
1164 event -> type = ENET_EVENT_TYPE_NONE;
1165 event -> peer = NULL;
1166 event -> packet = NULL;
1168 switch (enet_protocol_dispatch_incoming_commands (host, event))
1170 case 1:
1171 return 1;
1173 case -1:
1174 perror ("Error dispatching incoming packets");
1176 return -1;
1178 default:
1179 break;
1182 timeCurrent = enet_time_get ();
1184 timeout += timeCurrent;
1188 if (ENET_TIME_DIFFERENCE (timeCurrent, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
1189 enet_host_bandwidth_throttle (host);
1191 switch (enet_protocol_send_outgoing_commands (host, event, 1))
1193 case 1:
1194 return 1;
1196 case -1:
1197 perror ("Error sending outgoing packets");
1199 return -1;
1201 default:
1202 break;
1205 switch (enet_protocol_receive_incoming_commands (host, event))
1207 case 1:
1208 return 1;
1210 case -1:
1211 perror ("Error receiving incoming packets");
1213 return -1;
1215 default:
1216 break;
1219 switch (enet_protocol_send_outgoing_commands (host, event, 1))
1221 case 1:
1222 return 1;
1224 case -1:
1225 perror ("Error sending outgoing packets");
1227 return -1;
1229 default:
1230 break;
1233 switch (enet_protocol_dispatch_incoming_commands (host, event))
1235 case 1:
1236 return 1;
1238 case -1:
1239 perror ("Error dispatching incoming packets");
1241 return -1;
1243 default:
1244 break;
1247 timeCurrent = enet_time_get ();
1249 if (ENET_TIME_GREATER_EQUAL (timeCurrent, timeout))
1250 return 0;
1252 waitCondition = ENET_SOCKET_WAIT_RECEIVE;
1254 if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, timeCurrent)) != 0)
1255 return -1;
1257 timeCurrent = enet_time_get ();
1258 } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE);
1260 return 0;