Merge branch 'master' of github.com:supertuxkart/stk-code

This commit is contained in:
hiker 2015-10-27 15:00:13 +11:00
commit d2e6a10026
42 changed files with 850 additions and 765 deletions

View File

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<icon-button id="back" x="0" y="0" height="8%" icon="gui/back.png"/>
<div x="5%" y="2%" width="90%" height="96%" layout="vertical-row" >
<header I18N="Title for challenges screen" text="Challenges - Trophy Room" text_align="center" align="center" width="80%" />
<spacer height="5" width="100%"/>
<box width="100%" proportion="5" layout="vertical-row">
<ribbon_grid id="challenges" proportion="8" width="100%"
label_location="bottom" align="center" child_width="128" child_height="128" />
<spacer proportion="1" width="100%"/>
</box>
</div>
</stkgui>

View File

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<stkgui>
<div x="2%" y="10%" width="96%" height="80%" layout="vertical-row" >
<label id="title" width="100%" text_align="center" word_wrap="true"
I18N="In the 'add new player' dialog" text="Enter the new player's name" proportion="1" />
<spacer height="25" width="10" />
<textbox id="textfield" width="75%" I18N="In the 'add new player' dialog" align="center"/>
<spacer height="20" width="20" />
<buttonbar proportion="1" id="options" width="100%" height="100%">
<button id="ok" I18N="In the 'add new player' dialog" text="OK" align="center"/>
<button id="cancel" I18N="In the 'add new player' dialog" text="Cancel" align="center"/>
</buttonbar>
<spacer height="15" width="20" />
</div>
</stkgui>

View File

@ -65,6 +65,7 @@ SavedGrandPrix::SavedGPKart::SavedGPKart(GroupUserConfigParam * group,
// ============================================================================ // ============================================================================
SavedGrandPrix::SavedGrandPrix(unsigned int player_id, SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
const std::string &gp_id, const std::string &gp_id,
RaceManager::MinorRaceModeType race_type,
RaceManager::Difficulty difficulty, RaceManager::Difficulty difficulty,
int player_karts, int player_karts,
int last_track, int last_track,
@ -74,6 +75,7 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
"Represents the saved state of a GP"), "Represents the saved state of a GP"),
m_player_id(player_id, "player_id", &m_savedgp_group), m_player_id(player_id, "player_id", &m_savedgp_group),
m_gp_id(gp_id.c_str(), "gp_id", &m_savedgp_group), m_gp_id(gp_id.c_str(), "gp_id", &m_savedgp_group),
m_race_type((int)race_type,"race_type", &m_savedgp_group),
m_difficulty((int)difficulty,"difficulty", &m_savedgp_group), m_difficulty((int)difficulty,"difficulty", &m_savedgp_group),
m_player_karts(player_karts,"player_karts", &m_savedgp_group), m_player_karts(player_karts,"player_karts", &m_savedgp_group),
m_next_track(last_track,"last_track", &m_savedgp_group), m_next_track(last_track,"last_track", &m_savedgp_group),
@ -98,6 +100,7 @@ SavedGrandPrix::SavedGrandPrix(const XMLNode* node)
"Represents the saved state of a GP"), "Represents the saved state of a GP"),
m_player_id (0, "player_id", &m_savedgp_group), m_player_id (0, "player_id", &m_savedgp_group),
m_gp_id ("-", "gp_id", &m_savedgp_group), m_gp_id ("-", "gp_id", &m_savedgp_group),
m_race_type (0,"race_type", &m_savedgp_group),
m_difficulty (0,"difficulty", &m_savedgp_group), m_difficulty (0,"difficulty", &m_savedgp_group),
m_player_karts(0,"player_karts", &m_savedgp_group), m_player_karts(0,"player_karts", &m_savedgp_group),
m_next_track (0,"last_track", &m_savedgp_group), m_next_track (0,"last_track", &m_savedgp_group),
@ -106,6 +109,7 @@ SavedGrandPrix::SavedGrandPrix(const XMLNode* node)
//m_player_group.findYourDataInAChildOf(node); //m_player_group.findYourDataInAChildOf(node);
m_player_id. findYourDataInAnAttributeOf(node); m_player_id. findYourDataInAnAttributeOf(node);
m_gp_id. findYourDataInAnAttributeOf(node); m_gp_id. findYourDataInAnAttributeOf(node);
m_race_type. findYourDataInAnAttributeOf(node);
m_difficulty. findYourDataInAnAttributeOf(node); m_difficulty. findYourDataInAnAttributeOf(node);
m_player_karts.findYourDataInAnAttributeOf(node); m_player_karts.findYourDataInAnAttributeOf(node);
m_next_track. findYourDataInAnAttributeOf(node); m_next_track. findYourDataInAnAttributeOf(node);

View File

@ -67,6 +67,9 @@ protected:
/** Identifier of this GP. */ /** Identifier of this GP. */
StringUserConfigParam m_gp_id; StringUserConfigParam m_gp_id;
/** Race type at which this GP was run. */
IntUserConfigParam m_race_type;
/** Difficulty at which this GP was run. */ /** Difficulty at which this GP was run. */
IntUserConfigParam m_difficulty; IntUserConfigParam m_difficulty;
@ -88,6 +91,7 @@ public:
*/ */
SavedGrandPrix(unsigned int player_id, SavedGrandPrix(unsigned int player_id,
const std::string &gp_id, const std::string &gp_id,
RaceManager::MinorRaceModeType race_type,
RaceManager::Difficulty difficulty, RaceManager::Difficulty difficulty,
int player_karts, int player_karts,
int last_track, int last_track,
@ -110,6 +114,10 @@ public:
/** Returns the grand prix id. */ /** Returns the grand prix id. */
std::string getGPID() const { return m_gp_id; } std::string getGPID() const { return m_gp_id; }
// ------------------------------------------------------------------------
/** Returns the race type of this GP. */
int getRaceType() const { return m_race_type; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns the difficulty of this GP. */ /** Returns the difficulty of this GP. */
int getDifficulty() const { return m_difficulty; } int getDifficulty() const { return m_difficulty; }
@ -148,12 +156,14 @@ public:
* NULL if no matching GP was found. */ * NULL if no matching GP was found. */
static SavedGrandPrix* getSavedGP(unsigned int player, static SavedGrandPrix* getSavedGP(unsigned int player,
const std::string &gpid, const std::string &gpid,
RaceManager::MinorRaceModeType race_type,
const unsigned int number_of_players) const unsigned int number_of_players)
{ {
for (unsigned int n=0; n<UserConfigParams::m_saved_grand_prix_list.size(); n++) for (unsigned int n=0; n<UserConfigParams::m_saved_grand_prix_list.size(); n++)
{ {
SavedGrandPrix* gp = &UserConfigParams::m_saved_grand_prix_list[n]; SavedGrandPrix* gp = &UserConfigParams::m_saved_grand_prix_list[n];
if (gp->getGPID() == gpid && if (gp->getGPID() == gpid &&
gp->getRaceType() == race_type &&
gp->getPlayerID() == player && gp->getPlayerID() == player &&
gp->getPlayerKarts() == (int)number_of_players) gp->getPlayerKarts() == (int)number_of_players)
return gp; return gp;

View File

@ -27,6 +27,7 @@
#include "graphics/shaders.hpp" #include "graphics/shaders.hpp"
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
#include "io/xml_node.hpp" #include "io/xml_node.hpp"
#include "modes/profile_world.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "tracks/track.hpp" #include "tracks/track.hpp"
#include "utils/string_utils.hpp" #include "utils/string_utils.hpp"
@ -127,11 +128,16 @@ Material* MaterialManager::getDefaultMaterial(video::E_MATERIAL_TYPE shader_type
// TODO: workaround, should not hardcode these material types here? // TODO: workaround, should not hardcode these material types here?
// Try to find a cleaner way // Try to find a cleaner way
if (shader_type == Shaders::getShader(ShaderType::ES_OBJECT_UNLIT)) // If graphics are disabled, shaders should not be accessed (getShader
// asserts that shaders are initialised).
if(!ProfileWorld::isNoGraphics() &&
shader_type == Shaders::getShader(ShaderType::ES_OBJECT_UNLIT))
default_material->setShaderType(Material::SHADERTYPE_SOLID_UNLIT); default_material->setShaderType(Material::SHADERTYPE_SOLID_UNLIT);
else if (shader_type == Shaders::getShader(ShaderType::ES_OBJECTPASS_REF)) else if (!ProfileWorld::isNoGraphics() &&
shader_type == Shaders::getShader(ShaderType::ES_OBJECTPASS_REF))
default_material->setShaderType(Material::SHADERTYPE_ALPHA_TEST); default_material->setShaderType(Material::SHADERTYPE_ALPHA_TEST);
//else if (shader_type == Shaders::getShader(ShaderType::ES_OBJECTPASS)) //else if (!ProfileWorld::isNoGraphics() &&
// shader_type == Shaders::getShader(ShaderType::ES_OBJECTPASS))
// default_material->setShaderType(Material::SHADERTYPE_ALPHA_BLEND); // default_material->setShaderType(Material::SHADERTYPE_ALPHA_BLEND);
else else
default_material->setShaderType(Material::SHADERTYPE_SOLID); default_material->setShaderType(Material::SHADERTYPE_SOLID);

View File

@ -690,7 +690,8 @@ EventPropagation RibbonWidget::transmitEvent(Widget* w,
// bring focus back to enclosing ribbon widget // bring focus back to enclosing ribbon widget
this->setFocusForPlayer( playerID ); this->setFocusForPlayer( playerID );
if (m_selection[playerID] != -1) if (m_selection[playerID] > -1 &&
m_selection[playerID] < (int)(m_active_children.size()))
{ {
if (m_active_children[m_selection[playerID]].m_deactivated) if (m_active_children[m_selection[playerID]].m_deactivated)
{ {

View File

@ -64,6 +64,7 @@ namespace irr {
std::vector<std::string> FileManager::m_root_dirs; std::vector<std::string> FileManager::m_root_dirs;
std::string FileManager::m_stdout_filename = "stdout.log";
#ifdef __APPLE__ #ifdef __APPLE__
// dynamic data path detection onmac // dynamic data path detection onmac
@ -1044,6 +1045,15 @@ std::string FileManager::checkAndCreateLinuxDir(const char *env_name,
} // checkAndCreateLinuxDir } // checkAndCreateLinuxDir
#endif #endif
//-----------------------------------------------------------------------------
/** Sets the name for the stdout log file.
* \param filename Filename to use (relative to the user config dir).
*/
void FileManager::setStdoutName(const std::string& filename)
{
m_stdout_filename = filename;
} // setStdoutName
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Redirects output to go into files in the user's config directory /** Redirects output to go into files in the user's config directory
* instead of to the console. It keeps backup copies of previous stdout files * instead of to the console. It keeps backup copies of previous stdout files
@ -1053,7 +1063,7 @@ void FileManager::redirectOutput()
{ {
// Do a simple log rotate: stdout.log.2 becomes stdout.log.3 etc // Do a simple log rotate: stdout.log.2 becomes stdout.log.3 etc
const int NUM_BACKUPS=3; const int NUM_BACKUPS=3;
std::string logoutfile = getUserConfigFile("stdout.log"); std::string logoutfile = getUserConfigFile(m_stdout_filename);
for(int i=NUM_BACKUPS; i>1; i--) for(int i=NUM_BACKUPS; i>1; i--)
{ {
std::ostringstream out_old; std::ostringstream out_old;

View File

@ -69,6 +69,9 @@ private:
/** The list of all root directories. */ /** The list of all root directories. */
static std::vector<std::string> m_root_dirs; static std::vector<std::string> m_root_dirs;
/** Name of stdout file. */
static std::string m_stdout_filename;
/** Directory to store screenshots in. */ /** Directory to store screenshots in. */
std::string m_screenshot_dir; std::string m_screenshot_dir;
@ -109,6 +112,7 @@ public:
~FileManager(); ~FileManager();
void init(); void init();
static void addRootDirs(const std::string &roots); static void addRootDirs(const std::string &roots);
static void setStdoutName(const std::string &name);
io::IXMLReader *createXMLReader(const std::string &filename); io::IXMLReader *createXMLReader(const std::string &filename);
XMLNode *createXMLTree(const std::string &filename); XMLNode *createXMLTree(const std::string &filename);
XMLNode *createXMLTreeFromString(const std::string & content); XMLNode *createXMLTreeFromString(const std::string & content);

View File

@ -1252,6 +1252,8 @@ void Kart::update(float dt)
{ {
m_body->getBroadphaseHandle()->m_collisionFilterGroup = old_group; m_body->getBroadphaseHandle()->m_collisionFilterGroup = old_group;
} }
PROFILER_PUSH_CPU_MARKER("Kart::Update (material)", 0x60, 0x34, 0x7F);
handleMaterialGFX(); handleMaterialGFX();
const Material* material=m_terrain_info->getMaterial(); const Material* material=m_terrain_info->getMaterial();
if (!material) // kart falling off the track if (!material) // kart falling off the track
@ -1309,6 +1311,7 @@ void Kart::update(float dt)
#endif #endif
} }
} // if there is material } // if there is material
PROFILER_POP_CPU_MARKER();
// Check if any item was hit. // Check if any item was hit.
// check it if we're not in a network world, or if we're on the server (when network mode is on) // check it if we're not in a network world, or if we're on the server (when network mode is on)

View File

@ -1265,9 +1265,9 @@ int main(int argc, char *argv[] )
handleCmdLineOutputModifier(); handleCmdLineOutputModifier();
if(CommandLine::has("--root", &s)) if(CommandLine::has("--root", &s))
{
FileManager::addRootDirs(s); FileManager::addRootDirs(s);
} if (CommandLine::has("--stdout", &s))
FileManager::setStdoutName(s);
// Init the minimum managers so that user config exists, then // Init the minimum managers so that user config exists, then
// handle all command line options that do not need (or must // handle all command line options that do not need (or must

View File

@ -954,7 +954,7 @@ void World::update(float dt)
m_physics->update(dt); m_physics->update(dt);
} }
PROFILER_PUSH_CPU_MARKER("World::update (AI)", 0x40, 0x7F, 0x00); PROFILER_PUSH_CPU_MARKER("World::update (Kart::upate)", 0x40, 0x7F, 0x00);
const int kart_amount = (int)m_karts.size(); const int kart_amount = (int)m_karts.size();
for (int i = 0 ; i < kart_amount; ++i) for (int i = 0 ; i < kart_amount; ++i)
{ {

View File

@ -62,7 +62,7 @@ Event::Event(ENetEvent* event)
m_peer = NULL; m_peer = NULL;
for (unsigned int i = 0; i < peers.size(); i++) for (unsigned int i = 0; i < peers.size(); i++)
{ {
if (peers[i]->m_peer == event->peer) if (peers[i]->m_enet_peer == event->peer)
{ {
m_peer = peers[i]; m_peer = peers[i];
Log::verbose("Event", "The peer you sought has been found on %p", Log::verbose("Event", "The peer you sought has been found on %p",
@ -73,7 +73,7 @@ Event::Event(ENetEvent* event)
if (m_peer == NULL) // peer does not exist, create him if (m_peer == NULL) // peer does not exist, create him
{ {
STKPeer* new_peer = new STKPeer(); STKPeer* new_peer = new STKPeer();
new_peer->m_peer = event->peer; new_peer->m_enet_peer = event->peer;
m_peer = new_peer; m_peer = new_peer;
Log::debug("Event", Log::debug("Event",
"Creating a new peer, address are STKPeer:%p, Peer:%p", "Creating a new peer, address are STKPeer:%p, Peer:%p",
@ -81,18 +81,6 @@ Event::Event(ENetEvent* event)
} }
} // Event(ENetEvent) } // Event(ENetEvent)
// ----------------------------------------------------------------------------
/** \brief Constructor
* \param event : The event to copy.
*/
Event::Event(const Event& event)
{
m_type = event.m_type;
m_packet = NULL;
m_data = event.m_data;
m_peer = event.m_peer;
} // Event(Event)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Destructor that frees the memory of the package. /** \brief Destructor that frees the memory of the package.
*/ */

View File

@ -24,10 +24,14 @@
#ifndef EVENT_HPP #ifndef EVENT_HPP
#define EVENT_HPP #define EVENT_HPP
#include "network/stk_peer.hpp"
#include "network/network_string.hpp" #include "network/network_string.hpp"
#include "utils/leak_check.hpp"
#include "utils/types.hpp" #include "utils/types.hpp"
#include "enet/enet.h"
class STKPeer;
/*! /*!
* \enum EVENT_TYPE * \enum EVENT_TYPE
* \brief Represents a network event type. * \brief Represents a network event type.
@ -52,6 +56,7 @@ enum EVENT_TYPE
class Event class Event
{ {
private: private:
LEAK_CHECK()
/** Copy of the data passed by the event. */ /** Copy of the data passed by the event. */
NetworkString m_data; NetworkString m_data;
@ -66,7 +71,6 @@ private:
public: public:
Event(ENetEvent* event); Event(ENetEvent* event);
Event(const Event& event);
~Event(); ~Event();
void removeFront(int size); void removeFront(int size);
@ -78,11 +82,16 @@ public:
/** Returns the peer of this event. */ /** Returns the peer of this event. */
STKPeer* getPeer() const { return m_peer; } STKPeer* getPeer() const { return m_peer; }
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** \brief Get a copy of the data. /** \brief Get a const reference to the received data.
* \return A copy of the message data. This is empty for events like * This is empty for events like connection or disconnections.
*/
const NetworkString& data() const { return m_data; }
// ------------------------------------------------------------------------
/** \brief Get a non-const reference to the received data.
* A copy of the message data. This is empty for events like
* connection or disconnections. */ * connection or disconnections. */
NetworkString data() const { return m_data; } NetworkString& data() { return m_data; }
// ------------------------------------------------------------------------
}; // class Event }; // class Event

View File

@ -18,14 +18,9 @@
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "network/protocols/hide_public_address.hpp" #include "network/event.hpp"
#include "network/protocols/show_public_address.hpp" #include "network/game_setup.hpp"
#include "network/protocols/get_public_address.hpp"
#include "network/protocol_manager.hpp" #include "network/protocol_manager.hpp"
#include "network/client_network_manager.hpp"
#include "network/server_network_manager.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
#include <pthread.h> #include <pthread.h>
@ -58,6 +53,8 @@ NetworkManager::~NetworkManager()
} // ~Networkmanager } // ~Networkmanager
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
/** \brief Function to start the Network Manager (start threads).
*/
void NetworkManager::run() void NetworkManager::run()
{ {
// create the protocol manager // create the protocol manager
@ -65,6 +62,9 @@ void NetworkManager::run()
} // run } // run
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** \brief Function to reset the Network Manager.
* This function resets the peers and the listening host.
*/
void NetworkManager::reset() void NetworkManager::reset()
{ {
if (m_localhost) if (m_localhost)
@ -78,6 +78,10 @@ void NetworkManager::reset()
} // reset } // reset
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** \brief Function that aborts the NetworkManager.
* This function will stop the listening, delete the host and stop
* threads that are related to networking.
*/
void NetworkManager::abort() void NetworkManager::abort()
{ {
m_localhost->stopListening(); m_localhost->stopListening();
@ -88,17 +92,25 @@ void NetworkManager::abort()
} // abort } // abort
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** \brief Try to establish a connection to a given transport address.
bool NetworkManager::connect(const TransportAddress& peer) * \param peer : The transport address which you want to connect to.
* \return True if we're successfully connected. False elseway.
*/
bool NetworkManager::connect(const TransportAddress& address)
{ {
if (peerExists(peer)) if (peerExists(address))
return isConnectedTo(peer); return isConnectedTo(address);
return STKPeer::connectToHost(m_localhost, peer, 2, 0); return STKPeer::connectToHost(m_localhost, address, 2, 0);
} // connect } // connect
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** \brief Changes the socket working mode.
* Sockets can be in two modes : The ENet mode and a mode we will call
* the 'Raw' mode. In the ENet mode, the socket will be read as
* \param peer : The transport address which you want to connect to.
* \return True if we're successfully connected. False elseway.
*/
void NetworkManager::setManualSocketsMode(bool manual) void NetworkManager::setManualSocketsMode(bool manual)
{ {
if (manual) if (manual)
@ -108,7 +120,13 @@ void NetworkManager::setManualSocketsMode(bool manual)
} // setManualSocketsMode } // setManualSocketsMode
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
void NetworkManager::notifyEvent(Event* event) /** Is called from STKHost when an event (i.e. a package) is received. If the
* event indicates a new connection, the peer is added to the list of peers.
* It logs the package, and propagates the event to the ProtocollManager,
* which in turn will notify individual protocols.
* \param event Pointer to the event to propagate.
*/
void NetworkManager::propagateEvent(Event* event)
{ {
Log::verbose("NetworkManager", "EVENT received of type %d", Log::verbose("NetworkManager", "EVENT received of type %d",
(int)(event->getType())); (int)(event->getType()));
@ -135,8 +153,8 @@ void NetworkManager::notifyEvent(Event* event)
} }
// notify for the event now. // notify for the event now.
ProtocolManager::getInstance()->notifyEvent(event); ProtocolManager::getInstance()->propagateEvent(event);
} // notifyEvent } // propagateEvent
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@ -163,18 +181,20 @@ void NetworkManager::sendPacketExcept(STKPeer* peer, const NetworkString& data,
} // sendPacketExcept } // sendPacketExcept
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** A previous GameSetup is deletea and a new one is created.
* \return Newly create GameSetup object.
*/
GameSetup* NetworkManager::setupNewGame() GameSetup* NetworkManager::setupNewGame()
{ {
if (m_game_setup) if (m_game_setup)
delete m_game_setup; delete m_game_setup;
m_game_setup = NULL;
m_game_setup = new GameSetup(); m_game_setup = new GameSetup();
return m_game_setup; return m_game_setup;
} // setupNewGame } // setupNewGame
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Called when you leave a server.
*/
void NetworkManager::disconnected() void NetworkManager::disconnected()
{ {
// delete the game setup // delete the game setup
@ -248,15 +268,3 @@ void NetworkManager::removePeer(STKPeer* peer)
} // removePeer } // removePeer
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool NetworkManager::peerExists(const TransportAddress& peer)
{
return m_localhost->peerExists(peer);
} // peerExists
//-----------------------------------------------------------------------------
bool NetworkManager::isConnectedTo(const TransportAddress& peer)
{
return m_localhost->isConnectedTo(peer);
} // isConnectedTo

View File

@ -28,13 +28,14 @@
#include "network/protocol_manager.hpp" #include "network/protocol_manager.hpp"
#include "network/types.hpp" #include "network/types.hpp"
#include "network/event.hpp"
#include "network/game_setup.hpp"
#include "utils/singleton.hpp" #include "utils/singleton.hpp"
#include "utils/synchronised.hpp" #include "utils/synchronised.hpp"
#include <vector> #include <vector>
class Event;
class GameSetup;
/** \class NetworkManager /** \class NetworkManager
* \brief Gives the general functions to use network communication. * \brief Gives the general functions to use network communication.
* This class is in charge of storing the peers connected to this host. * This class is in charge of storing the peers connected to this host.
@ -46,36 +47,35 @@
*/ */
class NetworkManager : public AbstractSingleton<NetworkManager> class NetworkManager : public AbstractSingleton<NetworkManager>
{ {
protected:
NetworkManager();
virtual ~NetworkManager();
/** Pointer to the one stk host instance, which is used to do all
* network communication. */
STKHost* m_localhost;
/** The list of peers connected to this instance. */
std::vector<STKPeer*> m_peers;
private:
GameSetup* m_game_setup;
/** This computer's public IP address. With lock since it can
* be updated from a separate thread. */
Synchronised<TransportAddress> m_public_address;
PlayerLogin m_player_login;
friend class AbstractSingleton<NetworkManager>; friend class AbstractSingleton<NetworkManager>;
public: public:
/** \brief Function to start the Network Manager (start threads) */
virtual void run(); virtual void run();
/** \brief Function to reset the Network Manager.
* This function resets the peers and the listening host.
*/
virtual void reset(); virtual void reset();
/** \brief Function that aborts the NetworkManager.
* This function will stop the listening, delete the host and stop
* threads that are related to networking.
*/
virtual void abort(); virtual void abort();
// network management functions
/** \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.
*/
virtual bool connect(const TransportAddress& peer); virtual bool connect(const TransportAddress& peer);
/** \brief Changes the socket working mode.
* Sockets can be in two modes : The ENet mode and a mode we will call
* the 'Raw' mode. In the ENet mode, the socket will be read as
* \param peer : The transport address which you want to connect to.
* \return True if we're successfully connected. False elseway.
*/
virtual void setManualSocketsMode(bool manual); virtual void setManualSocketsMode(bool manual);
virtual void propagateEvent(Event* event);
// message/packets related functions
virtual void notifyEvent(Event* event);
virtual void sendPacket(const NetworkString& data, virtual void sendPacket(const NetworkString& data,
bool reliable = true) = 0; bool reliable = true) = 0;
virtual void sendPacket(STKPeer* peer, virtual void sendPacket(STKPeer* peer,
@ -86,8 +86,9 @@ class NetworkManager : public AbstractSingleton<NetworkManager>
bool reliable = true); bool reliable = true);
// Game related functions // Game related functions
virtual GameSetup* setupNewGame(); //!< Creates a new game setup and returns it virtual GameSetup* setupNewGame();
virtual void disconnected(); //!< Called when you leave a server virtual void disconnected();
virtual bool isServer() = 0;
// raw data management // raw data management
void setLogin(std::string username, std::string password); void setLogin(std::string username, std::string password);
@ -95,15 +96,22 @@ class NetworkManager : public AbstractSingleton<NetworkManager>
void removePeer(STKPeer* peer); void removePeer(STKPeer* peer);
// getters // getters
virtual bool peerExists(const TransportAddress& peer); // ------------------------------------------------------------------------
virtual bool isConnectedTo(const TransportAddress& peer); /** Returns if a peer from the specified IP:port address
* already exists. */
virtual bool peerExists(const TransportAddress& peer)
{
return m_localhost->peerExists(peer);
} // peerExists
// --------------------------------------------------------------------
virtual bool isConnectedTo(const TransportAddress& peer)
{
return m_localhost->isConnectedTo(peer);
} // isConnectedTo
virtual bool isServer() = 0;
// -------------------------------------------------------------------- // --------------------------------------------------------------------
inline bool isClient() { return !isServer(); } inline bool isClient() { return !isServer(); }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
bool isPlayingOnline() { return m_playing_online; }
// --------------------------------------------------------------------
STKHost* getHost() { return m_localhost; } STKHost* getHost() { return m_localhost; }
// -------------------------------------------------------------------- // --------------------------------------------------------------------
std::vector<STKPeer*> getPeers() { return m_peers; } std::vector<STKPeer*> getPeers() { return m_peers; }
@ -123,21 +131,9 @@ class NetworkManager : public AbstractSingleton<NetworkManager>
} // getPublicAddress } // getPublicAddress
// -------------------------------------------------------------------- // --------------------------------------------------------------------
/** Returns the current game setup. */
GameSetup* getGameSetup() { return m_game_setup; } GameSetup* getGameSetup() { return m_game_setup; }
protected: }; // class NetworkManager
NetworkManager();
virtual ~NetworkManager();
// protected members
std::vector<STKPeer*> m_peers;
STKHost* m_localhost;
bool m_playing_online;
GameSetup* m_game_setup;
/** This computer's public IP address. With lock since it can
* be updated from a separate thread. */
Synchronised<TransportAddress> m_public_address;
PlayerLogin m_player_login;
};
#endif // NETWORKMANAGER_HPP #endif // NETWORKMANAGER_HPP

View File

@ -39,10 +39,11 @@ typedef unsigned char uchar;
class NetworkString class NetworkString
{ {
private: private:
union { union FloatAsInt
{
float f; float f;
uint8_t i[4]; uint8_t i[4];
} f_as_i; // float as integer }; // float as integer
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
union { union {
@ -165,6 +166,7 @@ public:
NetworkString& addFloat(const float& value) //!< BEWARE OF PRECISION NetworkString& addFloat(const float& value) //!< BEWARE OF PRECISION
{ {
assert(sizeof(float) == 4); assert(sizeof(float) == 4);
FloatAsInt f_as_i;
f_as_i.f = value; f_as_i.f = value;
m_string.push_back(f_as_i.i[0]); m_string.push_back(f_as_i.i[0]);
m_string.push_back(f_as_i.i[1]); m_string.push_back(f_as_i.i[1]);
@ -339,8 +341,9 @@ public:
// ------------------------------------------------------------------------ // ------------------------------------------------------------------------
/** Returns a 4-byte floating point value. */ /** Returns a 4-byte floating point value. */
float getFloat(int pos = 0) //!< BEWARE OF PRECISION float getFloat(int pos = 0) const //!< BEWARE OF PRECISION
{ {
FloatAsInt f_as_i;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
f_as_i.i[i] = m_string[pos + i]; f_as_i.i[i] = m_string[pos + i];
return f_as_i.f; return f_as_i.f;
@ -426,6 +429,7 @@ public:
/** Get and remove a 4 byte floating point value. */ /** Get and remove a 4 byte floating point value. */
float getAndRemoveFloat(int pos = 0) //!< BEWARE OF PRECISION float getAndRemoveFloat(int pos = 0) //!< BEWARE OF PRECISION
{ {
FloatAsInt f_as_i;
for (int i = 0; i < 4; i++) for (int i = 0; i < 4; i++)
f_as_i.i[i] = m_string[pos + i]; f_as_i.i[i] = m_string[pos + i];
return f_as_i.f; return f_as_i.f;

View File

@ -18,10 +18,11 @@
#include "network/protocol.hpp" #include "network/protocol.hpp"
#include "network/protocol_manager.hpp" #include "network/event.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "network/protocol_manager.hpp"
Protocol::Protocol(CallbackObject* callback_object, PROTOCOL_TYPE type) Protocol::Protocol(CallbackObject* callback_object, ProtocolType type)
{ {
m_callback_object = callback_object; m_callback_object = callback_object;
m_type = type; m_type = type;
@ -49,14 +50,14 @@ void Protocol::setListener(ProtocolManager* listener)
m_listener = listener; m_listener = listener;
} }
PROTOCOL_TYPE Protocol::getProtocolType() ProtocolType Protocol::getProtocolType()
{ {
return m_type; return m_type;
} }
bool Protocol::checkDataSizeAndToken(Event* event, int minimum_size) bool Protocol::checkDataSizeAndToken(Event* event, int minimum_size)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() < minimum_size || data[0] != 4) if (data.size() < minimum_size || data[0] != 4)
{ {
Log::warn("Protocol", "Receiving a badly " Log::warn("Protocol", "Receiving a badly "
@ -77,7 +78,7 @@ bool Protocol::checkDataSizeAndToken(Event* event, int minimum_size)
bool Protocol::isByteCorrect(Event* event, int byte_nb, int value) bool Protocol::isByteCorrect(Event* event, int byte_nb, int value)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data[byte_nb] != value) if (data[byte_nb] != value)
{ {
Log::info("Protocol", "Bad byte at pos %d. %d " Log::info("Protocol", "Bad byte at pos %d. %d "

View File

@ -23,17 +23,18 @@
#ifndef PROTOCOL_HPP #ifndef PROTOCOL_HPP
#define PROTOCOL_HPP #define PROTOCOL_HPP
#include "network/event.hpp" #include "network/network_string.hpp"
#include "network/types.hpp" #include "network/types.hpp"
#include "utils/types.hpp" #include "utils/types.hpp"
class Event;
class ProtocolManager; class ProtocolManager;
/** \enum PROTOCOL_TYPE /** \enum ProtocolType
* \brief The types that protocols can have. This is used to select which protocol receives which event. * \brief The types that protocols can have. This is used to select which protocol receives which event.
* \ingroup network * \ingroup network
*/ */
enum PROTOCOL_TYPE enum ProtocolType
{ {
PROTOCOL_NONE = 0, //!< No protocol type assigned. PROTOCOL_NONE = 0, //!< No protocol type assigned.
PROTOCOL_CONNECTION = 1, //!< Protocol that deals with client-server connection. PROTOCOL_CONNECTION = 1, //!< Protocol that deals with client-server connection.
@ -64,7 +65,7 @@ class Protocol
* \param callback_object The callback object that will be used by the protocol. Protocols that do not use callback objects must set it to NULL. * \param callback_object The callback object that will be used by the protocol. Protocols that do not use callback objects must set it to NULL.
* \param type The type of the protocol. * \param type The type of the protocol.
*/ */
Protocol(CallbackObject* callback_object, PROTOCOL_TYPE type); Protocol(CallbackObject* callback_object, ProtocolType type);
/*! \brief Destructor /*! \brief Destructor
*/ */
virtual ~Protocol(); virtual ~Protocol();
@ -111,7 +112,7 @@ class Protocol
/*! \brief Method to get a protocol's type. /*! \brief Method to get a protocol's type.
* \return The protocol type. * \return The protocol type.
*/ */
PROTOCOL_TYPE getProtocolType(); ProtocolType getProtocolType();
/// functions to check incoming data easily /// functions to check incoming data easily
bool checkDataSizeAndToken(Event* event, int minimum_size); bool checkDataSizeAndToken(Event* event, int minimum_size);
@ -121,7 +122,7 @@ class Protocol
protected: protected:
ProtocolManager* m_listener; //!< The protocol listener ProtocolManager* m_listener; //!< The protocol listener
PROTOCOL_TYPE m_type; //!< The type of the protocol ProtocolType m_type; //!< The type of the protocol
CallbackObject* m_callback_object; //!< The callback object, if needed CallbackObject* m_callback_object; //!< The callback object, if needed
}; };

View File

@ -18,6 +18,7 @@
#include "network/protocol_manager.hpp" #include "network/protocol_manager.hpp"
#include "network/event.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "network/protocol.hpp" #include "network/protocol.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
@ -66,6 +67,8 @@ ProtocolManager::~ProtocolManager()
} // ~ProtocolManager } // ~ProtocolManager
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Stops the protocol manager.
*/
void ProtocolManager::abort() void ProtocolManager::abort()
{ {
pthread_mutex_unlock(&m_exit_mutex); // will stop the update function pthread_mutex_unlock(&m_exit_mutex); // will stop the update function
@ -76,9 +79,9 @@ void ProtocolManager::abort()
pthread_mutex_lock(&m_requests_mutex); pthread_mutex_lock(&m_requests_mutex);
pthread_mutex_lock(&m_id_mutex); pthread_mutex_lock(&m_id_mutex);
for (unsigned int i = 0; i < m_protocols.getData().size() ; i++) for (unsigned int i = 0; i < m_protocols.getData().size() ; i++)
delete m_protocols.getData()[i].protocol; delete m_protocols.getData()[i].m_protocol;
for (unsigned int i = 0; i < m_events_to_process.getData().size() ; i++) for (unsigned int i = 0; i < m_events_to_process.getData().size() ; i++)
delete m_events_to_process.getData()[i].event; delete m_events_to_process.getData()[i].m_event;
m_protocols.getData().clear(); m_protocols.getData().clear();
m_requests.clear(); m_requests.clear();
m_events_to_process.getData().clear(); m_events_to_process.getData().clear();
@ -95,63 +98,76 @@ void ProtocolManager::abort()
} // abort } // abort
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void ProtocolManager::notifyEvent(Event* event) /** \brief Function that processes incoming events.
* This function is called by the network manager each time there is an
* incoming packet.
*/
void ProtocolManager::propagateEvent(Event* event)
{ {
m_events_to_process.lock(); m_events_to_process.lock();
Event* event2 = new Event(*event);
// register protocols that will receive this event // register protocols that will receive this event
std::vector<unsigned int> protocols_ids; ProtocolType searched_protocol = PROTOCOL_NONE;
PROTOCOL_TYPE searched_protocol = PROTOCOL_NONE;
if (event->getType() == EVENT_TYPE_MESSAGE) if (event->getType() == EVENT_TYPE_MESSAGE)
{ {
if (event2->data().size() > 0) if (event->data().size() > 0)
{ {
searched_protocol = (PROTOCOL_TYPE)(event2->data()[0]); searched_protocol = (ProtocolType)(event->data()[0]);
event2->removeFront(1); event->removeFront(1);
} }
else else
{ {
Log::warn("ProtocolManager", "Not enough data."); Log::warn("ProtocolManager", "Not enough data.");
} }
} }
if (event->getType() == EVENT_TYPE_CONNECTED) else if (event->getType() == EVENT_TYPE_CONNECTED)
{ {
searched_protocol = PROTOCOL_CONNECTION; searched_protocol = PROTOCOL_CONNECTION;
} }
Log::verbose("ProtocolManager", "Received event for protocols of type %d", Log::verbose("ProtocolManager", "Received event for protocols of type %d",
searched_protocol); searched_protocol);
std::vector<unsigned int> protocols_ids;
m_protocols.lock(); m_protocols.lock();
for (unsigned int i = 0; i < m_protocols.getData().size() ; i++) for (unsigned int i = 0; i < m_protocols.getData().size() ; i++)
{ {
const ProtocolInfo &pi = m_protocols.getData()[i];
// Pass data to protocols even when paused // Pass data to protocols even when paused
if (m_protocols.getData()[i].protocol->getProtocolType() == searched_protocol || if (pi.m_protocol->getProtocolType() == searched_protocol ||
event->getType() == EVENT_TYPE_DISCONNECTED) event->getType() == EVENT_TYPE_DISCONNECTED)
{ {
protocols_ids.push_back(m_protocols.getData()[i].id); protocols_ids.push_back(pi.m_id);
}
} }
} // for i in m_protocols
m_protocols.unlock(); m_protocols.unlock();
// no protocol was aimed, show the msg to debug // no protocol was aimed, show the msg to debug
if (searched_protocol == PROTOCOL_NONE) if (searched_protocol == PROTOCOL_NONE)
{ {
Log::debug("ProtocolManager", "NO PROTOCOL : Message is \"%s\"", Log::debug("ProtocolManager", "NO PROTOCOL : Message is \"%s\"",
event2->data().std_string().c_str()); event->data().std_string().c_str());
} }
if (protocols_ids.size() != 0) if (protocols_ids.size() != 0)
{ {
EventProcessingInfo epi; EventProcessingInfo epi;
epi.arrival_time = (double)StkTime::getTimeSinceEpoch(); epi.m_arrival_time = (double)StkTime::getTimeSinceEpoch();
epi.event = event2; epi.m_event = event;
epi.protocols_ids = protocols_ids; epi.m_protocols_ids = protocols_ids;
m_events_to_process.getData().push_back(epi); // add the event to the queue // Add the event to the queue. After the event is handled
// its memory will be freed.
m_events_to_process.getData().push_back(epi);
} }
else else
{
Log::warn("ProtocolManager", Log::warn("ProtocolManager",
"Received an event for %d that has no destination protocol.", "Received an event for %d that has no destination protocol.",
searched_protocol); searched_protocol);
m_events_to_process.lock(); // Free the memory for the vent
} // notifyEvent delete event;
}
m_events_to_process.unlock();
} // propagateEvent
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void ProtocolManager::sendMessage(Protocol* sender, const NetworkString& message, void ProtocolManager::sendMessage(Protocol* sender, const NetworkString& message,
@ -185,33 +201,42 @@ void ProtocolManager::sendMessageExcept(Protocol* sender, STKPeer* peer,
} // sendMessageExcept } // sendMessageExcept
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Asks the manager to start a protocol.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol to start
* \return The unique id of the protocol that is being started.
*/
uint32_t ProtocolManager::requestStart(Protocol* protocol) uint32_t ProtocolManager::requestStart(Protocol* protocol)
{ {
// create the request // create the request
ProtocolRequest req; ProtocolRequest req;
ProtocolInfo info; req.m_protocol_info.m_protocol = protocol;
info.protocol = protocol; req.m_protocol_info.m_state = PROTOCOL_STATE_INITIALISING;
info.state = PROTOCOL_STATE_RUNNING; assignProtocolId(&req.m_protocol_info); // assign a unique id to the protocol.
assignProtocolId(&info); // assign a unique id to the protocol. req.m_type = PROTOCOL_REQUEST_START;
req.protocol_info = info;
req.type = PROTOCOL_REQUEST_START;
// add it to the request stack // add it to the request stack
pthread_mutex_lock(&m_requests_mutex); pthread_mutex_lock(&m_requests_mutex);
m_requests.push_back(req); m_requests.push_back(req);
pthread_mutex_unlock(&m_requests_mutex); pthread_mutex_unlock(&m_requests_mutex);
return info.id; return req.m_protocol_info.m_id;
} // requestStart } // requestStart
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Asks the manager to stop a protocol.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol to stop
*/
void ProtocolManager::requestStop(Protocol* protocol) void ProtocolManager::requestStop(Protocol* protocol)
{ {
if (!protocol) if (!protocol)
return; return;
// create the request // create the request
ProtocolRequest req; ProtocolRequest req;
req.protocol_info.protocol = protocol; req.m_protocol_info.m_protocol = protocol;
req.type = PROTOCOL_REQUEST_STOP; req.m_type = PROTOCOL_REQUEST_STOP;
// add it to the request stack // add it to the request stack
pthread_mutex_lock(&m_requests_mutex); pthread_mutex_lock(&m_requests_mutex);
m_requests.push_back(req); m_requests.push_back(req);
@ -219,14 +244,19 @@ void ProtocolManager::requestStop(Protocol* protocol)
} // requestStop } // requestStop
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Asks the manager to pause a protocol.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol to pause
*/
void ProtocolManager::requestPause(Protocol* protocol) void ProtocolManager::requestPause(Protocol* protocol)
{ {
if (!protocol) if (!protocol)
return; return;
// create the request // create the request
ProtocolRequest req; ProtocolRequest req;
req.protocol_info.protocol = protocol; req.m_protocol_info.m_protocol = protocol;
req.type = PROTOCOL_REQUEST_PAUSE; req.m_type = PROTOCOL_REQUEST_PAUSE;
// add it to the request stack // add it to the request stack
pthread_mutex_lock(&m_requests_mutex); pthread_mutex_lock(&m_requests_mutex);
m_requests.push_back(req); m_requests.push_back(req);
@ -234,14 +264,19 @@ void ProtocolManager::requestPause(Protocol* protocol)
} // requestPause } // requestPause
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Asks the manager to unpause a protocol.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol to unpause
*/
void ProtocolManager::requestUnpause(Protocol* protocol) void ProtocolManager::requestUnpause(Protocol* protocol)
{ {
if (!protocol) if (!protocol)
return; return;
// create the request // create the request
ProtocolRequest req; ProtocolRequest req;
req.protocol_info.protocol = protocol; req.m_protocol_info.m_protocol = protocol;
req.type = PROTOCOL_REQUEST_UNPAUSE; req.m_type = PROTOCOL_REQUEST_UNPAUSE;
// add it to the request stack // add it to the request stack
pthread_mutex_lock(&m_requests_mutex); pthread_mutex_lock(&m_requests_mutex);
m_requests.push_back(req); m_requests.push_back(req);
@ -249,20 +284,25 @@ void ProtocolManager::requestUnpause(Protocol* protocol)
} // requestUnpause } // requestUnpause
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Notifies the manager that a protocol is terminated.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol that is finished
*/
void ProtocolManager::requestTerminate(Protocol* protocol) void ProtocolManager::requestTerminate(Protocol* protocol)
{ {
if (!protocol) if (!protocol)
return; return;
// create the request // create the request
ProtocolRequest req; ProtocolRequest req;
req.protocol_info.protocol = protocol; req.m_protocol_info.m_protocol = protocol;
req.type = PROTOCOL_REQUEST_TERMINATE; req.m_type = PROTOCOL_REQUEST_TERMINATE;
// add it to the request stack // add it to the request stack
pthread_mutex_lock(&m_requests_mutex); pthread_mutex_lock(&m_requests_mutex);
// check that the request does not already exist : // check that the request does not already exist :
for (unsigned int i = 0; i < m_requests.size(); i++) for (unsigned int i = 0; i < m_requests.size(); i++)
{ {
if (m_requests[i].protocol_info.protocol == protocol) if (m_requests[i].m_protocol_info.m_protocol == protocol)
{ {
pthread_mutex_unlock(&m_requests_mutex); pthread_mutex_unlock(&m_requests_mutex);
return; return;
@ -273,19 +313,25 @@ void ProtocolManager::requestTerminate(Protocol* protocol)
} // requestTerminate } // requestTerminate
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void ProtocolManager::startProtocol(ProtocolInfo protocol) /** \brief Starts a protocol.
* Add the protocol info to the m_protocols vector.
* \param protocol : ProtocolInfo to start.
*/
void ProtocolManager::startProtocol(ProtocolInfo &protocol)
{ {
assert(protocol.m_state == PROTOCOL_STATE_INITIALISING);
// add the protocol to the protocol vector so that it's updated // add the protocol to the protocol vector so that it's updated
m_protocols.lock(); m_protocols.lock();
pthread_mutex_lock(&m_asynchronous_protocols_mutex); pthread_mutex_lock(&m_asynchronous_protocols_mutex);
Log::info("ProtocolManager", Log::info("ProtocolManager",
"A %s protocol with id=%u has been started. There are %ld protocols running.", "A %s protocol with id=%u has been started. There are %ld protocols running.",
typeid(*protocol.protocol).name(), protocol.id, typeid(*protocol.m_protocol).name(), protocol.m_id,
m_protocols.getData().size()+1); m_protocols.getData().size()+1);
m_protocols.getData().push_back(protocol); m_protocols.getData().push_back(protocol);
// setup the protocol and notify it that it's started // setup the protocol and notify it that it's started
protocol.protocol->setListener(this); protocol.m_protocol->setListener(this);
protocol.protocol->setup(); protocol.m_protocol->setup();
protocol.m_state = PROTOCOL_STATE_RUNNING;
m_protocols.unlock(); m_protocols.unlock();
pthread_mutex_unlock(&m_asynchronous_protocols_mutex); pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
} // startProtocol } // startProtocol
@ -301,12 +347,12 @@ void ProtocolManager::pauseProtocol(ProtocolInfo protocol)
// FIXME Does this need to be locked? // FIXME Does this need to be locked?
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
ProtocolInfo &p = m_protocols.getData()[i]; ProtocolInfo &pi = m_protocols.getData()[i];
if (p.protocol == protocol.protocol && if (pi.m_protocol == protocol.m_protocol &&
p.state == PROTOCOL_STATE_RUNNING) pi.m_state == PROTOCOL_STATE_RUNNING)
{ {
p.state = PROTOCOL_STATE_PAUSED; pi.m_state = PROTOCOL_STATE_PAUSED;
p.protocol->pause(); pi.m_protocol->pause();
} }
} }
} // pauseProtocol } // pauseProtocol
@ -318,11 +364,11 @@ void ProtocolManager::unpauseProtocol(ProtocolInfo protocol)
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
ProtocolInfo &p = m_protocols.getData()[i]; ProtocolInfo &p = m_protocols.getData()[i];
if (p.protocol == protocol.protocol && if (p.m_protocol == protocol.m_protocol &&
p.state == PROTOCOL_STATE_PAUSED) p.m_state == PROTOCOL_STATE_PAUSED)
{ {
p.state = PROTOCOL_STATE_RUNNING; p.m_state = PROTOCOL_STATE_RUNNING;
p.protocol->unpause(); p.m_protocol->unpause();
} }
} }
} // unpauseProtocol } // unpauseProtocol
@ -334,12 +380,12 @@ void ProtocolManager::protocolTerminated(ProtocolInfo protocol)
m_protocols.lock(); m_protocols.lock();
pthread_mutex_lock(&m_asynchronous_protocols_mutex); pthread_mutex_lock(&m_asynchronous_protocols_mutex);
int offset = 0; int offset = 0;
std::string protocol_type = typeid(*protocol.protocol).name(); std::string protocol_type = typeid(*protocol.m_protocol).name();
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (m_protocols.getData()[i-offset].protocol == protocol.protocol) if (m_protocols.getData()[i-offset].m_protocol == protocol.m_protocol)
{ {
delete m_protocols.getData()[i].protocol; delete m_protocols.getData()[i].m_protocol;
m_protocols.getData().erase(m_protocols.getData().begin()+(i-offset), m_protocols.getData().erase(m_protocols.getData().begin()+(i-offset),
m_protocols.getData().begin()+(i-offset)+1); m_protocols.getData().begin()+(i-offset)+1);
offset++; offset++;
@ -353,46 +399,59 @@ void ProtocolManager::protocolTerminated(ProtocolInfo protocol)
} // protocolTerminated } // protocolTerminated
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
bool ProtocolManager::propagateEvent(EventProcessingInfo* event, bool synchronous) /** Sends the event to the corresponding protocol.
*/
bool ProtocolManager::sendEvent(EventProcessingInfo* event, bool synchronous)
{ {
m_protocols.lock();
int index = 0; int index = 0;
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (event->protocols_ids[index] == m_protocols.getData()[i].id) if (event->m_protocols_ids[index] == m_protocols.getData()[i].m_id)
{ {
bool result = false; bool result = false;
if (synchronous) if (synchronous)
result = m_protocols.getData()[i].protocol result = m_protocols.getData()[i].m_protocol
->notifyEvent(event->event); ->notifyEvent(event->m_event);
else else
result = m_protocols.getData()[i].protocol result = m_protocols.getData()[i].m_protocol
->notifyEventAsynchronous(event->event); ->notifyEventAsynchronous(event->m_event);
if (result) if (result)
event->protocols_ids.pop_back(); event->m_protocols_ids.pop_back();
else else
index++; index++;
} }
} }
if (event->protocols_ids.size() == 0 || m_protocols.unlock();
(StkTime::getTimeSinceEpoch()-event->arrival_time) >= TIME_TO_KEEP_EVENTS)
if (event->m_protocols_ids.size() == 0 ||
(StkTime::getTimeSinceEpoch()-event->m_arrival_time) >= TIME_TO_KEEP_EVENTS)
{ {
// because we made a copy of the event delete event->m_event;
delete event->event;
return true; return true;
} }
return false; return false;
} // propagateEvent } // sendEvent
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Updates the manager.
*
* This function processes the events queue, notifies the concerned
* protocols that they have events to process. Then ask all protocols
* to update themselves. Finally processes stored requests about
* starting, stoping, pausing etc... protocols.
* This function is called by the main loop.
* This function IS FPS-dependant.
*/
void ProtocolManager::update() void ProtocolManager::update()
{ {
// before updating, notice protocols that they have received events // before updating, notify protocols that they have received events
m_events_to_process.lock(); m_events_to_process.lock();
int size = (int)m_events_to_process.getData().size(); int size = (int)m_events_to_process.getData().size();
int offset = 0; int offset = 0;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
bool result = propagateEvent(&m_events_to_process.getData()[i+offset], true); bool result = sendEvent(&m_events_to_process.getData()[i+offset], true);
if (result) if (result)
{ {
m_events_to_process.getData() m_events_to_process.getData()
@ -406,13 +465,21 @@ void ProtocolManager::update()
m_protocols.lock(); m_protocols.lock();
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (m_protocols.getData()[i].state == PROTOCOL_STATE_RUNNING) if (m_protocols.getData()[i].m_state == PROTOCOL_STATE_RUNNING)
m_protocols.getData()[i].protocol->update(); m_protocols.getData()[i].m_protocol->update();
} }
m_protocols.unlock(); m_protocols.unlock();
} // update } // update
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Updates the manager.
* This function processes the events queue, notifies the concerned
* protocols that they have events to process. Then ask all protocols
* to update themselves. Finally processes stored requests about
* starting, stoping, pausing etc... protocols.
* This function is called in a thread.
* This function IS NOT FPS-dependant.
*/
void ProtocolManager::asynchronousUpdate() void ProtocolManager::asynchronousUpdate()
{ {
// before updating, notice protocols that they have received information // before updating, notice protocols that they have received information
@ -421,7 +488,7 @@ void ProtocolManager::asynchronousUpdate()
int offset = 0; int offset = 0;
for (int i = 0; i < size; i++) for (int i = 0; i < size; i++)
{ {
bool result = propagateEvent(&m_events_to_process.getData()[i+offset], false); bool result = sendEvent(&m_events_to_process.getData()[i+offset], false);
if (result) if (result)
{ {
m_events_to_process.getData() m_events_to_process.getData()
@ -437,8 +504,8 @@ void ProtocolManager::asynchronousUpdate()
// FIXME: does m_protocols need to be locked??? // FIXME: does m_protocols need to be locked???
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (m_protocols.getData()[i].state == PROTOCOL_STATE_RUNNING) if (m_protocols.getData()[i].m_state == PROTOCOL_STATE_RUNNING)
m_protocols.getData()[i].protocol->asynchronousUpdate(); m_protocols.getData()[i].m_protocol->asynchronousUpdate();
} }
pthread_mutex_unlock(&m_asynchronous_protocols_mutex); pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
@ -447,22 +514,22 @@ void ProtocolManager::asynchronousUpdate()
pthread_mutex_lock(&m_requests_mutex); pthread_mutex_lock(&m_requests_mutex);
for (unsigned int i = 0; i < m_requests.size(); i++) for (unsigned int i = 0; i < m_requests.size(); i++)
{ {
switch (m_requests[i].type) switch (m_requests[i].m_type)
{ {
case PROTOCOL_REQUEST_START: case PROTOCOL_REQUEST_START:
startProtocol(m_requests[i].protocol_info); startProtocol(m_requests[i].m_protocol_info);
break; break;
case PROTOCOL_REQUEST_STOP: case PROTOCOL_REQUEST_STOP:
stopProtocol(m_requests[i].protocol_info); stopProtocol(m_requests[i].m_protocol_info);
break; break;
case PROTOCOL_REQUEST_PAUSE: case PROTOCOL_REQUEST_PAUSE:
pauseProtocol(m_requests[i].protocol_info); pauseProtocol(m_requests[i].m_protocol_info);
break; break;
case PROTOCOL_REQUEST_UNPAUSE: case PROTOCOL_REQUEST_UNPAUSE:
unpauseProtocol(m_requests[i].protocol_info); unpauseProtocol(m_requests[i].m_protocol_info);
break; break;
case PROTOCOL_REQUEST_TERMINATE: case PROTOCOL_REQUEST_TERMINATE:
protocolTerminated(m_requests[i].protocol_info); protocolTerminated(m_requests[i].m_protocol_info);
break; break;
} }
} }
@ -471,38 +538,46 @@ void ProtocolManager::asynchronousUpdate()
} // asynchronousUpdate } // asynchronousUpdate
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
PROTOCOL_STATE ProtocolManager::getProtocolState(uint32_t id) /** \brief Get the state of a protocol using its id.
* \param id : The id of the protocol you seek the state.
* \return The state of the protocol.
*/
ProtocolState ProtocolManager::getProtocolState(uint32_t id)
{ {
//FIXME that actually need a lock, but it also can be called from //FIXME that actually need a lock, but it also can be called from
// a locked section anyway // a locked section anyway
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (m_protocols.getData()[i].id == id) // we know a protocol with that id if (m_protocols.getData()[i].m_id == id) // we know a protocol with that id
return m_protocols.getData()[i].state; return m_protocols.getData()[i].m_state;
} }
// the protocol isn't running right now // the protocol isn't running right now
for (unsigned int i = 0; i < m_requests.size(); i++) for (unsigned int i = 0; i < m_requests.size(); i++)
{ {
// the protocol is going to be started // the protocol is going to be started
if (m_requests[i].protocol_info.id == id) if (m_requests[i].m_protocol_info.m_id == id)
return PROTOCOL_STATE_RUNNING; // we can say it's running return PROTOCOL_STATE_RUNNING; // we can say it's running
} }
return PROTOCOL_STATE_TERMINATED; // else, it's already finished return PROTOCOL_STATE_TERMINATED; // else, it's already finished
} // getProtocolState } // getProtocolState
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
PROTOCOL_STATE ProtocolManager::getProtocolState(Protocol* protocol) /** \brief Get the state of a protocol using a pointer on it.
* \param protocol : A pointer to the protocol you seek the state.
* \return The state of the protocol.
*/
ProtocolState ProtocolManager::getProtocolState(Protocol* protocol)
{ {
// FIXME Does this need to be locked? // FIXME Does this need to be locked?
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (m_protocols.getData()[i].protocol == protocol) // the protocol is known if (m_protocols.getData()[i].m_protocol == protocol) // the protocol is known
return m_protocols.getData()[i].state; return m_protocols.getData()[i].m_state;
} }
for (unsigned int i = 0; i < m_requests.size(); i++) for (unsigned int i = 0; i < m_requests.size(); i++)
{ {
// the protocol is going to be started // the protocol is going to be started
if (m_requests[i].protocol_info.protocol == protocol) if (m_requests[i].m_protocol_info.m_protocol == protocol)
return PROTOCOL_STATE_RUNNING; // we can say it's running return PROTOCOL_STATE_RUNNING; // we can say it's running
} }
// we don't know this protocol at all, it's finished // we don't know this protocol at all, it's finished
@ -510,48 +585,65 @@ PROTOCOL_STATE ProtocolManager::getProtocolState(Protocol* protocol)
} // getProtocolState } // getProtocolState
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Get the id of a protocol.
* \param protocol : A pointer to the protocol you seek the id.
* \return The id of the protocol pointed by the protocol parameter.
*/
uint32_t ProtocolManager::getProtocolID(Protocol* protocol) uint32_t ProtocolManager::getProtocolID(Protocol* protocol)
{ {
// FIXME: Does this need to be locked? // FIXME: Does this need to be locked?
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (m_protocols.getData()[i].protocol == protocol) if (m_protocols.getData()[i].m_protocol == protocol)
return m_protocols.getData()[i].id; return m_protocols.getData()[i].m_id;
} }
return 0; return 0;
} // getProtocolID } // getProtocolID
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Get a protocol using its id.
* \param id : Unique ID of the seek protocol.
* \return The protocol that has the ID id.
*/
Protocol* ProtocolManager::getProtocol(uint32_t id) Protocol* ProtocolManager::getProtocol(uint32_t id)
{ {
// FIXME: does m_protocols need to be locked?? // FIXME: does m_protocols need to be locked??
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (m_protocols.getData()[i].id == id) if (m_protocols.getData()[i].m_id == id)
return m_protocols.getData()[i].protocol; return m_protocols.getData()[i].m_protocol;
} }
return NULL; return NULL;
} // getProtocol } // getProtocol
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
Protocol* ProtocolManager::getProtocol(PROTOCOL_TYPE type) /** \brief Get a protocol using its type.
* \param type : The type of the protocol.
* \return The protocol that matches the given type.
*/
Protocol* ProtocolManager::getProtocol(ProtocolType type)
{ {
// FIXME: Does m_protocols need to be locked? // FIXME: Does m_protocols need to be locked?
for (unsigned int i = 0; i < m_protocols.getData().size(); i++) for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{ {
if (m_protocols.getData()[i].protocol->getProtocolType() == type) if (m_protocols.getData()[i].m_protocol->getProtocolType() == type)
return m_protocols.getData()[i].protocol; return m_protocols.getData()[i].m_protocol;
} }
return NULL; return NULL;
} // getProtocol } // getProtocol
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** \brief Know whether the app is a server.
* \return True if this application is in server mode, false elseway.
*/
bool ProtocolManager::isServer() bool ProtocolManager::isServer()
{ {
return NetworkManager::getInstance()->isServer(); return NetworkManager::getInstance()->isServer();
} // isServer } // isServer
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/*! \brief Tells if we need to stop the update thread.
*/
int ProtocolManager::exit() int ProtocolManager::exit()
{ {
switch(pthread_mutex_trylock(&m_exit_mutex)) { switch(pthread_mutex_trylock(&m_exit_mutex)) {
@ -568,7 +660,7 @@ int ProtocolManager::exit()
void ProtocolManager::assignProtocolId(ProtocolInfo* protocol_info) void ProtocolManager::assignProtocolId(ProtocolInfo* protocol_info)
{ {
pthread_mutex_lock(&m_id_mutex); pthread_mutex_lock(&m_id_mutex);
protocol_info->id = m_next_protocol_id; protocol_info->m_id = m_next_protocol_id;
m_next_protocol_id++; m_next_protocol_id++;
pthread_mutex_unlock(&m_id_mutex); pthread_mutex_unlock(&m_id_mutex);
} // assignProtocolId } // assignProtocolId

View File

@ -23,7 +23,6 @@
#ifndef PROTOCOL_MANAGER_HPP #ifndef PROTOCOL_MANAGER_HPP
#define PROTOCOL_MANAGER_HPP #define PROTOCOL_MANAGER_HPP
#include "network/event.hpp"
#include "network/network_string.hpp" #include "network/network_string.hpp"
#include "network/protocol.hpp" #include "network/protocol.hpp"
#include "utils/no_copy.hpp" #include "utils/no_copy.hpp"
@ -33,67 +32,74 @@
#include <vector> #include <vector>
class Event;
class STKPeer;
#define TIME_TO_KEEP_EVENTS 1.0 #define TIME_TO_KEEP_EVENTS 1.0
/*! /** \enum PROTOCOL_STATE
* \enum PROTOCOL_STATE
* \brief Defines the three states that a protocol can have. * \brief Defines the three states that a protocol can have.
*/ */
enum PROTOCOL_STATE enum ProtocolState
{ {
PROTOCOL_STATE_INITIALISING, //!< The protocol is waiting to be started
PROTOCOL_STATE_RUNNING, //!< The protocol is being updated everytime. PROTOCOL_STATE_RUNNING, //!< The protocol is being updated everytime.
PROTOCOL_STATE_PAUSED, //!< The protocol is paused. PROTOCOL_STATE_PAUSED, //!< The protocol is paused.
PROTOCOL_STATE_TERMINATED //!< The protocol is terminated/does not exist. PROTOCOL_STATE_TERMINATED //!< The protocol is terminated/does not exist.
}; }; // ProtocolState
/*! // ----------------------------------------------------------------------------
* \enum PROTOCOL_REQUEST_TYPE /** \enum ProtocolRequestType
* \brief Defines actions that can be done about protocols. * \brief Defines actions that can be done about protocols.
* This enum is used essentially to keep the manager thread-safe and * This enum is used essentially to keep the manager thread-safe and
* to avoid protocols modifying directly their state. * to avoid protocols modifying directly their state.
*/ */
enum PROTOCOL_REQUEST_TYPE enum ProtocolRequestType
{ {
PROTOCOL_REQUEST_START, //!< Start a protocol PROTOCOL_REQUEST_START, //!< Start a protocol
PROTOCOL_REQUEST_STOP, //!< Stop a protocol PROTOCOL_REQUEST_STOP, //!< Stop a protocol
PROTOCOL_REQUEST_PAUSE, //!< Pause a protocol PROTOCOL_REQUEST_PAUSE, //!< Pause a protocol
PROTOCOL_REQUEST_UNPAUSE, //!< Unpause a protocol PROTOCOL_REQUEST_UNPAUSE, //!< Unpause a protocol
PROTOCOL_REQUEST_TERMINATE //!< Terminate a protocol PROTOCOL_REQUEST_TERMINATE //!< Terminate a protocol
}; }; // ProtocolRequestType
/*! // ----------------------------------------------------------------------------
* \struct ProtocolInfo /** \struct ProtocolInfo
* \brief Stores the information needed to manage protocols * \brief Stores the information needed to manage protocols
*/ */
typedef struct ProtocolInfo typedef struct ProtocolInfo
{ {
PROTOCOL_STATE state; //!< The state of the protocol ProtocolState m_state; //!< The state of the protocol
Protocol* protocol; //!< A pointer to the protocol Protocol* m_protocol; //!< A pointer to the protocol
uint32_t id; //!< The unique id of the protocol uint32_t m_id; //!< The unique id of the protocol
} ProtocolInfo; } ProtocolInfo;
/*! // ----------------------------------------------------------------------------
* \struct ProtocolRequest /** \struct ProtocolRequest
* \brief Represents a request to do an action about a protocol. * \brief Represents a request to do an action about a protocol.
*/ */
typedef struct ProtocolRequest typedef struct ProtocolRequest
{ {
PROTOCOL_REQUEST_TYPE type; //!< The type of request /** The type of request. */
ProtocolInfo protocol_info; //!< The concerned protocol information ProtocolRequestType m_type;
/** The concerned protocol information. */
ProtocolInfo m_protocol_info;
} ProtocolRequest; } ProtocolRequest;
/*! \struct ProtocolRequest // ----------------------------------------------------------------------------
/** \struct ProtocolRequest
* \brief Used to pass the event to protocols that need it * \brief Used to pass the event to protocols that need it
*/ */
typedef struct EventProcessingInfo typedef struct EventProcessingInfo
{ {
Event* event; Event* m_event;
double arrival_time; double m_arrival_time;
std::vector<unsigned int> protocols_ids; std::vector<unsigned int> m_protocols_ids;
} EventProcessingInfo; } EventProcessingInfo;
/*! // ----------------------------------------------------------------------------
* \class ProtocolManager /** \class ProtocolManager
* \brief Manages the protocols at runtime. * \brief Manages the protocols at runtime.
* *
* This class is in charge of storing and managing protocols. * This class is in charge of storing and managing protocols.
@ -111,125 +117,30 @@ class ProtocolManager : public AbstractSingleton<ProtocolManager>,
static void* mainLoop(void *data); static void* mainLoop(void *data);
public: public:
/*! \brief Stops the protocol manager. */
virtual void abort(); virtual void abort();
/*! virtual void propagateEvent(Event* event);
* \brief Function that processes incoming events. virtual void sendMessage(Protocol* sender,
* This function is called by the network manager each time there is an const NetworkString& message,
* incoming packet. bool reliable = true);
*/ virtual void sendMessage(Protocol* sender, STKPeer* peer,
virtual void notifyEvent(Event* event); const NetworkString& message,
/*! bool reliable = true);
* \brief WILL BE COMMENTED LATER virtual void sendMessageExcept(Protocol* sender, STKPeer* peer,
*/ const NetworkString& message,
virtual void sendMessage(Protocol* sender, const NetworkString& message, bool reliable = true); bool reliable = true);
/*!
* \brief WILL BE COMMENTED LATER
*/
virtual void sendMessage(Protocol* sender, STKPeer* peer, const NetworkString& message, bool reliable = true);
/*!
* \brief WILL BE COMMENTED LATER
*/
virtual void sendMessageExcept(Protocol* sender, STKPeer* peer, const NetworkString& message, bool reliable = true);
/*!
* \brief Asks the manager to start a protocol.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol to start
* \return The unique id of the protocol that is being started.
*/
virtual uint32_t requestStart(Protocol* protocol); virtual uint32_t requestStart(Protocol* protocol);
/*!
* \brief Asks the manager to stop a protocol.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol to stop
*/
virtual void requestStop(Protocol* protocol); virtual void requestStop(Protocol* protocol);
/*!
* \brief Asks the manager to pause a protocol.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol to pause
*/
virtual void requestPause(Protocol* protocol); virtual void requestPause(Protocol* protocol);
/*!
* \brief Asks the manager to unpause a protocol.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol to unpause
*/
virtual void requestUnpause(Protocol* protocol); virtual void requestUnpause(Protocol* protocol);
/*!
* \brief Notifies the manager that a protocol is terminated.
* This function will store the request, and process it at a time it is
* thread-safe.
* \param protocol : A pointer to the protocol that is finished
*/
virtual void requestTerminate(Protocol* protocol); virtual void requestTerminate(Protocol* protocol);
/*!
* \brief Updates the manager.
*
* This function processes the events queue, notifies the concerned
* protocols that they have events to process. Then ask all protocols
* to update themselves. Finally processes stored requests about
* starting, stoping, pausing etc... protocols.
* This function is called by the main loop.
* This function IS FPS-dependant.
*/
virtual void update(); virtual void update();
/*!
* \brief Updates the manager.
*
* This function processes the events queue, notifies the concerned
* protocols that they have events to process. Then ask all protocols
* to update themselves. Finally processes stored requests about
* starting, stoping, pausing etc... protocols.
* This function is called in a thread.
* This function IS NOT FPS-dependant.
*/
virtual void asynchronousUpdate(); virtual void asynchronousUpdate();
virtual ProtocolState getProtocolState(uint32_t id);
/*! virtual ProtocolState getProtocolState(Protocol* protocol);
* \brief Get the state of a protocol using its id.
* \param id : The id of the protocol you seek the state.
* \return The state of the protocol.
*/
virtual PROTOCOL_STATE getProtocolState(uint32_t id);
/*!
* \brief Get the state of a protocol using a pointer on it.
* \param protocol : A pointer to the protocol you seek the state.
* \return The state of the protocol.
*/
virtual PROTOCOL_STATE getProtocolState(Protocol* protocol);
/*!
* \brief Get the id of a protocol.
* \param protocol : A pointer to the protocol you seek the id.
* \return The id of the protocol pointed by the protocol parameter.
*/
virtual uint32_t getProtocolID(Protocol* protocol); virtual uint32_t getProtocolID(Protocol* protocol);
/*!
* \brief Get a protocol using its id.
* \param id : Unique ID of the seek protocol.
* \return The protocol that has the ID id.
*/
virtual Protocol* getProtocol(uint32_t id); virtual Protocol* getProtocol(uint32_t id);
/*! virtual Protocol* getProtocol(ProtocolType type);
* \brief Get a protocol using its type.
* \param type : The type of the protocol.
* \return The protocol that matches the given type.
*/
virtual Protocol* getProtocol(PROTOCOL_TYPE type);
/*! \brief Know whether the app is a server.
* \return True if this application is in server mode, false elseway.
*/
bool isServer(); bool isServer();
/*! \brief Tells if we need to stop the update thread. */
int exit(); int exit();
protected: protected:
@ -251,12 +162,7 @@ class ProtocolManager : public AbstractSingleton<ProtocolManager>,
*/ */
void assignProtocolId(ProtocolInfo* protocol_info); void assignProtocolId(ProtocolInfo* protocol_info);
/*! virtual void startProtocol(ProtocolInfo &protocol);
* \brief Starts a protocol.
* Add the protocol info to the m_protocols vector.
* \param protocol : ProtocolInfo to start.
*/
virtual void startProtocol(ProtocolInfo protocol);
/*! /*!
* \brief Stops a protocol. * \brief Stops a protocol.
* Coes nothing. Noone can stop running protocols for now. * Coes nothing. Noone can stop running protocols for now.
@ -282,7 +188,7 @@ class ProtocolManager : public AbstractSingleton<ProtocolManager>,
*/ */
virtual void protocolTerminated(ProtocolInfo protocol); virtual void protocolTerminated(ProtocolInfo protocol);
bool propagateEvent(EventProcessingInfo* event, bool synchronous); bool sendEvent(EventProcessingInfo* event, bool synchronous);
// protected members // protected members
/** Contains the running protocols. /** Contains the running protocols.

View File

@ -20,6 +20,7 @@
#include "config/player_manager.hpp" #include "config/player_manager.hpp"
#include "modes/world_with_rank.hpp" #include "modes/world_with_rank.hpp"
#include "network/event.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "network/network_world.hpp" #include "network/network_world.hpp"
#include "network/protocols/start_game_protocol.hpp" #include "network/protocols/start_game_protocol.hpp"
@ -135,7 +136,7 @@ bool ClientLobbyRoomProtocol::notifyEvent(Event* event)
assert(m_setup); // assert that the setup exists assert(m_setup); // assert that the setup exists
if (event->getType() == EVENT_TYPE_MESSAGE) if (event->getType() == EVENT_TYPE_MESSAGE)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
assert(data.size()); // assert that data isn't empty assert(data.size()); // assert that data isn't empty
uint8_t message_type = data[0]; uint8_t message_type = data[0];
if (message_type != 0x03 && if (message_type != 0x03 &&
@ -161,7 +162,7 @@ bool ClientLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
assert(m_setup); // assert that the setup exists assert(m_setup); // assert that the setup exists
if (event->getType() == EVENT_TYPE_MESSAGE) if (event->getType() == EVENT_TYPE_MESSAGE)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
assert(data.size()); // assert that data isn't empty assert(data.size()); // assert that data isn't empty
uint8_t message_type = data[0]; uint8_t message_type = data[0];
if (message_type == 0x03 || if (message_type == 0x03 ||
@ -285,7 +286,7 @@ void ClientLobbyRoomProtocol::update()
*/ */
void ClientLobbyRoomProtocol::newPlayer(Event* event) void ClientLobbyRoomProtocol::newPlayer(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() != 7 || data[0] != 4 || data[5] != 1) // 7 bytes remains now if (data.size() != 7 || data[0] != 4 || data[5] != 1) // 7 bytes remains now
{ {
Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected."); Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
@ -328,7 +329,7 @@ void ClientLobbyRoomProtocol::newPlayer(Event* event)
*/ */
void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event) void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() != 2 || data[0] != 1) if (data.size() != 2 || data[0] != 1)
{ {
Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected."); Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
@ -359,7 +360,7 @@ void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
*/ */
void ClientLobbyRoomProtocol::connectionAccepted(Event* event) void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
{ {
NetworkString data = event->data(); NetworkString &data = event->data();
if (data.size() < 12 || data[0] != 1 || data[2] != 4 || data[7] != 4) // 12 bytes remains now if (data.size() < 12 || data[0] != 1 || data[2] != 4 || data[7] != 4) // 12 bytes remains now
{ {
Log::error("ClientLobbyRoomProtocol", "A message notifying an accepted connection wasn't formated as expected."); Log::error("ClientLobbyRoomProtocol", "A message notifying an accepted connection wasn't formated as expected.");
@ -428,7 +429,7 @@ void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
*/ */
void ClientLobbyRoomProtocol::connectionRefused(Event* event) void ClientLobbyRoomProtocol::connectionRefused(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() != 2 || data[0] != 1) // 2 bytes remains now if (data.size() != 2 || data[0] != 1) // 2 bytes remains now
{ {
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused connection wasn't formated as expected."); Log::error("ClientLobbyRoomProtocol", "A message notifying a refused connection wasn't formated as expected.");
@ -463,7 +464,7 @@ void ClientLobbyRoomProtocol::connectionRefused(Event* event)
*/ */
void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event) void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() != 2 || data[0] != 1) if (data.size() != 2 || data[0] != 1)
{ {
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused kart selection wasn't formated as expected."); Log::error("ClientLobbyRoomProtocol", "A message notifying a refused kart selection wasn't formated as expected.");
@ -498,7 +499,7 @@ void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
*/ */
void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event) void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() < 3 || data[0] != 1) if (data.size() < 3 || data[0] != 1)
{ {
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart selection update wasn't formated as expected."); Log::error("ClientLobbyRoomProtocol", "A message notifying a kart selection update wasn't formated as expected.");
@ -534,7 +535,7 @@ void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
*/ */
void ClientLobbyRoomProtocol::startGame(Event* event) void ClientLobbyRoomProtocol::startGame(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() < 5 || data[0] != 4) if (data.size() < 5 || data[0] != 4)
{ {
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart " Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
@ -567,7 +568,7 @@ void ClientLobbyRoomProtocol::startGame(Event* event)
*/ */
void ClientLobbyRoomProtocol::startSelection(Event* event) void ClientLobbyRoomProtocol::startSelection(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() < 5 || data[0] != 4) if (data.size() < 5 || data[0] != 4)
{ {
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart " Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
@ -599,12 +600,12 @@ void ClientLobbyRoomProtocol::startSelection(Event* event)
*/ */
void ClientLobbyRoomProtocol::raceFinished(Event* event) void ClientLobbyRoomProtocol::raceFinished(Event* event)
{ {
if (event->data().size() < 5) NetworkString &data = event->data();
if (data.size() < 5)
{ {
Log::error("ClientLobbyRoomProtocol", "Not enough data provided."); Log::error("ClientLobbyRoomProtocol", "Not enough data provided.");
return; return;
} }
NetworkString data = event->data();
if (event->getPeer()->getClientServerToken() != data.gui32(1)) if (event->getPeer()->getClientServerToken() != data.gui32(1))
{ {
Log::error("ClientLobbyRoomProtocol", "Bad token"); Log::error("ClientLobbyRoomProtocol", "Bad token");
@ -675,7 +676,7 @@ void ClientLobbyRoomProtocol::raceFinished(Event* event)
*/ */
void ClientLobbyRoomProtocol::playerMajorVote(Event* event) void ClientLobbyRoomProtocol::playerMajorVote(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 9)) if (!checkDataSizeAndToken(event, 9))
return; return;
if (!isByteCorrect(event, 5, 1)) if (!isByteCorrect(event, 5, 1))
@ -698,7 +699,7 @@ void ClientLobbyRoomProtocol::playerMajorVote(Event* event)
*/ */
void ClientLobbyRoomProtocol::playerRaceCountVote(Event* event) void ClientLobbyRoomProtocol::playerRaceCountVote(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 9)) if (!checkDataSizeAndToken(event, 9))
return; return;
if (!isByteCorrect(event, 5, 1)) if (!isByteCorrect(event, 5, 1))
@ -721,7 +722,7 @@ void ClientLobbyRoomProtocol::playerRaceCountVote(Event* event)
*/ */
void ClientLobbyRoomProtocol::playerMinorVote(Event* event) void ClientLobbyRoomProtocol::playerMinorVote(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 9)) if (!checkDataSizeAndToken(event, 9))
return; return;
if (!isByteCorrect(event, 5, 1)) if (!isByteCorrect(event, 5, 1))
@ -745,7 +746,7 @@ void ClientLobbyRoomProtocol::playerMinorVote(Event* event)
*/ */
void ClientLobbyRoomProtocol::playerTrackVote(Event* event) void ClientLobbyRoomProtocol::playerTrackVote(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 10)) if (!checkDataSizeAndToken(event, 10))
return; return;
if (!isByteCorrect(event, 5, 1)) if (!isByteCorrect(event, 5, 1))
@ -771,7 +772,7 @@ void ClientLobbyRoomProtocol::playerTrackVote(Event* event)
*/ */
void ClientLobbyRoomProtocol::playerReversedVote(Event* event) void ClientLobbyRoomProtocol::playerReversedVote(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 11)) if (!checkDataSizeAndToken(event, 11))
return; return;
if (!isByteCorrect(event, 5, 1)) if (!isByteCorrect(event, 5, 1))
@ -797,7 +798,7 @@ void ClientLobbyRoomProtocol::playerReversedVote(Event* event)
*/ */
void ClientLobbyRoomProtocol::playerLapsVote(Event* event) void ClientLobbyRoomProtocol::playerLapsVote(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 9)) if (!checkDataSizeAndToken(event, 9))
return; return;
if (!isByteCorrect(event, 5, 1)) if (!isByteCorrect(event, 5, 1))

View File

@ -2,6 +2,9 @@
#define CLIENT_LOBBY_ROOM_PROTOCOL_HPP #define CLIENT_LOBBY_ROOM_PROTOCOL_HPP
#include "network/protocols/lobby_room_protocol.hpp" #include "network/protocols/lobby_room_protocol.hpp"
#include "network/types.hpp"
class STKPeer;
class ClientLobbyRoomProtocol : public LobbyRoomProtocol class ClientLobbyRoomProtocol : public LobbyRoomProtocol
{ {

View File

@ -19,6 +19,7 @@
#include "network/protocols/connect_to_peer.hpp" #include "network/protocols/connect_to_peer.hpp"
#include "network/client_network_manager.hpp" #include "network/client_network_manager.hpp"
#include "network/event.hpp"
#include "network/protocols/get_public_address.hpp" #include "network/protocols/get_public_address.hpp"
#include "network/protocols/get_peer_address.hpp" #include "network/protocols/get_peer_address.hpp"
#include "network/protocols/show_public_address.hpp" #include "network/protocols/show_public_address.hpp"

View File

@ -19,6 +19,7 @@
#include "network/protocols/connect_to_server.hpp" #include "network/protocols/connect_to_server.hpp"
#include "network/client_network_manager.hpp" #include "network/client_network_manager.hpp"
#include "network/event.hpp"
#include "network/protocols/get_public_address.hpp" #include "network/protocols/get_public_address.hpp"
#include "network/protocols/get_peer_address.hpp" #include "network/protocols/get_peer_address.hpp"
#include "network/protocols/show_public_address.hpp" #include "network/protocols/show_public_address.hpp"
@ -37,31 +38,36 @@
#endif #endif
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Quick join/
ConnectToServer::ConnectToServer() : */
Protocol(NULL, PROTOCOL_CONNECTION) ConnectToServer::ConnectToServer() : Protocol(NULL, PROTOCOL_CONNECTION)
{ {
m_server_id = 0; m_server_id = 0;
m_host_id = 0;
m_quick_join = true; m_quick_join = true;
m_state = NONE; m_state = NONE;
} } // ConnectToServer()
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Specify server to connect to.
ConnectToServer::ConnectToServer(uint32_t server_id, uint32_t host_id) : * \param server_id Id of server to connect to.
Protocol(NULL, PROTOCOL_CONNECTION) * \param host_id Id of host.
*/
ConnectToServer::ConnectToServer(uint32_t server_id, uint32_t host_id)
: Protocol(NULL, PROTOCOL_CONNECTION)
{ {
m_server_id = server_id; m_server_id = server_id;
m_host_id = host_id; m_host_id = host_id;
m_quick_join = false; m_quick_join = false;
m_state = NONE; m_state = NONE;
} } // ConnectToServer(server, host)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** Destructor.
*/
ConnectToServer::~ConnectToServer() ConnectToServer::~ConnectToServer()
{ {
} } // ~ConnectToServer
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -74,20 +80,18 @@ bool ConnectToServer::notifyEventAsynchronous(Event* event)
m_state = CONNECTED; // we received a message, we are connected m_state = CONNECTED; // we received a message, we are connected
} }
return true; return true;
} } // notifyEventAsynchronous
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void ConnectToServer::setup() void ConnectToServer::setup()
{ {
Log::info("ConnectToServer", "SETUPP"); Log::info("ConnectToServer", "SETUP");
m_state = NONE; m_state = NONE;
m_server_address.clear(); m_server_address.clear();
m_current_protocol_id = 0; m_current_protocol_id = 0;
} } // setup
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
void ConnectToServer::asynchronousUpdate() void ConnectToServer::asynchronousUpdate()
{ {
switch(m_state) switch(m_state)
@ -95,87 +99,161 @@ void ConnectToServer::asynchronousUpdate()
case NONE: case NONE:
{ {
Log::info("ConnectToServer", "Protocol starting"); Log::info("ConnectToServer", "Protocol starting");
m_current_protocol_id = m_listener->requestStart(new GetPublicAddress()); m_current_protocol_id =
m_listener->requestStart(new GetPublicAddress());
m_state = GETTING_SELF_ADDRESS; m_state = GETTING_SELF_ADDRESS;
break; break;
} }
case GETTING_SELF_ADDRESS: case GETTING_SELF_ADDRESS:
if (m_listener->getProtocolState(m_current_protocol_id) if (m_listener->getProtocolState(m_current_protocol_id) ==
== PROTOCOL_STATE_TERMINATED) // now we know the public addr PROTOCOL_STATE_TERMINATED) // now we know the public addr
{ {
m_state = SHOWING_SELF_ADDRESS; m_state = SHOWING_SELF_ADDRESS;
m_current_protocol_id = m_listener->requestStart(new ShowPublicAddress()); m_current_protocol_id =
m_listener->requestStart(new ShowPublicAddress());
Log::info("ConnectToServer", "Public address known"); Log::info("ConnectToServer", "Public address known");
/*
if (m_quick_join)
m_current_protocol_id = m_listener->requestStart(new QuickJoinProtocol(&m_server_address, &m_server_id));
else
m_current_protocol_id = m_listener->requestStart(new GetPeerAddress(m_server_id, &m_server_address));*/
} }
break; break;
case SHOWING_SELF_ADDRESS: case SHOWING_SELF_ADDRESS:
if (m_listener->getProtocolState(m_current_protocol_id) if (m_listener->getProtocolState(m_current_protocol_id) ==
== PROTOCOL_STATE_TERMINATED) // now our public address is in the database PROTOCOL_STATE_TERMINATED)
{ {
// now our public address is in the database
Log::info("ConnectToServer", "Public address shown"); Log::info("ConnectToServer", "Public address shown");
if (m_quick_join) if (m_quick_join)
{ {
m_current_protocol_id = m_listener->requestStart(new QuickJoinProtocol(&m_server_address, &m_server_id)); m_current_protocol_id = m_listener->requestStart(
new QuickJoinProtocol(&m_server_address,
&m_server_id) );
m_state = REQUESTING_CONNECTION; m_state = REQUESTING_CONNECTION;
} }
else else
{ {
m_current_protocol_id = m_listener->requestStart(new GetPeerAddress(m_host_id, &m_server_address)); m_current_protocol_id = m_listener->requestStart(
new GetPeerAddress(m_host_id,
&m_server_address) );
m_state = GETTING_SERVER_ADDRESS; m_state = GETTING_SERVER_ADDRESS;
} }
} }
break; break;
case GETTING_SERVER_ADDRESS: case GETTING_SERVER_ADDRESS:
if (m_listener->getProtocolState(m_current_protocol_id) if (m_listener->getProtocolState(m_current_protocol_id) ==
== PROTOCOL_STATE_TERMINATED) // we know the server address PROTOCOL_STATE_TERMINATED) // we know the server address
{ {
Log::info("ConnectToServer", "Server's address known"); Log::info("ConnectToServer", "Server's address known");
// we're in the same lan (same public ip address) !! // we're in the same lan (same public ip address) !!
if (m_server_address.getIP() == if (m_server_address.getIP() ==
NetworkManager::getInstance()->getPublicAddress().getIP()) NetworkManager::getInstance()->getPublicAddress().getIP())
{
Log::info("ConnectToServer", Log::info("ConnectToServer",
"Server appears to be in the same LAN."); "Server appears to be in the same LAN.");
}
m_state = REQUESTING_CONNECTION; m_state = REQUESTING_CONNECTION;
m_current_protocol_id = m_current_protocol_id =
m_listener->requestStart(new RequestConnection(m_server_id)); m_listener->requestStart(
new RequestConnection(m_server_id));
} }
break; break;
case REQUESTING_CONNECTION: case REQUESTING_CONNECTION:
if (m_listener->getProtocolState(m_current_protocol_id) if (m_listener->getProtocolState(m_current_protocol_id) ==
== PROTOCOL_STATE_TERMINATED) // server knows we wanna connect PROTOCOL_STATE_TERMINATED)
{ {
// Server knows we want to connect
Log::info("ConnectToServer", "Connection request made"); Log::info("ConnectToServer", "Connection request made");
if (m_server_address.getIP() == 0 || if (m_server_address.getIP() == 0 ||
m_server_address.getPort() == 0 ) m_server_address.getPort() == 0 )
{ // server data not correct, hide address and stop {
// server data not correct, hide address and stop
m_state = HIDING_ADDRESS; m_state = HIDING_ADDRESS;
Log::error("ConnectToServer", "Server address is %s", Log::error("ConnectToServer", "Server address is %s",
m_server_address.toString().c_str()); m_server_address.toString().c_str());
m_current_protocol_id = m_listener->requestStart(new HidePublicAddress()); m_current_protocol_id =
m_listener->requestStart(new HidePublicAddress());
return; return;
} }
// we're in the same lan (same public ip address) !! if (m_server_address.getIP() == NetworkManager::getInstance()
if (m_server_address.getIP() == ->getPublicAddress().getIP())
NetworkManager::getInstance()->getPublicAddress().getIP())
{ {
// just send a broadcast packet, the client will know our ip address and will connect // we're in the same lan (same public ip address) !!
handleSameLAN();
}
else
{
m_state = CONNECTING;
m_current_protocol_id = m_listener->requestStart(
new PingProtocol(m_server_address, 2.0));
}
}
break;
case CONNECTING: // waiting the server to answer our connection
{
static double timer = 0;
if (StkTime::getRealTime() > timer+5.0) // every 5 seconds
{
timer = StkTime::getRealTime();
NetworkManager::getInstance()->connect(m_server_address);
Log::info("ConnectToServer", "Trying to connect to %s",
m_server_address.toString().c_str());
}
break;
}
case CONNECTED:
{
Log::info("ConnectToServer", "Connected");
// Kill the ping protocol because we're connected
m_listener->requestTerminate(
m_listener->getProtocol(m_current_protocol_id));
m_current_protocol_id =
m_listener->requestStart(new HidePublicAddress());
ClientNetworkManager::getInstance()->setConnected(true);
m_state = HIDING_ADDRESS;
break;
}
case HIDING_ADDRESS:
if (m_listener->getProtocolState(m_current_protocol_id)
== PROTOCOL_STATE_TERMINATED) // we have hidden our address
{
Log::info("ConnectToServer", "Address hidden");
m_state = DONE;
// lobby room protocol if we're connected only
if (ClientNetworkManager::getInstance()->isConnected())
{
m_listener->requestStart(
new ClientLobbyRoomProtocol(m_server_address));
}
}
break;
case DONE:
m_listener->requestTerminate(this);
m_state = EXITING;
break;
case EXITING:
break;
}
}
// ----------------------------------------------------------------------------
/** Called when the server is on the same LAN. It uses broadcast to
* find and conntect to the server.
*/
void ConnectToServer::handleSameLAN()
{
// just send a broadcast packet, the client will know our
// ip address and will connect
STKHost* host = NetworkManager::getInstance()->getHost(); STKHost* host = NetworkManager::getInstance()->getHost();
host->stopListening(); // stop the listening host->stopListening(); // stop the listening
TransportAddress sender;
TransportAddress broadcast_address; TransportAddress broadcast_address;
broadcast_address.setIP(-1); // 255.255.255.255 broadcast_address.setIP(-1); // 255.255.255.255
broadcast_address.setPort(7321); // 0b10101100000101101101111111111111; // for test broadcast_address.setPort(7321);
char data2[] = "aloha_stk\0"; char data2[] = "aloha_stk\0";
host->sendRawPacket((uint8_t*)(data2), 10, broadcast_address); host->sendRawPacket((uint8_t*)(data2), 10, broadcast_address);
Log::info("ConnectToServer", "Waiting broadcast message."); Log::info("ConnectToServer", "Waiting broadcast message.");
const uint8_t* received_data = host->receiveRawPacket(&sender); // get the sender
TransportAddress sender;
// get the sender
const uint8_t* received_data = host->receiveRawPacket(&sender);
host->startListening(); // start listening again host->startListening(); // start listening again
const char data[] = "aloha_stk\0"; const char data[] = "aloha_stk\0";
@ -184,7 +262,8 @@ void ConnectToServer::asynchronousUpdate()
Log::info("ConnectToServer", "LAN Server found : %s", Log::info("ConnectToServer", "LAN Server found : %s",
sender.toString().c_str()); sender.toString().c_str());
#ifndef WIN32 #ifndef WIN32
// just check if the ip is ours : if so, then just use localhost (127.0.0.1) // just check if the ip is ours : if so,
// then just use localhost (127.0.0.1)
struct ifaddrs *ifap, *ifa; struct ifaddrs *ifap, *ifa;
struct sockaddr_in *sa; struct sockaddr_in *sa;
getifaddrs(&ifap); // get the info getifaddrs(&ifap); // get the info
@ -238,53 +317,4 @@ void ConnectToServer::asynchronousUpdate()
m_server_address.copy(sender); m_server_address.copy(sender);
m_state = CONNECTING; m_state = CONNECTING;
} }
} } // handleSameLAN
else
{
m_state = CONNECTING;
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_server_address, 2.0));
}
}
break;
case CONNECTING: // waiting the server to answer our connection
{
static double timer = 0;
if (StkTime::getRealTime() > timer+5.0) // every 5 seconds
{
timer = StkTime::getRealTime();
NetworkManager::getInstance()->connect(m_server_address);
Log::info("ConnectToServer", "Trying to connect to %s",
m_server_address.toString().c_str());
}
break;
}
case CONNECTED:
{
Log::info("ConnectToServer", "Connected");
m_listener->requestTerminate( m_listener->getProtocol(m_current_protocol_id)); // kill the ping protocol because we're connected
m_current_protocol_id = m_listener->requestStart(new HidePublicAddress());
ClientNetworkManager::getInstance()->setConnected(true);
m_state = HIDING_ADDRESS;
break;
}
case HIDING_ADDRESS:
if (m_listener->getProtocolState(m_current_protocol_id)
== PROTOCOL_STATE_TERMINATED) // we have hidden our address
{
Log::info("ConnectToServer", "Address hidden");
m_state = DONE;
if (ClientNetworkManager::getInstance()->isConnected()) // lobby room protocol if we're connected only
m_listener->requestStart(new ClientLobbyRoomProtocol(m_server_address));
}
break;
case DONE:
m_listener->requestTerminate(this);
m_state = EXITING;
break;
case EXITING:
break;
}
}
// ----------------------------------------------------------------------------

View File

@ -21,28 +21,19 @@
#include "network/protocol.hpp" #include "network/protocol.hpp"
#include "network/types.hpp" #include "network/types.hpp"
#include "utils/cpp2011.hpp"
#include <string> #include <string>
class ConnectToServer : public Protocol, public CallbackObject class ConnectToServer : public Protocol, public CallbackObject
{ {
public: private:
ConnectToServer(); //!< Quick join
ConnectToServer(uint32_t server_id, uint32_t host_id); //!< Specify server id
virtual ~ConnectToServer();
virtual bool notifyEventAsynchronous(Event* event);
virtual void setup();
virtual void update() {}
virtual void asynchronousUpdate();
protected:
TransportAddress m_server_address; TransportAddress m_server_address;
uint32_t m_server_id; uint32_t m_server_id;
uint32_t m_host_id; uint32_t m_host_id;
uint32_t m_current_protocol_id; uint32_t m_current_protocol_id;
bool m_quick_join; bool m_quick_join;
enum STATE enum State
{ {
NONE, NONE,
GETTING_SELF_ADDRESS, GETTING_SELF_ADDRESS,
@ -55,7 +46,21 @@ class ConnectToServer : public Protocol, public CallbackObject
DONE, DONE,
EXITING EXITING
}; };
STATE m_state; /** State for finite state machine. */
}; State m_state;
void handleSameLAN();
public:
ConnectToServer();
ConnectToServer(uint32_t server_id, uint32_t host_id);
virtual ~ConnectToServer();
virtual bool notifyEventAsynchronous(Event* event) OVERRIDE;
virtual void setup() OVERRIDE;
virtual void asynchronousUpdate();
virtual void update() OVERRIDE {}
}; // class ConnectToServer
#endif // CONNECT_TO_SERVER_HPP #endif // CONNECT_TO_SERVER_HPP

View File

@ -2,6 +2,9 @@
#include "modes/world.hpp" #include "modes/world.hpp"
#include "karts/abstract_kart.hpp" #include "karts/abstract_kart.hpp"
#include "karts/controller/controller.hpp"
#include "network/event.hpp"
#include "network/game_setup.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "network/network_world.hpp" #include "network/network_world.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
@ -63,7 +66,7 @@ void ControllerEventsProtocol::setup()
bool ControllerEventsProtocol::notifyEventAsynchronous(Event* event) bool ControllerEventsProtocol::notifyEventAsynchronous(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() < 17) if (data.size() < 17)
{ {
Log::error("ControllerEventsProtocol", "The data supplied was not complete. Size was %d.", data.size()); Log::error("ControllerEventsProtocol", "The data supplied was not complete. Size was %d.", data.size());

View File

@ -4,7 +4,9 @@
#include "network/protocol.hpp" #include "network/protocol.hpp"
#include "input/input.hpp" #include "input/input.hpp"
#include "karts/controller/controller.hpp"
class Controller;
class STKPeer;
class ControllerEventsProtocol : public Protocol class ControllerEventsProtocol : public Protocol
{ {

View File

@ -6,7 +6,10 @@
#include "items/item_manager.hpp" #include "items/item_manager.hpp"
#include "items/powerup.hpp" #include "items/powerup.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "network/event.hpp"
#include "network/game_setup.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include <stdint.h> #include <stdint.h>
GameEventsProtocol::GameEventsProtocol() : Protocol(NULL, PROTOCOL_GAME_EVENTS) GameEventsProtocol::GameEventsProtocol() : Protocol(NULL, PROTOCOL_GAME_EVENTS)
@ -21,7 +24,7 @@ bool GameEventsProtocol::notifyEvent(Event* event)
{ {
if (event->getType() != EVENT_TYPE_MESSAGE) if (event->getType() != EVENT_TYPE_MESSAGE)
return true; return true;
NetworkString data = event->data(); NetworkString &data = event->data();
if (data.size() < 5) // for token and type if (data.size() < 5) // for token and type
{ {
Log::warn("GameEventsProtocol", "Too short message."); Log::warn("GameEventsProtocol", "Too short message.");

View File

@ -23,6 +23,8 @@
#include <string> #include <string>
class STKHost;
class GetPublicAddress : public Protocol class GetPublicAddress : public Protocol
{ {
public: public:

View File

@ -2,8 +2,9 @@
#include "karts/abstract_kart.hpp" #include "karts/abstract_kart.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "network/protocol_manager.hpp" #include "network/event.hpp"
#include "network/network_world.hpp" #include "network/network_world.hpp"
#include "network/protocol_manager.hpp"
#include "utils/time.hpp" #include "utils/time.hpp"
KartUpdateProtocol::KartUpdateProtocol() KartUpdateProtocol::KartUpdateProtocol()
@ -33,7 +34,7 @@ bool KartUpdateProtocol::notifyEventAsynchronous(Event* event)
{ {
if (event->getType() != EVENT_TYPE_MESSAGE) if (event->getType() != EVENT_TYPE_MESSAGE)
return true; return true;
NetworkString ns = event->data(); NetworkString &ns = event->data();
if (ns.size() < 36) if (ns.size() < 36)
{ {
Log::info("KartUpdateProtocol", "Message too short."); Log::info("KartUpdateProtocol", "Message too short.");

View File

@ -4,7 +4,9 @@
#include "network/protocol.hpp" #include "network/protocol.hpp"
#include "utils/vec3.hpp" #include "utils/vec3.hpp"
#include "LinearMath/btQuaternion.h" #include "LinearMath/btQuaternion.h"
#include <list> #include <list>
#include "pthread.h"
class AbstractKart; class AbstractKart;

View File

@ -21,6 +21,7 @@
#include "config/player_manager.hpp" #include "config/player_manager.hpp"
#include "config/user_config.hpp" #include "config/user_config.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "network/event.hpp"
#include "network/network_world.hpp" #include "network/network_world.hpp"
#include "network/protocols/get_public_address.hpp" #include "network/protocols/get_public_address.hpp"
#include "network/protocols/show_public_address.hpp" #include "network/protocols/show_public_address.hpp"
@ -65,7 +66,7 @@ bool ServerLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
assert(m_setup); // assert that the setup exists assert(m_setup); // assert that the setup exists
if (event->getType() == EVENT_TYPE_MESSAGE) if (event->getType() == EVENT_TYPE_MESSAGE)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
assert(data.size()); // message not empty assert(data.size()); // message not empty
uint8_t message_type; uint8_t message_type;
message_type = data[0]; message_type = data[0];
@ -335,7 +336,7 @@ void ServerLobbyRoomProtocol::kartDisconnected(Event* event)
void ServerLobbyRoomProtocol::connectionRequested(Event* event) void ServerLobbyRoomProtocol::connectionRequested(Event* event)
{ {
STKPeer* peer = event->getPeer(); STKPeer* peer = event->getPeer();
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() != 5 || data[0] != 4) if (data.size() != 5 || data[0] != 4)
{ {
Log::warn("ServerLobbyRoomProtocol", "Receiving badly formated message. Size is %d and first byte %d", data.size(), data[0]); Log::warn("ServerLobbyRoomProtocol", "Receiving badly formated message. Size is %d and first byte %d", data.size(), data[0]);
@ -414,7 +415,7 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
*/ */
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event) void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
STKPeer* peer = event->getPeer(); STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 6)) if (!checkDataSizeAndToken(event, 6))
return; return;
@ -475,7 +476,7 @@ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
*/ */
void ServerLobbyRoomProtocol::playerMajorVote(Event* event) void ServerLobbyRoomProtocol::playerMajorVote(Event* event)
{ {
NetworkString data = event->data(); NetworkString &data = event->data();
STKPeer* peer = event->getPeer(); STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 7)) if (!checkDataSizeAndToken(event, 7))
return; return;
@ -506,7 +507,7 @@ void ServerLobbyRoomProtocol::playerMajorVote(Event* event)
*/ */
void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event) void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event)
{ {
NetworkString data = event->data(); NetworkString &data = event->data();
STKPeer* peer = event->getPeer(); STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 7)) if (!checkDataSizeAndToken(event, 7))
return; return;
@ -537,7 +538,7 @@ void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event)
*/ */
void ServerLobbyRoomProtocol::playerMinorVote(Event* event) void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
{ {
NetworkString data = event->data(); NetworkString &data = event->data();
STKPeer* peer = event->getPeer(); STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 7)) if (!checkDataSizeAndToken(event, 7))
return; return;
@ -568,7 +569,7 @@ void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
*/ */
void ServerLobbyRoomProtocol::playerTrackVote(Event* event) void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
{ {
NetworkString data = event->data(); NetworkString &data = event->data();
STKPeer* peer = event->getPeer(); STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 8)) if (!checkDataSizeAndToken(event, 8))
return; return;
@ -601,7 +602,7 @@ void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
*/ */
void ServerLobbyRoomProtocol::playerReversedVote(Event* event) void ServerLobbyRoomProtocol::playerReversedVote(Event* event)
{ {
NetworkString data = event->data(); NetworkString &data = event->data();
STKPeer* peer = event->getPeer(); STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 9)) if (!checkDataSizeAndToken(event, 9))
return; return;
@ -634,7 +635,7 @@ void ServerLobbyRoomProtocol::playerReversedVote(Event* event)
*/ */
void ServerLobbyRoomProtocol::playerLapsVote(Event* event) void ServerLobbyRoomProtocol::playerLapsVote(Event* event)
{ {
NetworkString data = event->data(); NetworkString &data = event->data();
STKPeer* peer = event->getPeer(); STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 9)) if (!checkDataSizeAndToken(event, 9))
return; return;

View File

@ -34,7 +34,6 @@ class ServerLobbyRoomProtocol : public LobbyRoomProtocol
void playerLapsVote(Event* event); void playerLapsVote(Event* event);
uint8_t m_next_id; //!< Next id to assign to a peer. uint8_t m_next_id; //!< Next id to assign to a peer.
std::vector<TransportAddress> m_peers;
std::vector<uint32_t> m_incoming_peers_ids; std::vector<uint32_t> m_incoming_peers_ids;
uint32_t m_current_protocol_id; uint32_t m_current_protocol_id;
bool m_selection_enabled; bool m_selection_enabled;

View File

@ -6,10 +6,11 @@
#include "input/input_manager.hpp" #include "input/input_manager.hpp"
#include "challenges/unlock_manager.hpp" #include "challenges/unlock_manager.hpp"
#include "modes/world.hpp" #include "modes/world.hpp"
#include "network/network_manager.hpp" #include "network/event.hpp"
#include "network/protocol_manager.hpp"
#include "network/game_setup.hpp" #include "network/game_setup.hpp"
#include "network/network_manager.hpp"
#include "network/network_world.hpp" #include "network/network_world.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/synchronization_protocol.hpp" #include "network/protocols/synchronization_protocol.hpp"
#include "online/online_profile.hpp" #include "online/online_profile.hpp"
#include "race/race_manager.hpp" #include "race/race_manager.hpp"
@ -36,7 +37,7 @@ StartGameProtocol::~StartGameProtocol()
bool StartGameProtocol::notifyEventAsynchronous(Event* event) bool StartGameProtocol::notifyEventAsynchronous(Event* event)
{ {
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() < 5) if (data.size() < 5)
{ {
Log::error("StartGameProtocol", "Too short message."); Log::error("StartGameProtocol", "Too short message.");

View File

@ -1,5 +1,6 @@
#include "network/protocols/synchronization_protocol.hpp" #include "network/protocols/synchronization_protocol.hpp"
#include "network/event.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "network/protocols/kart_update_protocol.hpp" #include "network/protocols/kart_update_protocol.hpp"
#include "network/protocols/controller_events_protocol.hpp" #include "network/protocols/controller_events_protocol.hpp"
@ -35,7 +36,7 @@ bool SynchronizationProtocol::notifyEventAsynchronous(Event* event)
{ {
if (event->getType() != EVENT_TYPE_MESSAGE) if (event->getType() != EVENT_TYPE_MESSAGE)
return true; return true;
NetworkString data = event->data(); const NetworkString &data = event->data();
if (data.size() < 10) if (data.size() < 10)
{ {
Log::warn("SynchronizationProtocol", "Received a message too short."); Log::warn("SynchronizationProtocol", "Received a message too short.");

View File

@ -111,7 +111,7 @@ void ServerNetworkManager::run()
Log::info("ServerNetworkManager", "Host initialized."); Log::info("ServerNetworkManager", "Host initialized.");
// listen keyboard console input // listen keyboard console input
m_thread_keyboard = (pthread_t*)(malloc(sizeof(pthread_t))); m_thread_keyboard = new pthread_t;
pthread_create(m_thread_keyboard, NULL, waitInput2, NULL); pthread_create(m_thread_keyboard, NULL, waitInput2, NULL);
NetworkManager::run(); NetworkManager::run();

View File

@ -20,6 +20,7 @@
#include "config/user_config.hpp" #include "config/user_config.hpp"
#include "io/file_manager.hpp" #include "io/file_manager.hpp"
#include "network/event.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
#include "utils/time.hpp" #include "utils/time.hpp"
@ -178,12 +179,19 @@ void* STKHost::mainLoop(void* self)
{ {
while (enet_host_service(host, &event, 20) != 0) while (enet_host_service(host, &event, 20) != 0)
{ {
if (event.type == ENET_EVENT_TYPE_NONE)
continue;
// Create an STKEvent with the event data
Event* stk_event = new Event(&event); Event* stk_event = new Event(&event);
if (stk_event->getType() == EVENT_TYPE_MESSAGE) if (stk_event->getType() == EVENT_TYPE_MESSAGE)
logPacket(stk_event->data(), true); logPacket(stk_event->data(), true);
if (event.type != ENET_EVENT_TYPE_NONE)
NetworkManager::getInstance()->notifyEvent(stk_event); // The event is forwarded to the NetworkManger and from there
delete stk_event; // there to the ProtocolManager. The ProtocolManager is
// responsible for freeing the memory.
NetworkManager::getInstance()->propagateEvent(stk_event);
} // while enet_host_service } // while enet_host_service
} // while !mustStopListening } // while !mustStopListening
@ -372,7 +380,7 @@ uint8_t* STKHost::receiveRawPacket(const TransportAddress& sender,
} }
if (addr.sin_family == AF_INET) if (addr.sin_family == AF_INET)
{ {
TransportAddress a(addr.sin_addr.s_addr); TransportAddress a(ntohl(addr.sin_addr.s_addr));
Log::info("STKHost", "IPv4 Address of the sender was %s", Log::info("STKHost", "IPv4 Address of the sender was %s",
a.toString(false).c_str()); a.toString(false).c_str());
} }

View File

@ -18,50 +18,38 @@
#include "network/stk_peer.hpp" #include "network/stk_peer.hpp"
#include "network/network_manager.hpp" #include "network/network_manager.hpp"
#include "network/game_setup.hpp"
#include "network/network_string.hpp"
#include "utils/log.hpp" #include "utils/log.hpp"
#include <string.h> #include <string.h>
/** Constructor for an empty peer.
*/
STKPeer::STKPeer() STKPeer::STKPeer()
{ {
m_peer = NULL; m_enet_peer = NULL;
m_player_profile = new NetworkPlayerProfile*; m_player_profile = NULL;
*m_player_profile = NULL; m_client_server_token = 0;
m_client_server_token = new uint32_t; m_token_set = false;
*m_client_server_token = 0; } // STKPeer
m_token_set = new bool;
*m_token_set = false;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Destructor.
STKPeer::STKPeer(const STKPeer& peer) */
{
m_peer = peer.m_peer;
m_player_profile = peer.m_player_profile;
m_client_server_token = peer.m_client_server_token;
m_token_set = peer.m_token_set;
}
//-----------------------------------------------------------------------------
STKPeer::~STKPeer() STKPeer::~STKPeer()
{ {
if (m_peer) if (m_enet_peer)
m_peer = NULL; m_enet_peer = NULL;
if (m_player_profile) if (m_player_profile)
delete m_player_profile; delete m_player_profile;
m_player_profile = NULL; m_player_profile = NULL;
if (m_client_server_token) m_client_server_token = 0;
delete m_client_server_token; } // ~STKPeer
m_client_server_token = NULL;
if (m_token_set)
delete m_token_set;
m_token_set = NULL;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Connect to the specified host.
*/
bool STKPeer::connectToHost(STKHost* localhost, const TransportAddress &host, bool STKPeer::connectToHost(STKHost* localhost, const TransportAddress &host,
uint32_t channel_count, uint32_t data) uint32_t channel_count, uint32_t data)
{ {
@ -76,70 +64,70 @@ bool STKPeer::connectToHost(STKHost* localhost, const TransportAddress &host,
TransportAddress a(peer->address); TransportAddress a(peer->address);
Log::verbose("STKPeer", "Connecting to %s", a.toString().c_str()); Log::verbose("STKPeer", "Connecting to %s", a.toString().c_str());
return true; return true;
} } // connectToHost
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Disconnect from the server.
*/
void STKPeer::disconnect() void STKPeer::disconnect()
{ {
enet_peer_disconnect(m_peer, 0); enet_peer_disconnect(m_enet_peer, 0);
} } // disconnect
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Sends a packet to this host.
* \param data The data to send.
* \param reliable If the data is sent reliable or not.
*/
void STKPeer::sendPacket(NetworkString const& data, bool reliable) void STKPeer::sendPacket(NetworkString const& data, bool reliable)
{ {
TransportAddress a(m_peer->address); TransportAddress a(m_enet_peer->address);
Log::verbose("STKPeer", "sending packet of size %d to %s", Log::verbose("STKPeer", "sending packet of size %d to %s",
a.toString().c_str()); a.toString().c_str());
ENetPacket* packet = enet_packet_create(data.getBytes(), data.size() + 1, ENetPacket* packet = enet_packet_create(data.getBytes(), data.size() + 1,
(reliable ? ENET_PACKET_FLAG_RELIABLE : ENET_PACKET_FLAG_UNSEQUENCED)); (reliable ? ENET_PACKET_FLAG_RELIABLE
/* to debug the packet output : ENET_PACKET_FLAG_UNSEQUENCED));
printf("STKPeer: "); enet_peer_send(m_enet_peer, 0, packet);
for (unsigned int i = 0; i < data.size(); i++) } // sendPacket
{
printf("%d ", (uint8_t)(data[i]));
}
printf("\n");
*/
enet_peer_send(m_peer, 0, packet);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Returns the IP address (in host format) of this client.
*/
uint32_t STKPeer::getAddress() const uint32_t STKPeer::getAddress() const
{ {
return ntohl(m_peer->address.host); return ntohl(m_enet_peer->address.host);
} } // getAddress
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Returns the port of this peer.
*/
uint16_t STKPeer::getPort() const uint16_t STKPeer::getPort() const
{ {
return m_peer->address.port; return m_enet_peer->address.port;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/** Returns if the peer is connected or not.
*/
bool STKPeer::isConnected() const bool STKPeer::isConnected() const
{ {
Log::info("STKPeer", "The peer state is %i", m_peer->state); Log::info("STKPeer", "The peer state is %i", m_enet_peer->state);
return (m_peer->state == ENET_PEER_STATE_CONNECTED); return (m_enet_peer->state == ENET_PEER_STATE_CONNECTED);
} } // isConnected
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool STKPeer::exists() const bool STKPeer::exists() const
{ {
return (m_peer != NULL); // assert that the peer exists return (m_enet_peer != NULL); // assert that the peer exists
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
bool STKPeer::isSamePeer(const STKPeer* peer) const bool STKPeer::isSamePeer(const STKPeer* peer) const
{ {
return peer->m_peer==m_peer; return peer->m_enet_peer==m_enet_peer;
} }
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------

View File

@ -23,49 +23,76 @@
#ifndef STK_PEER_HPP #ifndef STK_PEER_HPP
#define STK_PEER_HPP #define STK_PEER_HPP
#include "network/stk_host.hpp" #include "utils/no_copy.hpp"
#include "network/network_string.hpp" #include "utils/types.hpp"
#include "network/game_setup.hpp"
#include <enet/enet.h> #include <enet/enet.h>
class NetworkPlayerProfile;
class NetworkString;
class STKHost;
class TransportAddress;
/*! \class STKPeer /*! \class STKPeer
* \brief Represents a peer. * \brief Represents a peer.
* This class is used to interface the ENetPeer structure. * This class is used to interface the ENetPeer structure.
*/ */
class STKPeer class STKPeer : public NoCopy
{ {
friend class Event; friend class Event;
protected: protected:
ENetPeer* m_peer; /** Pointer to the corresponding ENet peer data structure. */
NetworkPlayerProfile** m_player_profile; ENetPeer* m_enet_peer;
uint32_t *m_client_server_token;
bool *m_token_set; NetworkPlayerProfile* m_player_profile;
/** The token of this client. */
uint32_t m_client_server_token;
/** True if the token for this peer has been set. */
bool m_token_set;
public: public:
STKPeer(); STKPeer();
STKPeer(const STKPeer& peer);
virtual ~STKPeer(); virtual ~STKPeer();
virtual void sendPacket(const NetworkString& data, bool reliable = true); virtual void sendPacket(const NetworkString& data, bool reliable = true);
static bool connectToHost(STKHost* localhost, const TransportAddress& host, static bool connectToHost(STKHost* localhost, const TransportAddress& host,
uint32_t channel_count, uint32_t data); uint32_t channel_count, uint32_t data);
void disconnect(); void disconnect();
void setClientServerToken(const uint32_t& token) { *m_client_server_token = token; *m_token_set = true; }
void unsetClientServerToken() { *m_token_set = false; }
void setPlayerProfile(NetworkPlayerProfile* profile) { *m_player_profile = profile; }
void setPlayerProfilePtr(NetworkPlayerProfile** profile) { m_player_profile = profile; }
bool isConnected() const; bool isConnected() const;
bool exists() const; bool exists() const;
uint32_t getAddress() const; uint32_t getAddress() const;
uint16_t getPort() const; uint16_t getPort() const;
NetworkPlayerProfile* getPlayerProfile() { return (m_player_profile)?(*m_player_profile):NULL; }
uint32_t getClientServerToken() const { return *m_client_server_token; }
bool isClientServerTokenSet() const { return *m_token_set; }
bool isSamePeer(const STKPeer* peer) const; bool isSamePeer(const STKPeer* peer) const;
// ------------------------------------------------------------------------
/** Sets the token for this client. */
void setClientServerToken(const uint32_t& token)
{
m_client_server_token = token;
m_token_set = true;
} // setClientServerToken
// ------------------------------------------------------------------------
void unsetClientServerToken() { m_token_set = false; }
// ------------------------------------------------------------------------
void setPlayerProfile(NetworkPlayerProfile* profile)
{
m_player_profile = profile;
} // setPlayerProfile
// ------------------------------------------------------------------------
/** Returns the player profile of this peer. */
NetworkPlayerProfile* getPlayerProfile()
{
return m_player_profile;
} // getPlayerProfile
// ------------------------------------------------------------------------
/** Returns the token of this client. */
uint32_t getClientServerToken() const { return m_client_server_token; }
// ------------------------------------------------------------------------
/** Returns if the token for this client is known. */
bool isClientServerTokenSet() const { return m_token_set; }
}; // STKPeer }; // STKPeer
#endif // STK_PEER_HPP #endif // STK_PEER_HPP

View File

@ -305,6 +305,7 @@ void RaceManager::startNew(bool from_overworld)
->getActivePlayerProfile(0) ->getActivePlayerProfile(0)
->getUniqueID(), ->getUniqueID(),
m_grand_prix.getId(), m_grand_prix.getId(),
m_minor_mode,
m_player_karts.size()); m_player_karts.size());
// Saved GP only in offline mode // Saved GP only in offline mode
@ -398,6 +399,7 @@ void RaceManager::startNew(bool from_overworld)
->getActivePlayerProfile(0) ->getActivePlayerProfile(0)
->getUniqueID(), ->getUniqueID(),
m_grand_prix.getId(), m_grand_prix.getId(),
m_minor_mode,
m_player_karts.size()); m_player_karts.size());
} }
} }
@ -551,6 +553,7 @@ void RaceManager::saveGP()
m_saved_gp = new SavedGrandPrix( m_saved_gp = new SavedGrandPrix(
StateManager::get()->getActivePlayerProfile(0)->getUniqueID(), StateManager::get()->getActivePlayerProfile(0)->getUniqueID(),
m_grand_prix.getId(), m_grand_prix.getId(),
m_minor_mode,
m_difficulty, m_difficulty,
(int)m_player_karts.size(), (int)m_player_karts.size(),
m_track_number, m_track_number,

View File

@ -205,6 +205,7 @@ void GPInfoDialog::addButtons()
->getActivePlayerProfile(0) ->getActivePlayerProfile(0)
->getUniqueID(), ->getUniqueID(),
m_gp.getId(), m_gp.getId(),
race_manager->getMinorMode(),
race_manager->getNumLocalPlayers()); race_manager->getNumLocalPlayers());
okBtn->m_properties[PROP_ID] = "start"; okBtn->m_properties[PROP_ID] = "start";

View File

@ -134,6 +134,7 @@ void GPInfoScreen::beforeAddingWidget()
SavedGrandPrix* saved_gp = SavedGrandPrix::getSavedGP( SavedGrandPrix* saved_gp = SavedGrandPrix::getSavedGP(
StateManager::get()->getActivePlayerProfile(0)->getUniqueID(), StateManager::get()->getActivePlayerProfile(0)->getUniqueID(),
m_gp.getId(), m_gp.getId(),
race_manager->getMinorMode(),
race_manager->getNumLocalPlayers()); race_manager->getNumLocalPlayers());
int tracks = m_gp.getTrackNames().size(); int tracks = m_gp.getTrackNames().size();