home *** CD-ROM | disk | FTP | other *** search
/ Maximum CD 2007 September / maximum-cd-2007-09.iso / Assets / data / AssaultCube_v0.93.exe / source / enet / protocol.c < prev    next >
Encoding:
C/C++ Source or Header  |  2007-01-12  |  52.3 KB  |  1,475 lines

  1. /** 
  2.  @file  protocol.c
  3.  @brief ENet protocol functions
  4. */
  5. #include <stdio.h>
  6. #include <string.h>
  7. #define ENET_BUILDING_LIB 1
  8. #include "enet/utility.h"
  9. #include "enet/time.h"
  10. #include "enet/enet.h"
  11.  
  12. static enet_uint32 timeCurrent;
  13.  
  14. static size_t commandSizes [ENET_PROTOCOL_COMMAND_COUNT] =
  15. {
  16.     0,
  17.     sizeof (ENetProtocolAcknowledge),
  18.     sizeof (ENetProtocolConnect),
  19.     sizeof (ENetProtocolVerifyConnect),
  20.     sizeof (ENetProtocolDisconnect),
  21.     sizeof (ENetProtocolPing),
  22.     sizeof (ENetProtocolSendReliable),
  23.     sizeof (ENetProtocolSendUnreliable),
  24.     sizeof (ENetProtocolSendFragment),
  25.     sizeof (ENetProtocolSendUnsequenced),
  26.     sizeof (ENetProtocolBandwidthLimit),
  27.     sizeof (ENetProtocolThrottleConfigure),
  28. };
  29.  
  30. size_t
  31. enet_protocol_command_size (enet_uint8 commandNumber)
  32. {
  33.     return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK];
  34. }
  35.  
  36. static int
  37. enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
  38. {
  39.     ENetPeer * currentPeer = host -> lastServicedPeer;
  40.     ENetChannel * channel;
  41.  
  42.     do
  43.     {
  44.        ++ currentPeer;
  45.        
  46.        if (currentPeer >= & host -> peers [host -> peerCount])
  47.          currentPeer = host -> peers;
  48.  
  49.        switch (currentPeer -> state)
  50.        {
  51.        case ENET_PEER_STATE_CONNECTION_PENDING:
  52.        case ENET_PEER_STATE_CONNECTION_SUCCEEDED:
  53.            currentPeer -> state = ENET_PEER_STATE_CONNECTED;
  54.  
  55.            event -> type = ENET_EVENT_TYPE_CONNECT;
  56.            event -> peer = currentPeer;
  57.  
  58.            return 1;
  59.            
  60.        case ENET_PEER_STATE_ZOMBIE:
  61.            host -> recalculateBandwidthLimits = 1;
  62.  
  63.            event -> type = ENET_EVENT_TYPE_DISCONNECT;
  64.            event -> peer = currentPeer;
  65.            event -> data = currentPeer -> disconnectData;
  66.  
  67.            enet_peer_reset (currentPeer);
  68.  
  69.            host -> lastServicedPeer = currentPeer;
  70.  
  71.            return 1;
  72.        }
  73.  
  74.        if (currentPeer -> state != ENET_PEER_STATE_CONNECTED)
  75.          continue;
  76.  
  77.        for (channel = currentPeer -> channels;
  78.             channel < & currentPeer -> channels [currentPeer -> channelCount];
  79.             ++ channel)
  80.        {
  81.            if (enet_list_empty (& channel -> incomingReliableCommands) &&
  82.                enet_list_empty (& channel -> incomingUnreliableCommands))
  83.              continue;
  84.  
  85.            event -> packet = enet_peer_receive (currentPeer, channel - currentPeer -> channels);
  86.            if (event -> packet == NULL)
  87.              continue;
  88.              
  89.            event -> type = ENET_EVENT_TYPE_RECEIVE;
  90.            event -> peer = currentPeer;
  91.            event -> channelID = (enet_uint8) (channel - currentPeer -> channels);
  92.  
  93.            host -> lastServicedPeer = currentPeer;
  94.  
  95.            return 1;
  96.        }
  97.     } while (currentPeer != host -> lastServicedPeer);
  98.  
  99.     return 0;
  100. }
  101.  
  102. static void
  103. enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
  104. {
  105.     host -> recalculateBandwidthLimits = 1;
  106.  
  107.     if (event == NULL)
  108.        peer -> state = (peer -> state == ENET_PEER_STATE_CONNECTING ? ENET_PEER_STATE_CONNECTION_SUCCEEDED : ENET_PEER_STATE_CONNECTION_PENDING);
  109.     else
  110.     {
  111.        peer -> state = ENET_PEER_STATE_CONNECTED;
  112.  
  113.        event -> type = ENET_EVENT_TYPE_CONNECT;
  114.        event -> peer = peer;
  115.     }
  116. }
  117.  
  118. static void
  119. enet_protocol_notify_disconnect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
  120. {
  121.     if (peer -> state >= ENET_PEER_STATE_CONNECTION_PENDING)
  122.         host -> recalculateBandwidthLimits = 1;
  123.  
  124.     if (peer -> state != ENET_PEER_STATE_CONNECTING && peer -> state < ENET_PEER_STATE_CONNECTION_SUCCEEDED)
  125.         enet_peer_reset (peer);
  126.     else
  127.     if (event == NULL)
  128.         peer -> state = ENET_PEER_STATE_ZOMBIE;
  129.     else
  130.     {
  131.         event -> type = ENET_EVENT_TYPE_DISCONNECT;
  132.         event -> peer = peer;
  133.         event -> data = 0;
  134.  
  135.         enet_peer_reset (peer);
  136.     }
  137. }
  138.  
  139. static void
  140. enet_protocol_remove_sent_unreliable_commands (ENetPeer * peer)
  141. {
  142.     ENetOutgoingCommand * outgoingCommand;
  143.  
  144.     while (! enet_list_empty (& peer -> sentUnreliableCommands))
  145.     {
  146.         outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentUnreliableCommands);
  147.         
  148.         enet_list_remove (& outgoingCommand -> outgoingCommandList);
  149.  
  150.         if (outgoingCommand -> packet != NULL)
  151.         {
  152.            -- outgoingCommand -> packet -> referenceCount;
  153.  
  154.            if (outgoingCommand -> packet -> referenceCount == 0)
  155.              enet_packet_destroy (outgoingCommand -> packet);
  156.         }
  157.  
  158.         enet_free (outgoingCommand);
  159.     }
  160. }
  161.  
  162. static ENetProtocolCommand
  163. enet_protocol_remove_sent_reliable_command (ENetPeer * peer, enet_uint16 reliableSequenceNumber, enet_uint8 channelID)
  164. {
  165.     ENetOutgoingCommand * outgoingCommand;
  166.     ENetListIterator currentCommand;
  167.     ENetProtocolCommand commandNumber;
  168.  
  169.     for (currentCommand = enet_list_begin (& peer -> sentReliableCommands);
  170.          currentCommand != enet_list_end (& peer -> sentReliableCommands);
  171.          currentCommand = enet_list_next (currentCommand))
  172.     {
  173.        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
  174.         
  175.        if (outgoingCommand -> reliableSequenceNumber == reliableSequenceNumber &&
  176.            outgoingCommand -> command.header.channelID == channelID)
  177.          break;
  178.     }
  179.  
  180.     if (currentCommand == enet_list_end (& peer -> sentReliableCommands))
  181.       return ENET_PROTOCOL_COMMAND_NONE;
  182.  
  183.     commandNumber = outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK;
  184.  
  185.     enet_list_remove (& outgoingCommand -> outgoingCommandList);
  186.  
  187.     if (outgoingCommand -> packet != NULL)
  188.     {
  189.        peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
  190.  
  191.        -- outgoingCommand -> packet -> referenceCount;
  192.  
  193.        if (outgoingCommand -> packet -> referenceCount == 0)
  194.          enet_packet_destroy (outgoingCommand -> packet);
  195.     }
  196.  
  197.     enet_free (outgoingCommand);
  198.  
  199.     if (enet_list_empty (& peer -> sentReliableCommands))
  200.       return commandNumber;
  201.     
  202.     outgoingCommand = (ENetOutgoingCommand *) enet_list_front (& peer -> sentReliableCommands);
  203.     
  204.     peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
  205.  
  206.     return commandNumber;
  207.  
  208. static ENetPeer *
  209. enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENetProtocol * command)
  210. {
  211.     enet_uint16 mtu;
  212.     enet_uint32 windowSize;
  213.     ENetChannel * channel;
  214.     size_t channelCount;
  215.     ENetPeer * currentPeer;
  216.     ENetProtocol verifyCommand;
  217.  
  218. #ifdef USE_CRC32
  219.     {
  220.         enet_uint32 crc = header -> checksum;
  221.         ENetBuffer buffer;
  222.  
  223.         command -> header.reliableSequenceNumber = ENET_HOST_TO_NET_16 (command -> header.reliableSequenceNumber);
  224.  
  225.         header -> checksum = command -> connect.sessionID;
  226.  
  227.         buffer.data = host -> receivedData;
  228.         buffer.dataLength = host -> receivedDataLength;
  229.  
  230.         if (enet_crc32 (& buffer, 1) != crc)
  231.           return NULL;
  232.  
  233.         command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber);
  234.     }
  235. #endif
  236.  
  237.     channelCount = ENET_NET_TO_HOST_32 (command -> connect.channelCount);
  238.  
  239.     if (channelCount < ENET_PROTOCOL_MINIMUM_CHANNEL_COUNT ||
  240.         channelCount > ENET_PROTOCOL_MAXIMUM_CHANNEL_COUNT)
  241.       return NULL;
  242.  
  243.     for (currentPeer = host -> peers;
  244.          currentPeer < & host -> peers [host -> peerCount];
  245.          ++ currentPeer)
  246.     {
  247.         if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED &&
  248.             currentPeer -> address.host == host -> receivedAddress.host &&
  249.             currentPeer -> address.port == host -> receivedAddress.port &&
  250.             currentPeer -> sessionID == command -> connect.sessionID)
  251.           return NULL;
  252.     }
  253.  
  254.     for (currentPeer = host -> peers;
  255.          currentPeer < & host -> peers [host -> peerCount];
  256.          ++ currentPeer)
  257.     {
  258.         if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED)
  259.           break;
  260.     }
  261.  
  262.     if (currentPeer >= & host -> peers [host -> peerCount])
  263.       return NULL;
  264.  
  265.     currentPeer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
  266.     currentPeer -> sessionID = command -> connect.sessionID;
  267.     currentPeer -> address = host -> receivedAddress;
  268.     currentPeer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> connect.outgoingPeerID);
  269.     currentPeer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.incomingBandwidth);
  270.     currentPeer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> connect.outgoingBandwidth);
  271.     currentPeer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleInterval);
  272.     currentPeer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleAcceleration);
  273.     currentPeer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> connect.packetThrottleDeceleration);
  274.     currentPeer -> channels = (ENetChannel *) enet_malloc (channelCount * sizeof (ENetChannel));
  275.     currentPeer -> channelCount = channelCount;
  276.  
  277.     for (channel = currentPeer -> channels;
  278.          channel < & currentPeer -> channels [channelCount];
  279.          ++ channel)
  280.     {
  281.         channel -> outgoingReliableSequenceNumber = 0;
  282.         channel -> outgoingUnreliableSequenceNumber = 0;
  283.         channel -> incomingReliableSequenceNumber = 0;
  284.         channel -> incomingUnreliableSequenceNumber = 0;
  285.  
  286.         enet_list_clear (& channel -> incomingReliableCommands);
  287.         enet_list_clear (& channel -> incomingUnreliableCommands);
  288.     }
  289.  
  290.     mtu = ENET_NET_TO_HOST_16 (command -> connect.mtu);
  291.  
  292.     if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
  293.       mtu = ENET_PROTOCOL_MINIMUM_MTU;
  294.     else
  295.     if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
  296.       mtu = ENET_PROTOCOL_MAXIMUM_MTU;
  297.  
  298.     currentPeer -> mtu = mtu;
  299.  
  300.     if (host -> outgoingBandwidth == 0 &&
  301.         currentPeer -> incomingBandwidth == 0)
  302.       currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
  303.     else
  304.       currentPeer -> windowSize = (ENET_MIN (host -> outgoingBandwidth, currentPeer -> incomingBandwidth) /
  305.                                     ENET_PEER_WINDOW_SIZE_SCALE) * 
  306.                                       ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
  307.  
  308.     if (currentPeer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
  309.       currentPeer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
  310.     else
  311.     if (currentPeer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
  312.       currentPeer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
  313.  
  314.     if (host -> incomingBandwidth == 0)
  315.       windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
  316.     else
  317.       windowSize = (host -> incomingBandwidth / ENET_PEER_WINDOW_SIZE_SCALE) *
  318.                      ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
  319.  
  320.     if (windowSize > ENET_NET_TO_HOST_32 (command -> connect.windowSize))
  321.       windowSize = ENET_NET_TO_HOST_32 (command -> connect.windowSize);
  322.  
  323.     if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
  324.       windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
  325.     else
  326.     if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
  327.       windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
  328.  
  329.     verifyCommand.header.command = ENET_PROTOCOL_COMMAND_VERIFY_CONNECT | ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE;
  330.     verifyCommand.header.channelID = 0xFF;
  331.     verifyCommand.verifyConnect.outgoingPeerID = ENET_HOST_TO_NET_16 (currentPeer -> incomingPeerID);
  332.     verifyCommand.verifyConnect.mtu = ENET_HOST_TO_NET_16 (currentPeer -> mtu);
  333.     verifyCommand.verifyConnect.windowSize = ENET_HOST_TO_NET_32 (windowSize);
  334.     verifyCommand.verifyConnect.channelCount = ENET_HOST_TO_NET_32 (channelCount);
  335.     verifyCommand.verifyConnect.incomingBandwidth = ENET_HOST_TO_NET_32 (host -> incomingBandwidth);
  336.     verifyCommand.verifyConnect.outgoingBandwidth = ENET_HOST_TO_NET_32 (host -> outgoingBandwidth);
  337.     verifyCommand.verifyConnect.packetThrottleInterval = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleInterval);
  338.     verifyCommand.verifyConnect.packetThrottleAcceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleAcceleration);
  339.     verifyCommand.verifyConnect.packetThrottleDeceleration = ENET_HOST_TO_NET_32 (currentPeer -> packetThrottleDeceleration);
  340.  
  341.     enet_peer_queue_outgoing_command (currentPeer, & verifyCommand, NULL, 0, 0);
  342.  
  343.     return currentPeer;
  344. }
  345.  
  346. static int
  347. enet_protocol_handle_send_reliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
  348. {
  349.     ENetPacket * packet;
  350.     size_t dataLength;
  351.  
  352.     if (command -> header.channelID >= peer -> channelCount ||
  353.         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
  354.       return -1;
  355.  
  356.     dataLength = ENET_NET_TO_HOST_16 (command -> sendReliable.dataLength);
  357.     * currentData += dataLength;
  358.     if (* currentData > & host -> receivedData [host -> receivedDataLength])
  359.       return -1;
  360.  
  361.     packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendReliable),
  362.                                  dataLength,
  363.                                  ENET_PACKET_FLAG_RELIABLE);
  364.     if (packet == NULL)
  365.       return -1;
  366.  
  367.     enet_peer_queue_incoming_command (peer, command, packet, 0);
  368.     return 0;
  369. }
  370.  
  371. static int
  372. enet_protocol_handle_send_unsequenced (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
  373. {
  374.     ENetPacket * packet;
  375.     enet_uint32 unsequencedGroup, index;
  376.     size_t dataLength;
  377.  
  378.     if (command -> header.channelID >= peer -> channelCount ||
  379.         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
  380.       return -1;
  381.  
  382.     dataLength = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.dataLength);
  383.     * currentData += dataLength;
  384.     if (* currentData > & host -> receivedData [host -> receivedDataLength])
  385.       return -1; 
  386.  
  387.     unsequencedGroup = ENET_NET_TO_HOST_16 (command -> sendUnsequenced.unsequencedGroup);
  388.     index = unsequencedGroup % ENET_PEER_UNSEQUENCED_WINDOW_SIZE;
  389.     
  390.     if (unsequencedGroup >= peer -> incomingUnsequencedGroup + ENET_PEER_UNSEQUENCED_WINDOW_SIZE ||
  391.         peer -> incomingUnsequencedGroup >= 0xF000 && unsequencedGroup < 0x1000)
  392.     {
  393.         peer -> incomingUnsequencedGroup = unsequencedGroup - index;
  394.  
  395.         memset (peer -> unsequencedWindow, 0, sizeof (peer -> unsequencedWindow));
  396.     }
  397.     else
  398.     if (unsequencedGroup < peer -> incomingUnsequencedGroup ||
  399.         peer -> unsequencedWindow [index / 32] & (1 << (index % 32)))
  400.       return 0;
  401.       
  402.     peer -> unsequencedWindow [index / 32] |= 1 << (index % 32);
  403.     
  404.                         
  405.     packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnsequenced),
  406.                                  dataLength,
  407.                                  ENET_PACKET_FLAG_UNSEQUENCED);
  408.     if (packet == NULL)
  409.       return -1;
  410.     
  411.     enet_peer_queue_incoming_command (peer, command, packet, 0);
  412.     return 0;
  413. }
  414.  
  415. static int
  416. enet_protocol_handle_send_unreliable (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
  417. {
  418.     ENetPacket * packet;
  419.     size_t dataLength;
  420.  
  421.     if (command -> header.channelID >= peer -> channelCount ||
  422.         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
  423.       return -1;
  424.  
  425.     dataLength = ENET_NET_TO_HOST_16 (command -> sendUnreliable.dataLength);
  426.     * currentData += dataLength;
  427.     if (* currentData > & host -> receivedData [host -> receivedDataLength])
  428.       return -1;
  429.  
  430.     packet = enet_packet_create ((const enet_uint8 *) command + sizeof (ENetProtocolSendUnreliable),
  431.                                  dataLength,
  432.                                  0);
  433.     if (packet == NULL)
  434.       return -1;
  435.  
  436.     enet_peer_queue_incoming_command (peer, command, packet, 0);
  437.     return 0;
  438. }
  439.  
  440. static int
  441. enet_protocol_handle_send_fragment (ENetHost * host, ENetPeer * peer, const ENetProtocol * command, enet_uint8 ** currentData)
  442. {
  443.     enet_uint32 fragmentNumber,
  444.            fragmentCount,
  445.            fragmentOffset,
  446.            fragmentLength,
  447.            startSequenceNumber,
  448.            totalLength;
  449.     ENetChannel * channel;
  450.     ENetListIterator currentCommand;
  451.     ENetIncomingCommand * startCommand;
  452.  
  453.     if (command -> header.channelID >= peer -> channelCount ||
  454.         (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER))
  455.       return -1;
  456.  
  457.     fragmentLength = ENET_NET_TO_HOST_16 (command -> sendFragment.dataLength);
  458.     * currentData += fragmentLength;
  459.     if (* currentData > & host -> receivedData [host -> receivedDataLength])
  460.       return -1;
  461.  
  462.     channel = & peer -> channels [command -> header.channelID];
  463.     startSequenceNumber = ENET_NET_TO_HOST_16 (command -> sendFragment.startSequenceNumber);
  464.     if (channel -> incomingReliableSequenceNumber >= 0xF000 && startSequenceNumber < 0x1000)
  465.       startSequenceNumber += 0x10000;
  466.  
  467.     if (startSequenceNumber < channel -> incomingReliableSequenceNumber ||
  468.         (channel -> incomingReliableSequenceNumber < 0x1000 && (startSequenceNumber & 0xFFFF) >= 0xF000))
  469.       return 0;
  470.  
  471.     fragmentNumber = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentNumber);
  472.     fragmentCount = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentCount);
  473.     fragmentOffset = ENET_NET_TO_HOST_32 (command -> sendFragment.fragmentOffset);
  474.     totalLength = ENET_NET_TO_HOST_32 (command -> sendFragment.totalLength);
  475.     
  476.     if (fragmentOffset >= totalLength ||
  477.         fragmentOffset + fragmentLength > totalLength ||
  478.         fragmentNumber >= fragmentCount)
  479.       return -1;
  480.  
  481.     for (currentCommand = enet_list_previous (enet_list_end (& channel -> incomingReliableCommands));
  482.          currentCommand != enet_list_end (& channel -> incomingReliableCommands);
  483.          currentCommand = enet_list_previous (currentCommand))
  484.     {
  485.        startCommand = (ENetIncomingCommand *) currentCommand;
  486.  
  487.        if ((startCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_SEND_FRAGMENT &&
  488.            startCommand -> command.sendFragment.startSequenceNumber == (startSequenceNumber & 0xFFFF))
  489.          break;
  490.     }
  491.  
  492.     if (currentCommand == enet_list_end (& channel -> incomingReliableCommands))
  493.     {
  494.        ENetProtocol hostCommand = * command;
  495.        ENetPacket * packet = enet_packet_create (NULL, totalLength, ENET_PACKET_FLAG_RELIABLE);
  496.        if (packet == NULL)
  497.          return -1;
  498.  
  499.        hostCommand.header.reliableSequenceNumber = startSequenceNumber;
  500.        hostCommand.sendFragment.startSequenceNumber = startSequenceNumber;
  501.        hostCommand.sendFragment.dataLength = fragmentLength;
  502.        hostCommand.sendFragment.fragmentNumber = fragmentNumber;
  503.        hostCommand.sendFragment.fragmentCount = fragmentCount;
  504.        hostCommand.sendFragment.fragmentOffset = fragmentOffset;
  505.        hostCommand.sendFragment.totalLength = totalLength;
  506.  
  507.        startCommand = enet_peer_queue_incoming_command (peer, & hostCommand, packet, fragmentCount);
  508.     }
  509.     else
  510.     if (totalLength != startCommand -> packet -> dataLength ||
  511.         fragmentCount != startCommand -> fragmentCount)
  512.       return -1;
  513.     
  514.     if ((startCommand -> fragments [fragmentNumber / 32] & (1 << (fragmentNumber % 32))) == 0)
  515.     {
  516.        -- startCommand -> fragmentsRemaining;
  517.  
  518.        startCommand -> fragments [fragmentNumber / 32] |= (1 << (fragmentNumber % 32));
  519.  
  520.        if (fragmentOffset + fragmentLength > startCommand -> packet -> dataLength)
  521.          fragmentLength = startCommand -> packet -> dataLength - fragmentOffset;
  522.  
  523.        memcpy (startCommand -> packet -> data + fragmentOffset,
  524.                (enet_uint8 *) command + sizeof (ENetProtocolSendFragment),
  525.                fragmentLength);
  526.     }
  527.  
  528.     return 0;
  529. }
  530.  
  531. static int
  532. enet_protocol_handle_ping (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
  533. {
  534.     return 0;
  535. }
  536.  
  537. static int
  538. enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
  539. {
  540.     peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth);
  541.     peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth);
  542.  
  543.     if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0)
  544.       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
  545.     else
  546.       peer -> windowSize = (ENET_MIN (peer -> incomingBandwidth, host -> outgoingBandwidth) /
  547.                              ENET_PEER_WINDOW_SIZE_SCALE) * ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
  548.  
  549.     if (peer -> windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
  550.       peer -> windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
  551.     else
  552.     if (peer -> windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
  553.       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
  554.  
  555.     return 0;
  556. }
  557.  
  558. static int
  559. enet_protocol_handle_throttle_configure (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
  560. {
  561.     peer -> packetThrottleInterval = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleInterval);
  562.     peer -> packetThrottleAcceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleAcceleration);
  563.     peer -> packetThrottleDeceleration = ENET_NET_TO_HOST_32 (command -> throttleConfigure.packetThrottleDeceleration);
  564.  
  565.     return 0;
  566. }
  567.  
  568. static int
  569. enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetProtocol * command)
  570. {
  571.     enet_peer_reset_queues (peer);
  572.  
  573.     if (peer -> state == ENET_PEER_STATE_CONNECTION_SUCCEEDED)
  574.         peer -> state = ENET_PEER_STATE_ZOMBIE;
  575.     else
  576.     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
  577.     {
  578.         if (peer -> state == ENET_PEER_STATE_CONNECTION_PENDING) host -> recalculateBandwidthLimits = 1;
  579.  
  580.         enet_peer_reset (peer);
  581.     }
  582.     else
  583.     if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
  584.       peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT;
  585.     else
  586.       peer -> state = ENET_PEER_STATE_ZOMBIE;
  587.  
  588.     peer -> disconnectData = ENET_NET_TO_HOST_32 (command -> disconnect.data);
  589.     return 0;
  590. }
  591.  
  592. static int
  593. enet_protocol_handle_acknowledge (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
  594. {
  595.     enet_uint32 roundTripTime,
  596.            receivedSentTime,
  597.            receivedReliableSequenceNumber;
  598.     ENetProtocolCommand commandNumber;
  599.  
  600.     receivedSentTime = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedSentTime);
  601.     receivedSentTime |= timeCurrent & 0xFFFF0000;
  602.     if ((receivedSentTime & 0x8000) > (timeCurrent & 0x8000))
  603.         receivedSentTime -= 0x10000;
  604.  
  605.     if (ENET_TIME_LESS (timeCurrent, receivedSentTime))
  606.       return 0;
  607.  
  608.     peer -> lastReceiveTime = timeCurrent;
  609.     peer -> earliestTimeout = 0;
  610.  
  611.     roundTripTime = ENET_TIME_DIFFERENCE (timeCurrent, receivedSentTime);
  612.  
  613.     enet_peer_throttle (peer, roundTripTime);
  614.  
  615.     peer -> roundTripTimeVariance -= peer -> roundTripTimeVariance / 4;
  616.  
  617.     if (roundTripTime >= peer -> roundTripTime)
  618.     {
  619.        peer -> roundTripTime += (roundTripTime - peer -> roundTripTime) / 8;
  620.        peer -> roundTripTimeVariance += (roundTripTime - peer -> roundTripTime) / 4;
  621.     }
  622.     else
  623.     {
  624.        peer -> roundTripTime -= (peer -> roundTripTime - roundTripTime) / 8;
  625.        peer -> roundTripTimeVariance += (peer -> roundTripTime - roundTripTime) / 4;
  626.     }
  627.  
  628.     if (peer -> roundTripTime < peer -> lowestRoundTripTime)
  629.       peer -> lowestRoundTripTime = peer -> roundTripTime;
  630.  
  631.     if (peer -> roundTripTimeVariance > peer -> highestRoundTripTimeVariance) 
  632.       peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
  633.  
  634.     if (peer -> packetThrottleEpoch == 0 ||
  635.         ENET_TIME_DIFFERENCE(timeCurrent, peer -> packetThrottleEpoch) >= peer -> packetThrottleInterval)
  636.     {
  637.         peer -> lastRoundTripTime = peer -> lowestRoundTripTime;
  638.         peer -> lastRoundTripTimeVariance = peer -> highestRoundTripTimeVariance;
  639.         peer -> lowestRoundTripTime = peer -> roundTripTime;
  640.         peer -> highestRoundTripTimeVariance = peer -> roundTripTimeVariance;
  641.         peer -> packetThrottleEpoch = timeCurrent;
  642.     }
  643.  
  644.     receivedReliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> acknowledge.receivedReliableSequenceNumber);
  645.  
  646.     commandNumber = enet_protocol_remove_sent_reliable_command (peer, receivedReliableSequenceNumber, command -> header.channelID);
  647.  
  648.     switch (peer -> state)
  649.     {
  650.     case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
  651.        if (commandNumber != ENET_PROTOCOL_COMMAND_VERIFY_CONNECT)
  652.          return -1;
  653.  
  654.        enet_protocol_notify_connect (host, peer, event);
  655.        break;
  656.  
  657.     case ENET_PEER_STATE_DISCONNECTING:
  658.        if (commandNumber != ENET_PROTOCOL_COMMAND_DISCONNECT)
  659.          return -1;
  660.  
  661.        enet_protocol_notify_disconnect (host, peer, event);
  662.        break;
  663.  
  664.     case ENET_PEER_STATE_DISCONNECT_LATER:
  665.        if (enet_list_empty (& peer -> outgoingReliableCommands) &&
  666.            enet_list_empty (& peer -> outgoingUnreliableCommands) &&   
  667.            enet_list_empty (& peer -> sentReliableCommands))
  668.          enet_peer_disconnect (peer, peer -> disconnectData);
  669.        break;
  670.     }
  671.    
  672.     return 0;
  673. }
  674.  
  675. static int
  676. enet_protocol_handle_verify_connect (ENetHost * host, ENetEvent * event, ENetPeer * peer, const ENetProtocol * command)
  677. {
  678.     enet_uint16 mtu;
  679.     enet_uint32 windowSize;
  680.  
  681.     if (peer -> state != ENET_PEER_STATE_CONNECTING)
  682.       return -1;
  683.  
  684.     if (ENET_NET_TO_HOST_32 (command -> verifyConnect.channelCount) != peer -> channelCount ||
  685.         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleInterval) != peer -> packetThrottleInterval ||
  686.         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleAcceleration) != peer -> packetThrottleAcceleration ||
  687.         ENET_NET_TO_HOST_32 (command -> verifyConnect.packetThrottleDeceleration) != peer -> packetThrottleDeceleration)
  688.     {
  689.         peer -> state = ENET_PEER_STATE_ZOMBIE;
  690.  
  691.         return -1;
  692.     }
  693.  
  694.     enet_protocol_remove_sent_reliable_command (peer, 1, 0xFF);
  695.     
  696.     peer -> outgoingPeerID = ENET_NET_TO_HOST_16 (command -> verifyConnect.outgoingPeerID);
  697.  
  698.     mtu = ENET_NET_TO_HOST_16 (command -> verifyConnect.mtu);
  699.  
  700.     if (mtu < ENET_PROTOCOL_MINIMUM_MTU)
  701.       mtu = ENET_PROTOCOL_MINIMUM_MTU;
  702.     else 
  703.     if (mtu > ENET_PROTOCOL_MAXIMUM_MTU)
  704.       mtu = ENET_PROTOCOL_MAXIMUM_MTU;
  705.  
  706.     if (mtu < peer -> mtu)
  707.       peer -> mtu = mtu;
  708.  
  709.     windowSize = ENET_NET_TO_HOST_32 (command -> verifyConnect.windowSize);
  710.  
  711.     if (windowSize < ENET_PROTOCOL_MINIMUM_WINDOW_SIZE)
  712.       windowSize = ENET_PROTOCOL_MINIMUM_WINDOW_SIZE;
  713.  
  714.     if (windowSize > ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE)
  715.       windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
  716.  
  717.     if (windowSize < peer -> windowSize)
  718.       peer -> windowSize = windowSize;
  719.  
  720.     peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.incomingBandwidth);
  721.     peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> verifyConnect.outgoingBandwidth);
  722.  
  723.     enet_protocol_notify_connect (host, peer, event);
  724.     return 0;
  725. }
  726.  
  727. static int
  728. enet_protocol_handle_incoming_commands (ENetHost * host, ENetEvent * event)
  729. {
  730.     ENetProtocolHeader * header;
  731.     ENetProtocol * command;
  732.     ENetPeer * peer;
  733.     enet_uint8 * currentData;
  734.     size_t headerSize;
  735.     enet_uint16 peerID, flags;
  736.  
  737.     if (host -> receivedDataLength < sizeof (ENetProtocolHeader))
  738.       return 0;
  739.  
  740.     header = (ENetProtocolHeader *) host -> receivedData;
  741.  
  742.     peerID = ENET_NET_TO_HOST_16 (header -> peerID);
  743.     flags = peerID & ENET_PROTOCOL_HEADER_FLAG_MASK;
  744.     peerID &= ~ ENET_PROTOCOL_HEADER_FLAG_MASK;
  745.  
  746.     if (peerID == ENET_PROTOCOL_MAXIMUM_PEER_ID)
  747.       peer = NULL;
  748.     else
  749.     if (peerID >= host -> peerCount)
  750.       return 0;
  751.     else
  752.     {
  753.        peer = & host -> peers [peerID];
  754.  
  755.        if (peer -> state == ENET_PEER_STATE_DISCONNECTED ||
  756.            peer -> state == ENET_PEER_STATE_ZOMBIE || 
  757.            (host -> receivedAddress.host != peer -> address.host &&
  758.              peer -> address.host != ENET_HOST_BROADCAST))
  759.          return 0;
  760.  
  761. #ifdef USE_CRC32
  762.        {
  763.            enet_uint32 crc = header -> checksum;
  764.            ENetBuffer buffer;
  765.  
  766.            header -> checksum = peer -> sessionID;
  767.  
  768.            buffer.data = host -> receivedData;
  769.            buffer.dataLength = host -> receivedDataLength;
  770.  
  771.            if (enet_crc32 (& buffer, 1) != crc)
  772.              return 0;
  773.        }
  774. #else
  775.        if (header -> checksum != peer -> sessionID)
  776.          return 0;
  777. #endif
  778.  
  779.        peer -> address.host = host -> receivedAddress.host;
  780.        peer -> address.port = host -> receivedAddress.port;
  781.        peer -> incomingDataTotal += host -> receivedDataLength;
  782.     }
  783.     
  784.     headerSize = (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME ? sizeof (ENetProtocolHeader) : (size_t) & ((ENetProtocolHeader *) 0) -> sentTime);
  785.     currentData = host -> receivedData + headerSize;
  786.   
  787.     while (currentData < & host -> receivedData [host -> receivedDataLength])
  788.     {
  789.        enet_uint8 commandNumber;
  790.        size_t commandSize;
  791.  
  792.        command = (ENetProtocol *) currentData;
  793.  
  794.        if (currentData + sizeof (ENetProtocolCommandHeader) > & host -> receivedData [host -> receivedDataLength])
  795.          break;
  796.  
  797.        commandNumber = command -> header.command & ENET_PROTOCOL_COMMAND_MASK;
  798.        if (commandNumber >= ENET_PROTOCOL_COMMAND_COUNT) 
  799.          break;
  800.        
  801.        commandSize = commandSizes [commandNumber];
  802.        if (commandSize == 0 || currentData + commandSize > & host -> receivedData [host -> receivedDataLength])
  803.          break;
  804.  
  805.        currentData += commandSize;
  806.  
  807.        if (peer == NULL && commandNumber != ENET_PROTOCOL_COMMAND_CONNECT)
  808.          break;
  809.          
  810.        command -> header.reliableSequenceNumber = ENET_NET_TO_HOST_16 (command -> header.reliableSequenceNumber);
  811.  
  812.        switch (command -> header.command & ENET_PROTOCOL_COMMAND_MASK)
  813.        {
  814.        case ENET_PROTOCOL_COMMAND_ACKNOWLEDGE:
  815.           if (enet_protocol_handle_acknowledge (host, event, peer, command))
  816.             goto commandError;
  817.           break;
  818.  
  819.        case ENET_PROTOCOL_COMMAND_CONNECT:
  820.           peer = enet_protocol_handle_connect (host, header, command);
  821.           if (peer == NULL)
  822.             goto commandError;
  823.           break;
  824.  
  825.        case ENET_PROTOCOL_COMMAND_VERIFY_CONNECT:
  826.           if (enet_protocol_handle_verify_connect (host, event, peer, command))
  827.             goto commandError;
  828.           break;
  829.  
  830.        case ENET_PROTOCOL_COMMAND_DISCONNECT:
  831.           if (enet_protocol_handle_disconnect (host, peer, command))
  832.             goto commandError;
  833.           break;
  834.  
  835.        case ENET_PROTOCOL_COMMAND_PING:
  836.           if (enet_protocol_handle_ping (host, peer, command))
  837.             goto commandError;
  838.           break;
  839.  
  840.        case ENET_PROTOCOL_COMMAND_SEND_RELIABLE:
  841.           if (enet_protocol_handle_send_reliable (host, peer, command, & currentData))
  842.             goto commandError;
  843.           break;
  844.  
  845.        case ENET_PROTOCOL_COMMAND_SEND_UNRELIABLE:
  846.           if (enet_protocol_handle_send_unreliable (host, peer, command, & currentData))
  847.             goto commandError;
  848.           break;
  849.  
  850.        case ENET_PROTOCOL_COMMAND_SEND_UNSEQUENCED:
  851.           if (enet_protocol_handle_send_unsequenced (host, peer, command, & currentData))
  852.             goto commandError;
  853.           break;
  854.  
  855.        case ENET_PROTOCOL_COMMAND_SEND_FRAGMENT:
  856.           if (enet_protocol_handle_send_fragment (host, peer, command, & currentData))
  857.             goto commandError;
  858.           break;
  859.  
  860.        case ENET_PROTOCOL_COMMAND_BANDWIDTH_LIMIT:
  861.           if (enet_protocol_handle_bandwidth_limit (host, peer, command))
  862.             goto commandError;
  863.           break;
  864.  
  865.        case ENET_PROTOCOL_COMMAND_THROTTLE_CONFIGURE:
  866.           if (enet_protocol_handle_throttle_configure (host, peer, command))
  867.             goto commandError;
  868.           break;
  869.  
  870.        default:
  871.           goto commandError;
  872.        }
  873.  
  874.        if (peer != NULL &&
  875.            (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE) != 0)
  876.        {
  877.            enet_uint16 sentTime;
  878.  
  879.            if (! (flags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME))
  880.              break;
  881.  
  882.            sentTime = ENET_NET_TO_HOST_16 (header -> sentTime);
  883.  
  884.            switch (peer -> state)
  885.            {
  886.            case ENET_PEER_STATE_DISCONNECTING:
  887.            case ENET_PEER_STATE_ACKNOWLEDGING_CONNECT:
  888.               break;
  889.  
  890.            case ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT:
  891.               if ((command -> header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
  892.                 enet_peer_queue_acknowledgement (peer, command, sentTime);
  893.               break;
  894.  
  895.            default:   
  896.               enet_peer_queue_acknowledgement (peer, command, sentTime);        
  897.               break;
  898.            }
  899.        }
  900.     }
  901.  
  902. commandError:
  903.     if (event != NULL && event -> type != ENET_EVENT_TYPE_NONE)
  904.       return 1;
  905.  
  906.     return 0;
  907. }
  908.  
  909. static int
  910. enet_protocol_receive_incoming_commands (ENetHost * host, ENetEvent * event)
  911. {
  912.     for (;;)
  913.     {
  914.        int receivedLength;
  915.        ENetBuffer buffer;
  916.  
  917.        buffer.data = host -> receivedData;
  918.        buffer.dataLength = sizeof (host -> receivedData);
  919.  
  920.        receivedLength = enet_socket_receive (host -> socket,
  921.                                              & host -> receivedAddress,
  922.                                              & buffer,
  923.                                              1);
  924.  
  925.        if (receivedLength < 0)
  926.          return -1;
  927.  
  928.        if (receivedLength == 0)
  929.          return 0;
  930.  
  931.        host -> receivedDataLength = receivedLength;
  932.        
  933.        switch (enet_protocol_handle_incoming_commands (host, event))
  934.        {
  935.        case 1:
  936.           return 1;
  937.        
  938.        case -1:
  939.           return -1;
  940.  
  941.        default:
  942.           break;
  943.        }
  944.     }
  945.  
  946.     return -1;
  947. }
  948.  
  949. static void
  950. enet_protocol_send_acknowledgements (ENetHost * host, ENetPeer * peer)
  951. {
  952.     ENetProtocol * command = & host -> commands [host -> commandCount];
  953.     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
  954.     ENetAcknowledgement * acknowledgement;
  955.     ENetListIterator currentAcknowledgement;
  956.   
  957.     currentAcknowledgement = enet_list_begin (& peer -> acknowledgements);
  958.          
  959.     while (currentAcknowledgement != enet_list_end (& peer -> acknowledgements))
  960.     {
  961.        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
  962.            buffer >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
  963.            peer -> mtu - host -> packetSize < sizeof (ENetProtocolAcknowledge))
  964.        {
  965.           host -> continueSending = 1;
  966.  
  967.           break;
  968.        }
  969.  
  970.        acknowledgement = (ENetAcknowledgement *) currentAcknowledgement;
  971.  
  972.        currentAcknowledgement = enet_list_next (currentAcknowledgement);
  973.  
  974.        buffer -> data = command;
  975.        buffer -> dataLength = sizeof (ENetProtocolAcknowledge);
  976.  
  977.        host -> packetSize += buffer -> dataLength;
  978.  
  979.        command -> header.command = ENET_PROTOCOL_COMMAND_ACKNOWLEDGE;
  980.        command -> header.channelID = acknowledgement -> command.header.channelID;
  981.        command -> acknowledge.receivedReliableSequenceNumber = ENET_HOST_TO_NET_16 (acknowledgement -> command.header.reliableSequenceNumber);
  982.        command -> acknowledge.receivedSentTime = ENET_HOST_TO_NET_16 (acknowledgement -> sentTime);
  983.   
  984.        if ((acknowledgement -> command.header.command & ENET_PROTOCOL_COMMAND_MASK) == ENET_PROTOCOL_COMMAND_DISCONNECT)
  985.          peer -> state = ENET_PEER_STATE_ZOMBIE;
  986.  
  987.        enet_list_remove (& acknowledgement -> acknowledgementList);
  988.        enet_free (acknowledgement);
  989.  
  990.        ++ command;
  991.        ++ buffer;
  992.     }
  993.  
  994.     host -> commandCount = command - host -> commands;
  995.     host -> bufferCount = buffer - host -> buffers;
  996. }
  997.  
  998. static void
  999. enet_protocol_send_unreliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
  1000. {
  1001.     ENetProtocol * command = & host -> commands [host -> commandCount];
  1002.     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
  1003.     ENetOutgoingCommand * outgoingCommand;
  1004.     ENetListIterator currentCommand;
  1005.  
  1006.     currentCommand = enet_list_begin (& peer -> outgoingUnreliableCommands);
  1007.     
  1008.     while (currentCommand != enet_list_end (& peer -> outgoingUnreliableCommands))
  1009.     {
  1010.        size_t commandSize;
  1011.  
  1012.        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
  1013.        commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
  1014.  
  1015.        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
  1016.            buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
  1017.            peer -> mtu - host -> packetSize < commandSize ||
  1018.            (outgoingCommand -> packet != NULL &&
  1019.              peer -> mtu - host -> packetSize < commandSize + outgoingCommand -> packet -> dataLength))
  1020.        {
  1021.           host -> continueSending = 1;
  1022.  
  1023.           break;
  1024.        }
  1025.  
  1026.        currentCommand = enet_list_next (currentCommand);
  1027.  
  1028.        if (outgoingCommand -> packet != NULL)
  1029.        {
  1030.           peer -> packetThrottleCounter += ENET_PEER_PACKET_THROTTLE_COUNTER;
  1031.           peer -> packetThrottleCounter %= ENET_PEER_PACKET_THROTTLE_SCALE;
  1032.           
  1033.           if (peer -> packetThrottleCounter > peer -> packetThrottle)
  1034.           {
  1035.              -- outgoingCommand -> packet -> referenceCount;
  1036.  
  1037.              if (outgoingCommand -> packet -> referenceCount == 0)
  1038.                enet_packet_destroy (outgoingCommand -> packet);
  1039.          
  1040.              enet_list_remove (& outgoingCommand -> outgoingCommandList);
  1041.              enet_free (outgoingCommand);
  1042.            
  1043.              continue;
  1044.           }
  1045.        }
  1046.  
  1047.        buffer -> data = command;
  1048.        buffer -> dataLength = commandSize;
  1049.       
  1050.        host -> packetSize += buffer -> dataLength;
  1051.  
  1052.        * command = outgoingCommand -> command;
  1053.        
  1054.        enet_list_remove (& outgoingCommand -> outgoingCommandList);
  1055.  
  1056.        if (outgoingCommand -> packet != NULL)
  1057.        {
  1058.           ++ buffer;
  1059.           
  1060.           buffer -> data = outgoingCommand -> packet -> data;
  1061.           buffer -> dataLength = outgoingCommand -> packet -> dataLength;
  1062.  
  1063.           host -> packetSize += buffer -> dataLength;
  1064.  
  1065.           enet_list_insert (enet_list_end (& peer -> sentUnreliableCommands), outgoingCommand);
  1066.        }
  1067.        else
  1068.          enet_free (outgoingCommand);
  1069.  
  1070.        ++ command;
  1071.        ++ buffer;
  1072.     } 
  1073.  
  1074.     host -> commandCount = command - host -> commands;
  1075.     host -> bufferCount = buffer - host -> buffers;
  1076.  
  1077.     if (peer -> state == ENET_PEER_STATE_DISCONNECT_LATER && 
  1078.         enet_list_empty (& peer -> outgoingReliableCommands) &&
  1079.         enet_list_empty (& peer -> outgoingUnreliableCommands) && 
  1080.         enet_list_empty (& peer -> sentReliableCommands))
  1081.       enet_peer_disconnect (peer, peer -> disconnectData);
  1082. }
  1083.  
  1084. static int
  1085. enet_protocol_check_timeouts (ENetHost * host, ENetPeer * peer, ENetEvent * event)
  1086. {
  1087.     ENetOutgoingCommand * outgoingCommand;
  1088.     ENetListIterator currentCommand;
  1089.  
  1090.     currentCommand = enet_list_begin (& peer -> sentReliableCommands);
  1091.  
  1092.     while (currentCommand != enet_list_end (& peer -> sentReliableCommands))
  1093.     {
  1094.        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
  1095.  
  1096.        currentCommand = enet_list_next (currentCommand);
  1097.  
  1098.        if (ENET_TIME_DIFFERENCE (timeCurrent, outgoingCommand -> sentTime) < outgoingCommand -> roundTripTimeout)
  1099.          continue;
  1100.  
  1101.        if(peer -> earliestTimeout == 0 ||
  1102.           ENET_TIME_LESS(outgoingCommand -> sentTime, peer -> earliestTimeout))
  1103.            peer -> earliestTimeout = outgoingCommand -> sentTime;
  1104.  
  1105.        if (peer -> earliestTimeout != 0 &&
  1106.              (ENET_TIME_DIFFERENCE(timeCurrent, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MAXIMUM ||
  1107.                (outgoingCommand -> roundTripTimeout >= outgoingCommand -> roundTripTimeoutLimit &&
  1108.                  ENET_TIME_DIFFERENCE(timeCurrent, peer -> earliestTimeout) >= ENET_PEER_TIMEOUT_MINIMUM)))
  1109.        {
  1110.           enet_protocol_notify_disconnect (host, peer, event);
  1111.  
  1112.           return 1;
  1113.        }
  1114.  
  1115.        if (outgoingCommand -> packet != NULL)
  1116.          peer -> reliableDataInTransit -= outgoingCommand -> fragmentLength;
  1117.           
  1118.        ++ peer -> packetsLost;
  1119.  
  1120.        outgoingCommand -> roundTripTimeout *= 2;
  1121.  
  1122.        enet_list_insert (enet_list_begin (& peer -> outgoingReliableCommands),
  1123.                          enet_list_remove (& outgoingCommand -> outgoingCommandList));
  1124.  
  1125.        if (currentCommand == enet_list_begin (& peer -> sentReliableCommands) &&
  1126.            ! enet_list_empty (& peer -> sentReliableCommands))
  1127.        {
  1128.           outgoingCommand = (ENetOutgoingCommand *) currentCommand;
  1129.  
  1130.           peer -> nextTimeout = outgoingCommand -> sentTime + outgoingCommand -> roundTripTimeout;
  1131.        }
  1132.     }
  1133.     
  1134.     return 0;
  1135. }
  1136.  
  1137. static void
  1138. enet_protocol_send_reliable_outgoing_commands (ENetHost * host, ENetPeer * peer)
  1139. {
  1140.     ENetProtocol * command = & host -> commands [host -> commandCount];
  1141.     ENetBuffer * buffer = & host -> buffers [host -> bufferCount];
  1142.     ENetOutgoingCommand * outgoingCommand;
  1143.     ENetListIterator currentCommand;
  1144.  
  1145.     currentCommand = enet_list_begin (& peer -> outgoingReliableCommands);
  1146.     
  1147.     while (currentCommand != enet_list_end (& peer -> outgoingReliableCommands))
  1148.     {
  1149.        size_t commandSize;
  1150.  
  1151.        outgoingCommand = (ENetOutgoingCommand *) currentCommand;
  1152.        commandSize = commandSizes [outgoingCommand -> command.header.command & ENET_PROTOCOL_COMMAND_MASK];
  1153.     
  1154.        if (command >= & host -> commands [sizeof (host -> commands) / sizeof (ENetProtocol)] ||
  1155.            buffer + 1 >= & host -> buffers [sizeof (host -> buffers) / sizeof (ENetBuffer)] ||
  1156.            peer -> mtu - host -> packetSize < commandSize)
  1157.        {
  1158.           host -> continueSending = 1;
  1159.           
  1160.           break;
  1161.        }
  1162.  
  1163.        currentCommand = enet_list_next (currentCommand);
  1164.  
  1165.        if (outgoingCommand -> packet != NULL)
  1166.        {
  1167.           if (peer -> reliableDataInTransit + outgoingCommand -> fragmentLength > peer -> windowSize)
  1168.             break;
  1169.  
  1170.           if ((enet_uint16) (peer -> mtu - host -> packetSize) < (enet_uint16) (commandSize + outgoingCommand -> fragmentLength))
  1171.           {
  1172.              host -> continueSending = 1;
  1173.  
  1174.              break;
  1175.           }
  1176.        }
  1177.        
  1178.        if (outgoingCommand -> roundTripTimeout == 0)
  1179.        {
  1180.           outgoingCommand -> roundTripTimeout = peer -> roundTripTime + 4 * peer -> roundTripTimeVariance;
  1181.           outgoingCommand -> roundTripTimeoutLimit = ENET_PEER_TIMEOUT_LIMIT * outgoingCommand -> roundTripTimeout;
  1182.        }
  1183.  
  1184.        if (enet_list_empty (& peer -> sentReliableCommands))
  1185.          peer -> nextTimeout = timeCurrent + outgoingCommand -> roundTripTimeout;
  1186.  
  1187.        enet_list_insert (enet_list_end (& peer -> sentReliableCommands),
  1188.                          enet_list_remove (& outgoingCommand -> outgoingCommandList));
  1189.  
  1190.        outgoingCommand -> sentTime = timeCurrent;
  1191.  
  1192.        buffer -> data = command;
  1193.        buffer -> dataLength = commandSize;
  1194.  
  1195.        host -> packetSize += buffer -> dataLength;
  1196.        host -> headerFlags |= ENET_PROTOCOL_HEADER_FLAG_SENT_TIME;
  1197.  
  1198.        * command = outgoingCommand -> command;
  1199.  
  1200.        if (outgoingCommand -> packet != NULL)
  1201.        {
  1202.           ++ buffer;
  1203.           
  1204.           buffer -> data = outgoingCommand -> packet -> data + outgoingCommand -> fragmentOffset;
  1205.           buffer -> dataLength = outgoingCommand -> fragmentLength;
  1206.  
  1207.           host -> packetSize += outgoingCommand -> fragmentLength;
  1208.  
  1209.           peer -> reliableDataInTransit += outgoingCommand -> fragmentLength;
  1210.        }
  1211.  
  1212.        ++ peer -> packetsSent;
  1213.         
  1214.        ++ command;
  1215.        ++ buffer;
  1216.     }
  1217.  
  1218.     host -> commandCount = command - host -> commands;
  1219.     host -> bufferCount = buffer - host -> buffers;
  1220. }
  1221.  
  1222. static int
  1223. enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
  1224. {
  1225.     ENetProtocolHeader header;
  1226.     ENetPeer * currentPeer;
  1227.     int sentLength;
  1228.     
  1229.     host -> continueSending = 1;
  1230.  
  1231.     while (host -> continueSending)
  1232.     for (host -> continueSending = 0,
  1233.            currentPeer = host -> peers;
  1234.          currentPeer < & host -> peers [host -> peerCount];
  1235.          ++ currentPeer)
  1236.     {
  1237.         if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
  1238.             currentPeer -> state == ENET_PEER_STATE_ZOMBIE)
  1239.           continue;
  1240.  
  1241.         host -> headerFlags = 0;
  1242.         host -> commandCount = 0;
  1243.         host -> bufferCount = 1;
  1244.         host -> packetSize = sizeof (ENetProtocolHeader);
  1245.  
  1246.         if (! enet_list_empty (& currentPeer -> acknowledgements))
  1247.           enet_protocol_send_acknowledgements (host, currentPeer);
  1248.  
  1249.         if (checkForTimeouts != 0 &&
  1250.             ! enet_list_empty (& currentPeer -> sentReliableCommands) &&
  1251.             ENET_TIME_GREATER_EQUAL (timeCurrent, currentPeer -> nextTimeout) &&
  1252.             enet_protocol_check_timeouts (host, currentPeer, event) == 1)
  1253.           return 1;
  1254.  
  1255.         if (! enet_list_empty (& currentPeer -> outgoingReliableCommands))
  1256.           enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
  1257.         else
  1258.         if (enet_list_empty (& currentPeer -> sentReliableCommands) &&
  1259.             ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL &&
  1260.             currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing))
  1261.         { 
  1262.             enet_peer_ping (currentPeer);
  1263.             enet_protocol_send_reliable_outgoing_commands (host, currentPeer);
  1264.         }
  1265.                       
  1266.         if (! enet_list_empty (& currentPeer -> outgoingUnreliableCommands))
  1267.           enet_protocol_send_unreliable_outgoing_commands (host, currentPeer);
  1268.  
  1269.         if (host -> commandCount == 0)
  1270.           continue;
  1271.  
  1272.         if (currentPeer -> packetLossEpoch == 0)
  1273.           currentPeer -> packetLossEpoch = timeCurrent;
  1274.         else
  1275.         if (ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL &&
  1276.             currentPeer -> packetsSent > 0)
  1277.         {
  1278.            enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent;
  1279.  
  1280. #ifdef ENET_DEBUG
  1281. #ifdef WIN32
  1282.            printf (
  1283. #else
  1284.            fprintf (stderr, 
  1285. #endif
  1286.                     "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);
  1287. #endif
  1288.           
  1289.            currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4;
  1290.  
  1291.            if (packetLoss >= currentPeer -> packetLoss)
  1292.            {
  1293.               currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8;
  1294.               currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4;
  1295.            }
  1296.            else
  1297.            {
  1298.               currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8;
  1299.               currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4;
  1300.            }
  1301.  
  1302.            currentPeer -> packetLossEpoch = timeCurrent;
  1303.            currentPeer -> packetsSent = 0;
  1304.            currentPeer -> packetsLost = 0;
  1305.         }
  1306.  
  1307.         header.checksum = currentPeer -> sessionID;
  1308.         header.peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID | host -> headerFlags);
  1309.         
  1310.         host -> buffers -> data = & header;
  1311.         if (host -> headerFlags & ENET_PROTOCOL_HEADER_FLAG_SENT_TIME)
  1312.         {
  1313.             header.sentTime = ENET_HOST_TO_NET_16 (timeCurrent & 0xFFFF);
  1314.  
  1315.             host -> buffers -> dataLength = sizeof (ENetProtocolHeader);
  1316.         }
  1317.         else
  1318.           host -> buffers -> dataLength = (size_t) & ((ENetProtocolHeader *) 0) -> sentTime;
  1319.  
  1320. #ifdef USE_CRC32
  1321.         header.checksum = enet_crc32 (host -> buffers, host -> bufferCount);
  1322. #endif
  1323.  
  1324.         currentPeer -> lastSendTime = timeCurrent;
  1325.  
  1326.         sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount);
  1327.  
  1328.         enet_protocol_remove_sent_unreliable_commands (currentPeer);
  1329.  
  1330.         if (sentLength < 0)
  1331.           return -1;
  1332.     }
  1333.    
  1334.     return 0;
  1335. }
  1336.  
  1337. /** Sends any queued packets on the host specified to its designated peers.
  1338.  
  1339.     @param host   host to flush
  1340.     @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().
  1341.     @ingroup host
  1342. */
  1343. void
  1344. enet_host_flush (ENetHost * host)
  1345. {
  1346.     timeCurrent = enet_time_get ();
  1347.  
  1348.     enet_protocol_send_outgoing_commands (host, NULL, 0);
  1349. }
  1350.  
  1351. /** Waits for events on the host specified and shuttles packets between
  1352.     the host and its peers.
  1353.  
  1354.     @param host    host to service
  1355.     @param event   an event structure where event details will be placed if one occurs
  1356.                    if event == NULL then no events will be delivered
  1357.     @param timeout number of milliseconds that ENet should wait for events
  1358.     @retval > 0 if an event occurred within the specified time limit
  1359.     @retval 0 if no event occurred
  1360.     @retval < 0 on failure
  1361.     @remarks enet_host_service should be called fairly regularly for adequate performance
  1362.     @ingroup host
  1363. */
  1364. int
  1365. enet_host_service (ENetHost * host, ENetEvent * event, enet_uint32 timeout)
  1366. {
  1367.     enet_uint32 waitCondition;
  1368.  
  1369.     if (event != NULL)
  1370.     {
  1371.         event -> type = ENET_EVENT_TYPE_NONE;
  1372.         event -> peer = NULL;
  1373.         event -> packet = NULL;
  1374.  
  1375.         switch (enet_protocol_dispatch_incoming_commands (host, event))
  1376.         {
  1377.         case 1:
  1378.             return 1;
  1379.  
  1380.         case -1:
  1381.             perror ("Error dispatching incoming packets");
  1382.  
  1383.             return -1;
  1384.  
  1385.         default:
  1386.             break;
  1387.         }
  1388.     }
  1389.  
  1390.     timeCurrent = enet_time_get ();
  1391.     
  1392.     timeout += timeCurrent;
  1393.  
  1394.     do
  1395.     {
  1396.        if (ENET_TIME_DIFFERENCE (timeCurrent, host -> bandwidthThrottleEpoch) >= ENET_HOST_BANDWIDTH_THROTTLE_INTERVAL)
  1397.          enet_host_bandwidth_throttle (host);
  1398.  
  1399.        switch (enet_protocol_send_outgoing_commands (host, event, 1))
  1400.        {
  1401.        case 1:
  1402.           return 1;
  1403.  
  1404.        case -1:
  1405.           perror ("Error sending outgoing packets");
  1406.  
  1407.           return -1;
  1408.  
  1409.        default:
  1410.           break;
  1411.        }
  1412.  
  1413.        switch (enet_protocol_receive_incoming_commands (host, event))
  1414.        {
  1415.        case 1:
  1416.           return 1;
  1417.  
  1418.        case -1:
  1419.           perror ("Error receiving incoming packets");
  1420.  
  1421.           return -1;
  1422.  
  1423.        default:
  1424.           break;
  1425.        }
  1426.  
  1427.        switch (enet_protocol_send_outgoing_commands (host, event, 1))
  1428.        {
  1429.        case 1:
  1430.           return 1;
  1431.  
  1432.        case -1:
  1433.           perror ("Error sending outgoing packets");
  1434.  
  1435.           return -1;
  1436.  
  1437.        default:
  1438.           break;
  1439.        }
  1440.  
  1441.        if (event != NULL)
  1442.        {
  1443.           switch (enet_protocol_dispatch_incoming_commands (host, event))
  1444.           {
  1445.           case 1:
  1446.              return 1;
  1447.  
  1448.           case -1:
  1449.              perror ("Error dispatching incoming packets");
  1450.  
  1451.              return -1;
  1452.  
  1453.           default:
  1454.              break;
  1455.           }
  1456.        }
  1457.  
  1458.        timeCurrent = enet_time_get ();
  1459.  
  1460.        if (ENET_TIME_GREATER_EQUAL (timeCurrent, timeout))
  1461.          return 0;
  1462.  
  1463.        waitCondition = ENET_SOCKET_WAIT_RECEIVE;
  1464.  
  1465.        if (enet_socket_wait (host -> socket, & waitCondition, ENET_TIME_DIFFERENCE (timeout, timeCurrent)) != 0)
  1466.          return -1;
  1467.        
  1468.        timeCurrent = enet_time_get ();
  1469.     } while (waitCondition == ENET_SOCKET_WAIT_RECEIVE);
  1470.  
  1471.     return 0; 
  1472. }
  1473.  
  1474.