Add kicking players and properly recieve disconnect events
This commit is contained in:
parent
22ca1cb751
commit
98e3d82921
@ -30,6 +30,7 @@
|
||||
Event::Event(ENetEvent* event, std::shared_ptr<STKPeer> peer)
|
||||
{
|
||||
m_arrival_time = (double)StkTime::getTimeSinceEpoch();
|
||||
m_pdi = PDI_TIMEOUT;
|
||||
|
||||
switch (event->type)
|
||||
{
|
||||
@ -38,6 +39,7 @@ Event::Event(ENetEvent* event, std::shared_ptr<STKPeer> peer)
|
||||
break;
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
m_type = EVENT_TYPE_DISCONNECTED;
|
||||
m_pdi = (PeerDisconnectInfo)event->data;
|
||||
break;
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
m_type = EVENT_TYPE_MESSAGE;
|
||||
|
@ -44,6 +44,7 @@ enum EVENT_TYPE
|
||||
EVENT_TYPE_DISCONNECTED,//!< A peer is disconnected
|
||||
EVENT_TYPE_MESSAGE //!< A message between server and client protocols
|
||||
};
|
||||
enum PeerDisconnectInfo : unsigned int;
|
||||
|
||||
/*!
|
||||
* \class Event
|
||||
@ -72,6 +73,9 @@ private:
|
||||
/** Arrivial time of the event, for timeouts. */
|
||||
double m_arrival_time;
|
||||
|
||||
/** For disconnection event, a bit more info is provided. */
|
||||
PeerDisconnectInfo m_pdi;
|
||||
|
||||
public:
|
||||
Event(ENetEvent* event, std::shared_ptr<STKPeer> peer);
|
||||
~Event();
|
||||
@ -103,7 +107,8 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
/** Returns the arrival time of this event. */
|
||||
double getArrivalTime() const { return m_arrival_time; }
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
PeerDisconnectInfo getPeerDisconnectInfo() const { return m_pdi; }
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
}; // class Event
|
||||
|
@ -37,7 +37,7 @@ void kickAllPlayers(STKHost* host)
|
||||
auto peers = host->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
peers[i]->disconnect();
|
||||
peers[i]->kick();
|
||||
}
|
||||
} // kickAllPlayers
|
||||
|
||||
|
@ -61,7 +61,6 @@ ClientLobby::ClientLobby() : LobbyProtocol(NULL)
|
||||
{
|
||||
|
||||
m_server_address.clear();
|
||||
m_server = NULL;
|
||||
setHandleDisconnections(true);
|
||||
} // ClientLobby
|
||||
|
||||
@ -207,8 +206,6 @@ void ClientLobby::voteLaps(uint8_t player_id, uint8_t laps,
|
||||
*/
|
||||
void ClientLobby::leave()
|
||||
{
|
||||
m_server->disconnect();
|
||||
m_server_address.clear();
|
||||
} // leave
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
@ -288,6 +285,22 @@ bool ClientLobby::notifyEventAsynchronous(Event* event)
|
||||
// the ProtocolManager, which might already have been deleted.
|
||||
// So only signal that STKHost should exit, which will be tested
|
||||
// from the main thread.
|
||||
STKHost::get()->disconnectAllPeers(false/*timeout_waiting*/);
|
||||
switch(event->getPeerDisconnectInfo())
|
||||
{
|
||||
case PDI_TIMEOUT:
|
||||
STKHost::get()->setErrorMessage(
|
||||
_("Server connection timed out."));
|
||||
break;
|
||||
case PDI_NORMAL:
|
||||
STKHost::get()->setErrorMessage(
|
||||
_("Server has been shut down."));
|
||||
break;
|
||||
case PDI_KICK:
|
||||
STKHost::get()->setErrorMessage(
|
||||
_("You were kicked from the server."));
|
||||
break;
|
||||
} // switch
|
||||
STKHost::get()->requestShutdown();
|
||||
return true;
|
||||
} // disconnection
|
||||
@ -507,8 +520,8 @@ void ClientLobby::connectionAccepted(Event* event)
|
||||
uint8_t player_id = data.getUInt8();
|
||||
uint8_t host_id = data.getUInt8();
|
||||
irr::core::stringw name;
|
||||
int bytes_read = data.decodeStringW(&name);
|
||||
|
||||
data.decodeStringW(&name);
|
||||
|
||||
NetworkPlayerProfile* profile2 =
|
||||
new NetworkPlayerProfile(name, player_id, host_id);
|
||||
m_game_setup->addPlayer(profile2);
|
||||
@ -521,7 +534,6 @@ void ClientLobby::connectionAccepted(Event* event)
|
||||
// on server and all clients.
|
||||
m_game_setup->addPlayer(profile);
|
||||
NetworkingLobby::getInstance()->addPlayer(profile);
|
||||
m_server = event->getPeer();
|
||||
m_state = CONNECTED;
|
||||
if (NetworkConfig::get()->isAutoConnect())
|
||||
{
|
||||
@ -841,7 +853,7 @@ void ClientLobby::playerTrackVote(Event* event)
|
||||
std::string track_name;
|
||||
uint8_t player_id = data.getUInt8();
|
||||
uint8_t number = data.getUInt8();
|
||||
int N = data.decodeString(&track_name);
|
||||
data.decodeString(&track_name);
|
||||
m_game_setup->getRaceConfig()->setPlayerTrackVote(player_id, track_name,
|
||||
number);
|
||||
} // playerTrackVote
|
||||
|
@ -6,8 +6,6 @@
|
||||
#include "utils/cpp2011.hpp"
|
||||
#include <set>
|
||||
|
||||
class STKPeer;
|
||||
|
||||
class ClientLobby : public LobbyProtocol
|
||||
{
|
||||
private:
|
||||
@ -31,8 +29,6 @@ private:
|
||||
|
||||
TransportAddress m_server_address;
|
||||
|
||||
STKPeer* m_server;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
|
@ -59,6 +59,7 @@
|
||||
|
||||
#include <algorithm>
|
||||
#include <functional>
|
||||
#include <limits>
|
||||
#include <random>
|
||||
#include <string>
|
||||
|
||||
@ -320,9 +321,7 @@ void STKHost::init()
|
||||
m_shutdown = false;
|
||||
m_network = NULL;
|
||||
m_game_setup = NULL;
|
||||
|
||||
m_exit_flag.clear();
|
||||
m_exit_flag.test_and_set();
|
||||
m_exit_timeout.store(std::numeric_limits<double>::max());
|
||||
|
||||
// Start with initialising ENet
|
||||
// ============================
|
||||
@ -358,8 +357,7 @@ STKHost::~STKHost()
|
||||
delete m_game_setup;
|
||||
m_game_setup = NULL;
|
||||
|
||||
m_peers.clear();
|
||||
|
||||
disconnectAllPeers(true/*timeout_waiting*/);
|
||||
Network::closeLog();
|
||||
stopListening();
|
||||
|
||||
@ -385,7 +383,6 @@ STKHost::~STKHost()
|
||||
void STKHost::shutdown()
|
||||
{
|
||||
ProtocolManager::lock()->abort();
|
||||
deleteAllPeers();
|
||||
destroy();
|
||||
} // shutdown
|
||||
|
||||
@ -624,14 +621,21 @@ GameSetup* STKHost::setupNewGame()
|
||||
} // setupNewGame
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Called when you leave a server.
|
||||
/** Disconnect all connected peers.
|
||||
*/
|
||||
void STKHost::deleteAllPeers()
|
||||
void STKHost::disconnectAllPeers(bool timeout_waiting)
|
||||
{
|
||||
m_peers.clear();
|
||||
} // deleteAllPeers
|
||||
std::lock_guard<std::mutex> lock(m_peers_mutex);
|
||||
if (!m_peers.empty())
|
||||
{
|
||||
// Wait for at most 2 seconds for disconnect event to be generated
|
||||
if (timeout_waiting)
|
||||
m_exit_timeout.store(StkTime::getRealTime() + 2.0);
|
||||
m_peers.clear();
|
||||
}
|
||||
} // disconnectAllPeers
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sets an error message for the gui.
|
||||
*/
|
||||
void STKHost::setErrorMessage(const irr::core::stringw &message)
|
||||
@ -644,7 +648,7 @@ void STKHost::setErrorMessage(const irr::core::stringw &message)
|
||||
m_error_message = message;
|
||||
} // setErrorMessage
|
||||
|
||||
// --------------------------------------------------------------------
|
||||
//-----------------------------------------------------------------------------
|
||||
/** \brief Try to establish a connection to a given transport address.
|
||||
* \param peer : The transport address which you want to connect to.
|
||||
* \return True if we're successfully connected. False elseway.
|
||||
@ -672,8 +676,7 @@ bool STKHost::connect(const TransportAddress& address)
|
||||
*/
|
||||
void STKHost::startListening()
|
||||
{
|
||||
m_exit_flag.clear();
|
||||
m_exit_flag.test_and_set();
|
||||
m_exit_timeout.store(std::numeric_limits<double>::max());
|
||||
m_listening_thread = std::thread(std::bind(&STKHost::mainLoop, this));
|
||||
} // startListening
|
||||
|
||||
@ -683,7 +686,8 @@ void STKHost::startListening()
|
||||
*/
|
||||
void STKHost::stopListening()
|
||||
{
|
||||
m_exit_flag.clear();
|
||||
if (m_exit_timeout.load() == std::numeric_limits<double>::max())
|
||||
m_exit_timeout.store(0.0);
|
||||
if (m_listening_thread.joinable())
|
||||
m_listening_thread.join();
|
||||
} // stopListening
|
||||
@ -736,7 +740,7 @@ void STKHost::mainLoop()
|
||||
}
|
||||
}
|
||||
|
||||
while (m_exit_flag.test_and_set())
|
||||
while (m_exit_timeout.load() > StkTime::getRealTime())
|
||||
{
|
||||
auto sl = LobbyProtocol::get<ServerLobby>();
|
||||
if (direct_socket && sl && sl->waitingForPlayers())
|
||||
@ -749,21 +753,14 @@ void STKHost::mainLoop()
|
||||
if (event.type == ENET_EVENT_TYPE_NONE)
|
||||
continue;
|
||||
|
||||
auto pm = ProtocolManager::lock();
|
||||
if (!pm || pm->isExiting())
|
||||
{
|
||||
// Don't create more event if no protocol manager or it will
|
||||
// be exiting
|
||||
enet_packet_destroy(event.packet);
|
||||
continue;
|
||||
}
|
||||
|
||||
Event* stk_event = NULL;
|
||||
if (event.type == ENET_EVENT_TYPE_CONNECT)
|
||||
{
|
||||
auto stk_peer =
|
||||
std::make_shared<STKPeer>(event.peer, m_network);
|
||||
std::unique_lock<std::mutex> lock(m_peers_mutex);
|
||||
m_peers[event.peer] = stk_peer;
|
||||
lock.unlock();
|
||||
stk_event = new Event(&event, stk_peer);
|
||||
TransportAddress addr(event.peer->address);
|
||||
Log::info("STKHost", "%s has just connected. There are "
|
||||
@ -772,21 +769,36 @@ void STKHost::mainLoop()
|
||||
else if (event.type == ENET_EVENT_TYPE_DISCONNECT)
|
||||
{
|
||||
Log::flushBuffers();
|
||||
|
||||
// If used a timeout waiting disconnect, exit now
|
||||
if (m_exit_timeout.load() !=
|
||||
std::numeric_limits<double>::max())
|
||||
{
|
||||
m_exit_timeout.store(0.0);
|
||||
break;
|
||||
}
|
||||
// Use the previous stk peer so protocol can see the network
|
||||
// profile and handle it for disconnection
|
||||
assert(m_peers.find(event.peer) != m_peers.end());
|
||||
stk_event = new Event(&event, m_peers.at(event.peer));
|
||||
m_peers.erase(event.peer);
|
||||
if (m_peers.find(event.peer) != m_peers.end())
|
||||
{
|
||||
stk_event = new Event(&event, m_peers.at(event.peer));
|
||||
std::lock_guard<std::mutex> lock(m_peers_mutex);
|
||||
m_peers.erase(event.peer);
|
||||
}
|
||||
TransportAddress addr(event.peer->address);
|
||||
Log::info("STKHost", "%s has just disconnected. There are "
|
||||
"now %u peers.", addr.toString().c_str(), getPeerCount());
|
||||
} // ENET_EVENT_TYPE_DISCONNECT
|
||||
|
||||
if (!stk_event)
|
||||
if (!stk_event && m_peers.find(event.peer) != m_peers.end())
|
||||
{
|
||||
assert(m_peers.find(event.peer) != m_peers.end());
|
||||
stk_event = new Event(&event, m_peers.at(event.peer));
|
||||
}
|
||||
else if (!stk_event)
|
||||
{
|
||||
enet_packet_destroy(event.packet);
|
||||
continue;
|
||||
}
|
||||
if (stk_event->getType() == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
Network::logPacket(stk_event->data(), true);
|
||||
@ -802,8 +814,11 @@ void STKHost::mainLoop()
|
||||
} // if message event
|
||||
|
||||
// notify for the event now.
|
||||
pm->propagateEvent(stk_event);
|
||||
|
||||
auto pm = ProtocolManager::lock();
|
||||
if (pm && !pm->isExiting())
|
||||
pm->propagateEvent(stk_event);
|
||||
else
|
||||
delete stk_event;
|
||||
} // while enet_host_service
|
||||
} // while m_exit_flag.test_and_set()
|
||||
delete direct_socket;
|
||||
|
@ -97,8 +97,8 @@ private:
|
||||
* triggers a shutdown of the STKHost (and the Protocolmanager). */
|
||||
std::atomic_bool m_shutdown;
|
||||
|
||||
/** Atomic flag used to stop this thread. */
|
||||
std::atomic_flag m_exit_flag = ATOMIC_FLAG_INIT;
|
||||
/** Use as a timeout to waiting a disconnect event when exiting. */
|
||||
std::atomic<double> m_exit_timeout;
|
||||
|
||||
/** An error message, which is set by a protocol to be displayed
|
||||
* in the GUI. */
|
||||
@ -162,10 +162,11 @@ public:
|
||||
// ------------------------------------------------------------------------
|
||||
void setPublicAddress();
|
||||
// ------------------------------------------------------------------------
|
||||
virtual GameSetup* setupNewGame();
|
||||
void deleteAllPeers();
|
||||
GameSetup* setupNewGame();
|
||||
// ------------------------------------------------------------------------
|
||||
void disconnectAllPeers(bool timeout_waiting = false);
|
||||
// ------------------------------------------------------------------------
|
||||
bool connect(const TransportAddress& peer);
|
||||
|
||||
//-------------------------------------------------------------------------
|
||||
/** Requests that the network infrastructure is to be shut down. This
|
||||
* function is called from a thread, but the actual shutdown needs to be
|
||||
|
@ -44,17 +44,26 @@ STKPeer::STKPeer(ENetPeer *enet_peer, Network* network)
|
||||
*/
|
||||
STKPeer::~STKPeer()
|
||||
{
|
||||
enet_peer_disconnect(m_enet_peer, 0);
|
||||
m_client_server_token = 0;
|
||||
TransportAddress a(m_enet_peer->address);
|
||||
if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED ||
|
||||
a != m_peer_address)
|
||||
return;
|
||||
auto lock = m_network->acquireEnetLock();
|
||||
enet_peer_disconnect(m_enet_peer, PDI_NORMAL);
|
||||
} // ~STKPeer
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Disconnect from the server.
|
||||
/** Kick this peer (used by server).
|
||||
*/
|
||||
void STKPeer::disconnect()
|
||||
void STKPeer::kick()
|
||||
{
|
||||
enet_peer_disconnect(m_enet_peer, 0);
|
||||
} // disconnect
|
||||
TransportAddress a(m_enet_peer->address);
|
||||
if (m_enet_peer->state != ENET_PEER_STATE_CONNECTED ||
|
||||
a != m_peer_address)
|
||||
return;
|
||||
auto lock = m_network->acquireEnetLock();
|
||||
enet_peer_disconnect(m_enet_peer, PDI_KICK);
|
||||
} // kick
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Sends a packet to this host.
|
||||
@ -86,7 +95,7 @@ void STKPeer::sendPacket(NetworkString *data, bool reliable)
|
||||
*/
|
||||
bool STKPeer::isConnected() const
|
||||
{
|
||||
Log::info("STKPeer", "The peer state is %i", m_enet_peer->state);
|
||||
Log::debug("STKPeer", "The peer state is %i", m_enet_peer->state);
|
||||
return (m_enet_peer->state == ENET_PEER_STATE_CONNECTED);
|
||||
} // isConnected
|
||||
|
||||
|
@ -36,6 +36,13 @@ class NetworkPlayerProfile;
|
||||
class NetworkString;
|
||||
class TransportAddress;
|
||||
|
||||
enum PeerDisconnectInfo : unsigned int
|
||||
{
|
||||
PDI_TIMEOUT = 0, //!< Timeout disconnected (default in enet).
|
||||
PDI_NORMAL = 1, //!< Normal disconnction with acknowledgement
|
||||
PDI_KICK = 2, //!< Kick disconnection
|
||||
}; // PeerDisconnectInfo
|
||||
|
||||
/*! \class STKPeer
|
||||
* \brief Represents a peer.
|
||||
* This class is used to interface the ENetPeer structure.
|
||||
@ -64,11 +71,12 @@ protected:
|
||||
|
||||
public:
|
||||
STKPeer(ENetPeer *enet_peer, Network* network);
|
||||
virtual ~STKPeer();
|
||||
|
||||
virtual void sendPacket(NetworkString *data,
|
||||
bool reliable = true);
|
||||
void disconnect();
|
||||
~STKPeer();
|
||||
// ------------------------------------------------------------------------
|
||||
void sendPacket(NetworkString *data, bool reliable = true);
|
||||
// ------------------------------------------------------------------------
|
||||
void kick();
|
||||
// ------------------------------------------------------------------------
|
||||
bool isConnected() const;
|
||||
const TransportAddress& getAddress() const { return m_peer_address; }
|
||||
bool isSamePeer(const STKPeer* peer) const;
|
||||
@ -79,7 +87,7 @@ public:
|
||||
void setClientServerToken(const uint32_t& token)
|
||||
{
|
||||
m_client_server_token = token;
|
||||
m_token_set = true;
|
||||
m_token_set = true;
|
||||
} // setClientServerToken
|
||||
// ------------------------------------------------------------------------
|
||||
void unsetClientServerToken() { m_token_set = false; }
|
||||
|
Loading…
Reference in New Issue
Block a user