Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent iteration over inactive peers #266

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion host.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,22 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
}
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));

host -> activePeers = (ENetPeer **)enet_malloc((peerCount + 1) * sizeof(ENetPeer*));
if (host->activePeers == NULL)
{
enet_free(host->peers);
enet_free(host);
return NULL;
}
memset (host -> peers, 0, peerCount * sizeof (ENetPeer));

host -> socket = enet_socket_create (ENET_SOCKET_TYPE_DATAGRAM);
if (host -> socket == ENET_SOCKET_NULL || (address != NULL && enet_socket_bind (host -> socket, address) < 0))
{
if (host -> socket != ENET_SOCKET_NULL)
enet_socket_destroy (host -> socket);

enet_free (host -> activePeers);
enet_free (host -> peers);
enet_free (host);

Expand Down Expand Up @@ -84,6 +94,7 @@ enet_host_create (const ENetAddress * address, size_t peerCount, size_t channelL
host -> recalculateBandwidthLimits = 0;
host -> mtu = ENET_HOST_DEFAULT_MTU;
host -> peerCount = peerCount;
host -> peerStatesChanged = 1;
host -> commandCount = 0;
host -> bufferCount = 0;
host -> checksum = NULL;
Expand Down Expand Up @@ -157,6 +168,7 @@ enet_host_destroy (ENetHost * host)
if (host -> compressor.context != NULL && host -> compressor.destroy)
(* host -> compressor.destroy) (host -> compressor.context);

enet_free (host -> activePeers);
enet_free (host -> peers);
enet_free (host);
}
Expand Down Expand Up @@ -208,7 +220,7 @@ enet_host_connect (ENetHost * host, const ENetAddress * address, size_t channelC
if (currentPeer -> channels == NULL)
return NULL;
currentPeer -> channelCount = channelCount;
currentPeer -> state = ENET_PEER_STATE_CONNECTING;
enet_peer_change_state(currentPeer, ENET_PEER_STATE_CONNECTING);
currentPeer -> address = * address;
currentPeer -> connectID = enet_host_random (host);
currentPeer -> mtu = host -> mtu;
Expand Down
3 changes: 3 additions & 0 deletions include/enet/enet.h
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,8 @@ typedef struct _ENetHost
int recalculateBandwidthLimits;
ENetPeer * peers; /**< array of peers allocated for this host */
size_t peerCount; /**< number of peers allocated for this host */
int peerStatesChanged; /**< 0,1 - flagged on any peer state change */
ENetPeer ** activePeers; /**< active peer pointers */
size_t channelLimit; /**< maximum number of channels allowed for connected peers */
enet_uint32 serviceTime;
ENetList dispatchQueue;
Expand Down Expand Up @@ -599,6 +601,7 @@ extern void enet_peer_dispatch_incoming_unreliable_commands (EN
extern void enet_peer_dispatch_incoming_reliable_commands (ENetPeer *, ENetChannel *, ENetIncomingCommand *);
extern void enet_peer_on_connect (ENetPeer *);
extern void enet_peer_on_disconnect (ENetPeer *);
extern void enet_peer_change_state(ENetPeer *, ENetPeerState);

ENET_API void * enet_range_coder_create (void);
ENET_API void enet_range_coder_destroy (void *);
Expand Down
16 changes: 13 additions & 3 deletions peer.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,16 @@ enet_peer_on_disconnect (ENetPeer * peer)
}
}

void
enet_peer_change_state(ENetPeer * peer, ENetPeerState newState)
{
peer->state = newState;
if (peer->host)
{
peer->host->peerStatesChanged = 1;
}
}

/** Forcefully disconnects a peer.
@param peer peer to forcefully disconnect
@remarks The foreign host represented by the peer is not notified of the disconnection and will timeout
Expand All @@ -389,7 +399,7 @@ enet_peer_reset (ENetPeer * peer)
peer -> outgoingPeerID = ENET_PROTOCOL_MAXIMUM_PEER_ID;
peer -> connectID = 0;

peer -> state = ENET_PEER_STATE_DISCONNECTED;
enet_peer_change_state(peer, ENET_PEER_STATE_DISCONNECTED);

peer -> incomingBandwidth = 0;
peer -> outgoingBandwidth = 0;
Expand Down Expand Up @@ -565,7 +575,7 @@ enet_peer_disconnect (ENetPeer * peer, enet_uint32 data)
{
enet_peer_on_disconnect (peer);

peer -> state = ENET_PEER_STATE_DISCONNECTING;
enet_peer_change_state(peer, ENET_PEER_STATE_DISCONNECTING);
}
else
{
Expand Down Expand Up @@ -597,7 +607,7 @@ enet_peer_disconnect_later (ENetPeer * peer, enet_uint32 data)
if ((peer -> state == ENET_PEER_STATE_CONNECTED || peer -> state == ENET_PEER_STATE_DISCONNECT_LATER) &&
enet_peer_has_outgoing_commands (peer))
{
peer -> state = ENET_PEER_STATE_DISCONNECT_LATER;
enet_peer_change_state(peer, ENET_PEER_STATE_DISCONNECT_LATER);
peer -> eventData = data;
}
else
Expand Down
38 changes: 33 additions & 5 deletions protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ enet_protocol_change_state (ENetHost * host, ENetPeer * peer, ENetPeerState stat
else
enet_peer_on_disconnect (peer);

peer -> state = state;
enet_peer_change_state(peer, state);
}

static void
Expand Down Expand Up @@ -337,7 +337,7 @@ enet_protocol_handle_connect (ENetHost * host, ENetProtocolHeader * header, ENet
if (peer -> channels == NULL)
return NULL;
peer -> channelCount = channelCount;
peer -> state = ENET_PEER_STATE_ACKNOWLEDGING_CONNECT;
enet_peer_change_state(peer, ENET_PEER_STATE_ACKNOWLEDGING_CONNECT);
peer -> connectID = command -> connect.connectID;
peer -> address = host -> receivedAddress;
peer -> mtu = host -> mtu;
Expand Down Expand Up @@ -1596,22 +1596,49 @@ enet_protocol_check_outgoing_commands (ENetHost * host, ENetPeer * peer, ENetLis
return canPing;
}

static void
enet_protocol_on_peer_states_changed(ENetHost * host)
{
// Update active peers array
enet_uint16 activePeersPos = 0;
for (ENetPeer *currentPeer = host->peers; currentPeer < &host -> peers[host->peerCount]; ++currentPeer)
{
if (currentPeer -> state != ENET_PEER_STATE_DISCONNECTED &&
currentPeer -> state != ENET_PEER_STATE_ZOMBIE)
{
host -> activePeers[activePeersPos] = currentPeer;
activePeersPos++;
}
}
// End of active peers
host -> activePeers[activePeersPos] = NULL;
}

static int
enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts)
{
enet_uint8 headerData [sizeof (ENetProtocolHeader) + sizeof (enet_uint32)];
ENetProtocolHeader * header = (ENetProtocolHeader *) headerData;
int sentLength = 0;
ENetPeer * currentPeer = NULL;
size_t shouldCompress = 0;
ENetList sentUnreliableCommands;

enet_list_clear (& sentUnreliableCommands);

for (int sendPass = 0, continueSending = 0; sendPass <= continueSending; ++ sendPass)
for (ENetPeer * currentPeer = host -> peers;
currentPeer < & host -> peers [host -> peerCount];
++ currentPeer)
{
// Check if active peers array must be refilled.
// Normally a peer state is stable and equals Connected or Disconnected, so no refilling is required.
if (host->peerStatesChanged)
{
host->peerStatesChanged = 0;
enet_protocol_on_peer_states_changed(host);
}

for (enet_uint16 i = 0; host->activePeers[i]; ++i)
{
currentPeer = host->activePeers[i];
if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED ||
currentPeer -> state == ENET_PEER_STATE_ZOMBIE ||
(sendPass > 0 && ! (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)))
Expand Down Expand Up @@ -1737,6 +1764,7 @@ enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int ch
nextPeer:
if (currentPeer -> flags & ENET_PEER_FLAG_CONTINUE_SENDING)
continueSending = sendPass + 1;
}
}

return 0;
Expand Down