//Used to verify that all clients are still connected void NetServer::PingClients() { ENetPeer * pCurrentPeer; for (pCurrentPeer = m_pServer-> peers; pCurrentPeer < & m_pServer->peers [m_pServer->peerCount]; ++ pCurrentPeer) { if (pCurrentPeer->state != ENET_PEER_STATE_CONNECTED) continue; enet_peer_ping (pCurrentPeer); } }
static int enet_protocol_send_outgoing_commands (ENetHost * host, ENetEvent * event, int checkForTimeouts) { size_t packetsSent = 1; ENetProtocolHeader header; ENetPeer * currentPeer; int sentLength; while (packetsSent > 0) for (currentPeer = host -> peers, packetsSent = 0; currentPeer < & host -> peers [host -> peerCount]; ++ currentPeer) { if (currentPeer -> state == ENET_PEER_STATE_DISCONNECTED || currentPeer -> state == ENET_PEER_STATE_ZOMBIE) continue; host -> commandCount = 0; host -> bufferCount = 1; host -> packetSize = sizeof (ENetProtocolHeader); if (enet_list_empty (& currentPeer -> acknowledgements) == 0) enet_protocol_send_acknowledgements (host, currentPeer); if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol)) { if (checkForTimeouts != 0 && enet_list_empty (& currentPeer -> sentReliableCommands) == 0 && ENET_TIME_GREATER_EQUAL (timeCurrent, currentPeer -> nextTimeout) && enet_protocol_check_timeouts (host, currentPeer, event) == 1) return 1; } if (enet_list_empty (& currentPeer -> outgoingReliableCommands) == 0) enet_protocol_send_reliable_outgoing_commands (host, currentPeer); else if (enet_list_empty (& currentPeer -> sentReliableCommands) && ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> lastReceiveTime) >= ENET_PEER_PING_INTERVAL && currentPeer -> mtu - host -> packetSize >= sizeof (ENetProtocolPing)) { enet_peer_ping (currentPeer); enet_protocol_send_reliable_outgoing_commands (host, currentPeer); } if (host -> commandCount < sizeof (host -> commands) / sizeof (ENetProtocol) && enet_list_empty (& currentPeer -> outgoingUnreliableCommands) == 0) enet_protocol_send_unreliable_outgoing_commands (host, currentPeer); if (host -> commandCount == 0) continue; if (currentPeer -> packetLossEpoch == 0) currentPeer -> packetLossEpoch = timeCurrent; else if (ENET_TIME_DIFFERENCE (timeCurrent, currentPeer -> packetLossEpoch) >= ENET_PEER_PACKET_LOSS_INTERVAL && currentPeer -> packetsSent > 0) { enet_uint32 packetLoss = currentPeer -> packetsLost * ENET_PEER_PACKET_LOSS_SCALE / currentPeer -> packetsSent; #ifdef ENET_DEBUG #ifdef WIN32 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)); #else 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)); #endif #endif currentPeer -> packetLossVariance -= currentPeer -> packetLossVariance / 4; if (packetLoss >= currentPeer -> packetLoss) { currentPeer -> packetLoss += (packetLoss - currentPeer -> packetLoss) / 8; currentPeer -> packetLossVariance += (packetLoss - currentPeer -> packetLoss) / 4; } else { currentPeer -> packetLoss -= (currentPeer -> packetLoss - packetLoss) / 8; currentPeer -> packetLossVariance += (currentPeer -> packetLoss - packetLoss) / 4; } currentPeer -> packetLossEpoch = timeCurrent; currentPeer -> packetsSent = 0; currentPeer -> packetsLost = 0; } header.peerID = ENET_HOST_TO_NET_16 (currentPeer -> outgoingPeerID); header.flags = 0; header.commandCount = host -> commandCount; header.sentTime = ENET_HOST_TO_NET_32 (timeCurrent); header.challenge = currentPeer -> challenge; host -> buffers -> data = & header; host -> buffers -> dataLength = sizeof (ENetProtocolHeader); currentPeer -> lastSendTime = timeCurrent; ++ packetsSent; sentLength = enet_socket_send (host -> socket, & currentPeer -> address, host -> buffers, host -> bufferCount); enet_protocol_remove_sent_unreliable_commands (currentPeer); if (sentLength < 0) return -1; } return 0; }
// Receive packets from the network and buffers and create ConnectionEvents void Connection::receive() { if (!m_enet_host) { return; } ENetEvent event; int ret = enet_host_service(m_enet_host, & event, 10); if (ret > 0) { m_last_recieved = porting::getTimeMs(); m_last_recieved_warn = 0; switch (event.type) { case ENET_EVENT_TYPE_CONNECT: { //MutexAutoLock peerlock(m_peers_mutex); u16 peer_id = 0; static u16 last_try = PEER_ID_SERVER + 1; if (m_peers.size() > 0) { for (int i = 0; i < 1000; ++i) { if (last_try > 30000) last_try = PEER_ID_SERVER; ++last_try; if (!m_peers.count(last_try)) { peer_id = last_try; break; } } } else { peer_id = last_try; } if (!peer_id) last_try = peer_id = m_peers.rbegin()->first + 1; m_peers.set(peer_id, event.peer); m_peers_address.set(peer_id, Address(event.peer->address.host, event.peer->address.port)); event.peer->data = new u16; *((u16*)event.peer->data) = peer_id; // Create peer addition event ConnectionEvent e; e.peerAdded(peer_id); putEvent(e); } break; case ENET_EVENT_TYPE_RECEIVE: { ConnectionEvent e; SharedBuffer<u8> resultdata(event.packet->data, event.packet->dataLength); e.dataReceived(*(u16*)event.peer->data, resultdata); putEvent(e); } /* Clean up the packet now that we're done using it. */ enet_packet_destroy (event.packet); break; case ENET_EVENT_TYPE_DISCONNECT: deletePeer(*((u16*)event.peer->data), false); /* Reset the peer's client information. */ delete (u16*)event.peer->data; break; case ENET_EVENT_TYPE_NONE: break; } } else if (ret < 0) { infostream<<"recieve enet_host_service failed = "<< ret << std::endl; if (m_peers.count(PEER_ID_SERVER)) deletePeer(PEER_ID_SERVER, false); } else { //0 if (m_peers.count(PEER_ID_SERVER) && m_last_recieved) { //ugly fix. todo: fix enet and remove unsigned int time = porting::getTimeMs(); const unsigned int t1 = 10000, t2 = 30000 * timeout_mul, t3 = 60000 * timeout_mul; unsigned int wait = time - m_last_recieved; if (wait > t3 && m_last_recieved_warn > t2) { errorstream<<"connection lost [60s], disconnecting."<<std::endl; #if defined(__has_feature) #if __has_feature(thread_sanitizer) || __has_feature(address_sanitizer) if (0) #endif #endif { deletePeer(PEER_ID_SERVER, false); } m_last_recieved_warn = 0; m_last_recieved = 0; } else if (wait > t2 && m_last_recieved_warn > t1 && m_last_recieved_warn < t2) { errorstream<<"connection lost [30s]!"<<std::endl; m_last_recieved_warn = time - m_last_recieved; } else if (wait > t1 && m_last_recieved_warn < t1) { errorstream<<"connection lost [10s]? ping."<<std::endl; enet_peer_ping(m_peers.get(PEER_ID_SERVER)); m_last_recieved_warn = wait; } } } }