Browse Source

track the number of connected peers to make throttling a bit cheaper

Lee Salzman 12 years ago
parent
commit
69b98608e5
4 changed files with 93 additions and 45 deletions
  1. 24 27
      host.c
  2. 4 0
      include/enet/enet.h
  3. 32 2
      peer.c
  4. 33 16
      protocol.c

+ 24 - 27
host.c

@@ -102,6 +102,9 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
     host -> totalReceivedData = 0;
     host -> totalReceivedData = 0;
     host -> totalReceivedPackets = 0;
     host -> totalReceivedPackets = 0;
 
 
+    host -> connectedPeers = 0;
+    host -> bandwidthLimitedPeers = 0;
+
     host -> compressor.context = NULL;
     host -> compressor.context = NULL;
     host -> compressor.compress = NULL;
     host -> compressor.compress = NULL;
     host -> compressor.decompress = NULL;
     host -> compressor.decompress = NULL;
@@ -328,13 +331,12 @@ enet_host_bandwidth_throttle (ENetHost * host)
 {
 {
     enet_uint32 timeCurrent = enet_time_get (),
     enet_uint32 timeCurrent = enet_time_get (),
            elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
            elapsedTime = timeCurrent - host -> bandwidthThrottleEpoch,
-           peersTotal = 0,
-           dataTotal = 0,
-           peersRemaining,
-           bandwidth,
+           peersRemaining = (enet_uint32) host -> connectedPeers,
+           dataTotal = ~0,
+           bandwidth = ~0,
            throttle = 0,
            throttle = 0,
            bandwidthLimit = 0;
            bandwidthLimit = 0;
-    int needsAdjustment = 0;
+    int needsAdjustment = host -> bandwidthLimitedPeers > 0 ? 1 : 0;
     ENetPeer * peer;
     ENetPeer * peer;
     ENetProtocol command;
     ENetProtocol command;
 
 
@@ -343,35 +345,30 @@ enet_host_bandwidth_throttle (ENetHost * host)
 
 
     host -> bandwidthThrottleEpoch = timeCurrent;
     host -> bandwidthThrottleEpoch = timeCurrent;
 
 
-    for (peer = host -> peers;
-         peer < & host -> peers [host -> peerCount];
-         ++ peer)
+    if (peersRemaining == 0)
+      return;
+
+    if (host -> outgoingBandwidth != 0)
     {
     {
-        if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
-          continue;
+        dataTotal = 0;
+        bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
 
 
-        if (peer -> incomingBandwidth != 0)
-          needsAdjustment = 1;
+        for (peer = host -> peers;
+             peer < & host -> peers [host -> peerCount];
+            ++ peer)
+        {
+            if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
+              continue;
 
 
-        ++ peersTotal;
-        dataTotal += peer -> outgoingDataTotal;
+            dataTotal += peer -> outgoingDataTotal;
+        }
     }
     }
 
 
-    if (peersTotal == 0)
-      return;
-
-    peersRemaining = peersTotal;
-
-    if (host -> outgoingBandwidth == 0)
-      bandwidth = ~0;
-    else
-      bandwidth = (host -> outgoingBandwidth * elapsedTime) / 1000;
-
     while (peersRemaining > 0 && needsAdjustment != 0)
     while (peersRemaining > 0 && needsAdjustment != 0)
     {
     {
         needsAdjustment = 0;
         needsAdjustment = 0;
         
         
-        if (dataTotal < bandwidth)
+        if (dataTotal <= bandwidth)
           throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
           throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
         else
         else
           throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
           throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
@@ -414,7 +411,7 @@ enet_host_bandwidth_throttle (ENetHost * host)
 
 
     if (peersRemaining > 0)
     if (peersRemaining > 0)
     {
     {
-        if (dataTotal < bandwidth)
+        if (dataTotal <= bandwidth)
           throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
           throttle = ENET_PEER_PACKET_THROTTLE_SCALE;
         else
         else
           throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
           throttle = (bandwidth * ENET_PEER_PACKET_THROTTLE_SCALE) / dataTotal;
@@ -441,7 +438,7 @@ enet_host_bandwidth_throttle (ENetHost * host)
     {
     {
        host -> recalculateBandwidthLimits = 0;
        host -> recalculateBandwidthLimits = 0;
 
 
-       peersRemaining = peersTotal;
+       peersRemaining = (enet_uint32) host -> connectedPeers;
        bandwidth = host -> incomingBandwidth;
        bandwidth = host -> incomingBandwidth;
        needsAdjustment = 1;
        needsAdjustment = 1;
 
 

+ 4 - 0
include/enet/enet.h

@@ -383,6 +383,8 @@ typedef struct _ENetHost
    enet_uint32          totalReceivedData;           /**< total data received, user should reset to 0 as needed to prevent overflow */
    enet_uint32          totalReceivedData;           /**< total data received, user should reset to 0 as needed to prevent overflow */
    enet_uint32          totalReceivedPackets;        /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */
    enet_uint32          totalReceivedPackets;        /**< total UDP packets received, user should reset to 0 as needed to prevent overflow */
    ENetInterceptCallback intercept;                  /**< callback the user can set to intercept received raw UDP packets */
    ENetInterceptCallback intercept;                  /**< callback the user can set to intercept received raw UDP packets */
+   size_t               connectedPeers;
+   size_t               bandwidthLimitedPeers;
 } ENetHost;
 } ENetHost;
 
 
 /**
 /**
@@ -566,6 +568,8 @@ extern ENetIncomingCommand * enet_peer_queue_incoming_command (ENetPeer *, const
 extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
 extern ENetAcknowledgement * enet_peer_queue_acknowledgement (ENetPeer *, const ENetProtocol *, enet_uint16);
 extern void                  enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *);
 extern void                  enet_peer_dispatch_incoming_unreliable_commands (ENetPeer *, ENetChannel *);
 extern void                  enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *);
 extern void                  enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *);
+extern void                  enet_peer_on_connect (ENetPeer *);
+extern void                  enet_peer_on_disconnect (ENetPeer *);
 
 
 ENET_API void * enet_range_coder_create (void);
 ENET_API void * enet_range_coder_create (void);
 ENET_API void   enet_range_coder_destroy (void *);
 ENET_API void   enet_range_coder_destroy (void *);

+ 32 - 2
peer.c

@@ -337,6 +337,30 @@ enet_peer_reset_queues (ENetPeer * peer)
     peer -> channelCount = 0;
     peer -> channelCount = 0;
 }
 }
 
 
+void
+enet_peer_on_connect (ENetPeer * peer)
+{
+    if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
+    {
+        if (peer -> incomingBandwidth != 0)
+          ++ peer -> host -> bandwidthLimitedPeers;
+
+        ++ peer -> host -> connectedPeers;
+    }
+}
+
+void
+enet_peer_on_disconnect (ENetPeer * peer)
+{
+    if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
+    {
+        if (peer -> incomingBandwidth != 0)
+          -- peer -> host -> bandwidthLimitedPeers;
+
+        -- peer -> host -> connectedPeers;
+    }
+}
+
 /** Forcefully disconnects a peer.
 /** Forcefully disconnects a peer.
     @param peer peer to forcefully disconnect
     @param peer peer to forcefully disconnect
     @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
     @remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
@@ -345,6 +369,8 @@ enet_peer_reset_queues (ENetPeer * peer)
 void
 void
 enet_peer_reset (ENetPeer * peer)
 enet_peer_reset (ENetPeer * peer)
 {
 {
+    enet_peer_on_disconnect (peer);
+        
     peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
     peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
     peer -> connectID = 0;
     peer -> connectID = 0;
 
 
@@ -519,7 +545,11 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
     enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
     enet_peer_queue_outgoing_command (peer, & command, NULL, 0, 0);
 
 
     if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
     if (peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER)
-      peer -> state = ENET_PEER_STATE_DISCONNECTING;
+    {
+        enet_peer_notify_disconnect (peer);
+
+        peer -> state = ENET_PEER_STATE_DISCONNECTING;
+    }
     else
     else
     {
     {
         enet_host_flush (peer -> host);
         enet_host_flush (peer -> host);
@@ -584,7 +614,7 @@ void
 enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
 enet_peer_setup_outgoing_command (ENetPeer * peer, ENetOutgoingCommand * outgoingCommand)
 {
 {
     ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
     ENetChannel * channel = & peer -> channels [outgoingCommand -> command.header.channelID];
-
+    
     peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
     peer -> outgoingDataTotal += enet_protocol_command_size (outgoingCommand -> command.header.command) + outgoingCommand -> fragmentLength;
 
 
     if (outgoingCommand -> command.header.channelID == 0xFF)
     if (outgoingCommand -> command.header.channelID == 0xFF)

+ 33 - 16
protocol.c

@@ -32,6 +32,30 @@ enet_protocol_command_size (enet_uint8 commandNumber)
     return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK];
     return commandSizes [commandNumber & ENET_PROTOCOL_COMMAND_MASK];
 }
 }
 
 
+static void
+enet_protocol_change_state (ENetHost * host, ENetPeer * peer, ENetPeerState state)
+{
+    if (state == ENET_PEER_STATE_CONNECTED || state == ENET_PEER_STATE_DISCONNECT_LATER)
+      enet_peer_on_connect (peer);
+    else
+      enet_peer_on_disconnect (peer);
+
+    peer -> state = state;
+}
+
+static void
+enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state)
+{
+    enet_peer_change_state (host, peer, state);
+
+    if (! peer -> needsDispatch)
+    {
+       enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
+
+       peer -> needsDispatch = 1;
+    }
+}
+
 static int
 static int
 enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
 enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
 {
 {
@@ -45,7 +69,7 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
        {
        {
        case ENET_PEER_STATE_CONNECTION_PENDING:
        case ENET_PEER_STATE_CONNECTION_PENDING:
        case ENET_PEER_STATE_CONNECTION_SUCCEEDED:
        case ENET_PEER_STATE_CONNECTION_SUCCEEDED:
-           peer -> state = ENET_PEER_STATE_CONNECTED;
+           enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED);
 
 
            event -> type = ENET_EVENT_TYPE_CONNECT;
            event -> type = ENET_EVENT_TYPE_CONNECT;
            event -> peer = peer;
            event -> peer = peer;
@@ -92,19 +116,6 @@ enet_protocol_dispatch_incoming_commands (ENetHost * host, ENetEvent * event)
     return 0;
     return 0;
 }
 }
 
 
-static void
-enet_protocol_dispatch_state (ENetHost * host, ENetPeer * peer, ENetPeerState state)
-{
-    peer -> state = state;
-
-    if (! peer -> needsDispatch)
-    {
-       enet_list_insert (enet_list_end (& host -> dispatchQueue), & peer -> dispatchList);
-
-       peer -> needsDispatch = 1;
-    }    
-}
-    
 static void
 static void
 enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
 enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * event)
 {
 {
@@ -112,7 +123,7 @@ enet_protocol_notify_connect (ENetHost * host, ENetPeer * peer, ENetEvent * even
 
 
     if (event != NULL)
     if (event != NULL)
     {
     {
-        peer -> state = ENET_PEER_STATE_CONNECTED;
+        enet_protocol_change_state (host, peer, ENET_PEER_STATE_CONNECTED);
 
 
         event -> type = ENET_EVENT_TYPE_CONNECT;
         event -> type = ENET_EVENT_TYPE_CONNECT;
         event -> peer = peer;
         event -> peer = peer;
@@ -762,9 +773,15 @@ enet_protocol_handle_bandwidth_limit (ENetHost * host, ENetPeer * peer, const EN
     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
     if (peer -> state != ENET_PEER_STATE_CONNECTED && peer -> state != ENET_PEER_STATE_DISCONNECT_LATER)
       return -1;
       return -1;
 
 
+    if (peer -> incomingBandwidth != 0)
+      -- host -> bandwidthLimitedPeers;
+
     peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth);
     peer -> incomingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.incomingBandwidth);
     peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth);
     peer -> outgoingBandwidth = ENET_NET_TO_HOST_32 (command -> bandwidthLimit.outgoingBandwidth);
 
 
+    if (peer -> incomingBandwidth != 0)
+      ++ host -> bandwidthLimitedPeers;
+
     if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0)
     if (peer -> incomingBandwidth == 0 && host -> outgoingBandwidth == 0)
       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
       peer -> windowSize = ENET_PROTOCOL_MAXIMUM_WINDOW_SIZE;
     else
     else
@@ -812,7 +829,7 @@ enet_protocol_handle_disconnect (ENetHost * host, ENetPeer * peer, const ENetPro
     }
     }
     else
     else
     if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
     if (command -> header.command & ENET_PROTOCOL_COMMAND_FLAG_ACKNOWLEDGE)
-      peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT;
+      enet_protocol_change_state (host, peer, ENET_PEER_STATE_ACKNOWLEDGING_DISCONNECT);
     else
     else
       enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);
       enet_protocol_dispatch_state (host, peer, ENET_PEER_STATE_ZOMBIE);