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,
const std::string &gp_id,
RaceManager::MinorRaceModeType race_type,
RaceManager::Difficulty difficulty,
int player_karts,
int last_track,
@ -74,6 +75,7 @@ SavedGrandPrix::SavedGrandPrix(unsigned int player_id,
"Represents the saved state of a GP"),
m_player_id(player_id, "player_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_player_karts(player_karts,"player_karts", &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"),
m_player_id (0, "player_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_player_karts(0,"player_karts", &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_id. findYourDataInAnAttributeOf(node);
m_gp_id. findYourDataInAnAttributeOf(node);
m_race_type. findYourDataInAnAttributeOf(node);
m_difficulty. findYourDataInAnAttributeOf(node);
m_player_karts.findYourDataInAnAttributeOf(node);
m_next_track. findYourDataInAnAttributeOf(node);

View File

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

View File

@ -27,6 +27,7 @@
#include "graphics/shaders.hpp"
#include "io/file_manager.hpp"
#include "io/xml_node.hpp"
#include "modes/profile_world.hpp"
#include "modes/world.hpp"
#include "tracks/track.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?
// 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);
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);
//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);
else
default_material->setShaderType(Material::SHADERTYPE_SOLID);

View File

@ -690,7 +690,8 @@ EventPropagation RibbonWidget::transmitEvent(Widget* w,
// bring focus back to enclosing ribbon widget
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)
{

View File

@ -64,6 +64,7 @@ namespace irr {
std::vector<std::string> FileManager::m_root_dirs;
std::string FileManager::m_stdout_filename = "stdout.log";
#ifdef __APPLE__
// dynamic data path detection onmac
@ -1044,6 +1045,15 @@ std::string FileManager::checkAndCreateLinuxDir(const char *env_name,
} // checkAndCreateLinuxDir
#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
* 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
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--)
{
std::ostringstream out_old;

View File

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

View File

@ -1252,6 +1252,8 @@ void Kart::update(float dt)
{
m_body->getBroadphaseHandle()->m_collisionFilterGroup = old_group;
}
PROFILER_PUSH_CPU_MARKER("Kart::Update (material)", 0x60, 0x34, 0x7F);
handleMaterialGFX();
const Material* material=m_terrain_info->getMaterial();
if (!material) // kart falling off the track
@ -1309,6 +1311,7 @@ void Kart::update(float dt)
#endif
}
} // if there is material
PROFILER_POP_CPU_MARKER();
// 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)

View File

@ -1265,9 +1265,9 @@ int main(int argc, char *argv[] )
handleCmdLineOutputModifier();
if(CommandLine::has("--root", &s))
{
FileManager::addRootDirs(s);
}
if (CommandLine::has("--stdout", &s))
FileManager::setStdoutName(s);
// Init the minimum managers so that user config exists, then
// 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);
}
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();
for (int i = 0 ; i < kart_amount; ++i)
{

View File

@ -62,7 +62,7 @@ Event::Event(ENetEvent* event)
m_peer = NULL;
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];
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
{
STKPeer* new_peer = new STKPeer();
new_peer->m_peer = event->peer;
new_peer->m_enet_peer = event->peer;
m_peer = new_peer;
Log::debug("Event",
"Creating a new peer, address are STKPeer:%p, Peer:%p",
@ -81,18 +81,6 @@ Event::Event(ENetEvent* event)
}
} // 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.
*/

View File

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

View File

@ -18,14 +18,9 @@
#include "network/network_manager.hpp"
#include "network/protocols/hide_public_address.hpp"
#include "network/protocols/show_public_address.hpp"
#include "network/protocols/get_public_address.hpp"
#include "network/event.hpp"
#include "network/game_setup.hpp"
#include "network/protocol_manager.hpp"
#include "network/client_network_manager.hpp"
#include "network/server_network_manager.hpp"
#include "utils/log.hpp"
#include <pthread.h>
@ -58,6 +53,8 @@ NetworkManager::~NetworkManager()
} // ~Networkmanager
//----------------------------------------------------------------------------
/** \brief Function to start the Network Manager (start threads).
*/
void NetworkManager::run()
{
// create the protocol manager
@ -65,6 +62,9 @@ void NetworkManager::run()
} // run
//-----------------------------------------------------------------------------
/** \brief Function to reset the Network Manager.
* This function resets the peers and the listening host.
*/
void NetworkManager::reset()
{
if (m_localhost)
@ -78,6 +78,10 @@ void NetworkManager::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()
{
m_localhost->stopListening();
@ -88,17 +92,25 @@ void NetworkManager::abort()
} // abort
//-----------------------------------------------------------------------------
bool NetworkManager::connect(const TransportAddress& peer)
/** \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.
*/
bool NetworkManager::connect(const TransportAddress& address)
{
if (peerExists(peer))
return isConnectedTo(peer);
if (peerExists(address))
return isConnectedTo(address);
return STKPeer::connectToHost(m_localhost, peer, 2, 0);
return STKPeer::connectToHost(m_localhost, address, 2, 0);
} // 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)
{
if (manual)
@ -108,7 +120,13 @@ void NetworkManager::setManualSocketsMode(bool manual)
} // 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",
(int)(event->getType()));
@ -135,8 +153,8 @@ void NetworkManager::notifyEvent(Event* event)
}
// notify for the event now.
ProtocolManager::getInstance()->notifyEvent(event);
} // notifyEvent
ProtocolManager::getInstance()->propagateEvent(event);
} // propagateEvent
//-----------------------------------------------------------------------------
@ -163,18 +181,20 @@ void NetworkManager::sendPacketExcept(STKPeer* peer, const NetworkString& data,
} // sendPacketExcept
//-----------------------------------------------------------------------------
/** A previous GameSetup is deletea and a new one is created.
* \return Newly create GameSetup object.
*/
GameSetup* NetworkManager::setupNewGame()
{
if (m_game_setup)
delete m_game_setup;
m_game_setup = NULL;
m_game_setup = new GameSetup();
return m_game_setup;
} // setupNewGame
//-----------------------------------------------------------------------------
/** Called when you leave a server.
*/
void NetworkManager::disconnected()
{
// delete the game setup
@ -248,15 +268,3 @@ void NetworkManager::removePeer(STKPeer* peer)
} // 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/types.hpp"
#include "network/event.hpp"
#include "network/game_setup.hpp"
#include "utils/singleton.hpp"
#include "utils/synchronised.hpp"
#include <vector>
class Event;
class GameSetup;
/** \class NetworkManager
* \brief Gives the general functions to use network communication.
* This class is in charge of storing the peers connected to this host.
@ -46,98 +47,93 @@
*/
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>;
public:
/** \brief Function to start the Network Manager (start threads) */
virtual void run();
/** \brief Function to reset the Network Manager.
* This function resets the peers and the listening host.
*/
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();
public:
virtual void run();
virtual void reset();
virtual void abort();
virtual bool connect(const TransportAddress& peer);
virtual void setManualSocketsMode(bool manual);
virtual void propagateEvent(Event* event);
virtual void sendPacket(const NetworkString& data,
bool reliable = true) = 0;
virtual void sendPacket(STKPeer* peer,
const NetworkString& data,
bool reliable = true);
virtual void sendPacketExcept(STKPeer* peer,
const NetworkString& data,
bool reliable = true);
// 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);
/** \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);
// Game related functions
virtual GameSetup* setupNewGame();
virtual void disconnected();
virtual bool isServer() = 0;
// message/packets related functions
virtual void notifyEvent(Event* event);
virtual void sendPacket(const NetworkString& data,
bool reliable = true) = 0;
virtual void sendPacket(STKPeer* peer,
const NetworkString& data,
bool reliable = true);
virtual void sendPacketExcept(STKPeer* peer,
const NetworkString& data,
bool reliable = true);
// raw data management
void setLogin(std::string username, std::string password);
void setPublicAddress(const TransportAddress& addr);
void removePeer(STKPeer* peer);
// Game related functions
virtual GameSetup* setupNewGame(); //!< Creates a new game setup and returns it
virtual void disconnected(); //!< Called when you leave a server
// getters
// ------------------------------------------------------------------------
/** 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
// raw data management
void setLogin(std::string username, std::string password);
void setPublicAddress(const TransportAddress& addr);
void removePeer(STKPeer* peer);
// --------------------------------------------------------------------
inline bool isClient() { return !isServer(); }
// --------------------------------------------------------------------
STKHost* getHost() { return m_localhost; }
// --------------------------------------------------------------------
std::vector<STKPeer*> getPeers() { return m_peers; }
// --------------------------------------------------------------------
unsigned int getPeerCount() { return (int)m_peers.size(); }
// --------------------------------------------------------------------
/** Returns the public IP address (thread safe). The network manager
* is a friend of TransportAddress and so has access to the copy
* constructor, which is otherwise declared private. */
const TransportAddress getPublicAddress()
{
m_public_address.lock();
TransportAddress a;
a.copy(m_public_address.getData());
m_public_address.unlock();
return a;
} // getPublicAddress
// getters
virtual bool peerExists(const TransportAddress& peer);
virtual bool isConnectedTo(const TransportAddress& peer);
// --------------------------------------------------------------------
/** Returns the current game setup. */
GameSetup* getGameSetup() { return m_game_setup; }
virtual bool isServer() = 0;
// --------------------------------------------------------------------
inline bool isClient() { return !isServer(); }
// --------------------------------------------------------------------
bool isPlayingOnline() { return m_playing_online; }
// --------------------------------------------------------------------
STKHost* getHost() { return m_localhost; }
// --------------------------------------------------------------------
std::vector<STKPeer*> getPeers() { return m_peers; }
// --------------------------------------------------------------------
unsigned int getPeerCount() { return (int)m_peers.size(); }
// --------------------------------------------------------------------
/** Returns the public IP address (thread safe). The network manager
* is a friend of TransportAddress and so has access to the copy
* constructor, which is otherwise declared private. */
const TransportAddress getPublicAddress()
{
m_public_address.lock();
TransportAddress a;
a.copy(m_public_address.getData());
m_public_address.unlock();
return a;
} // getPublicAddress
// --------------------------------------------------------------------
GameSetup* getGameSetup() { return m_game_setup; }
protected:
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;
};
}; // class NetworkManager
#endif // NETWORKMANAGER_HPP

View File

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

View File

@ -18,10 +18,11 @@
#include "network/protocol.hpp"
#include "network/protocol_manager.hpp"
#include "network/event.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_type = type;
@ -49,14 +50,14 @@ void Protocol::setListener(ProtocolManager* listener)
m_listener = listener;
}
PROTOCOL_TYPE Protocol::getProtocolType()
ProtocolType Protocol::getProtocolType()
{
return m_type;
}
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)
{
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)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (data[byte_nb] != value)
{
Log::info("Protocol", "Bad byte at pos %d. %d "

View File

@ -23,17 +23,18 @@
#ifndef PROTOCOL_HPP
#define PROTOCOL_HPP
#include "network/event.hpp"
#include "network/network_string.hpp"
#include "network/types.hpp"
#include "utils/types.hpp"
class Event;
class ProtocolManager;
/** \enum PROTOCOL_TYPE
/** \enum ProtocolType
* \brief The types that protocols can have. This is used to select which protocol receives which event.
* \ingroup network
*/
enum PROTOCOL_TYPE
enum ProtocolType
{
PROTOCOL_NONE = 0, //!< No protocol type assigned.
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 type The type of the protocol.
*/
Protocol(CallbackObject* callback_object, PROTOCOL_TYPE type);
Protocol(CallbackObject* callback_object, ProtocolType type);
/*! \brief Destructor
*/
virtual ~Protocol();
@ -111,7 +112,7 @@ class Protocol
/*! \brief Method to get a protocol's type.
* \return The protocol type.
*/
PROTOCOL_TYPE getProtocolType();
ProtocolType getProtocolType();
/// functions to check incoming data easily
bool checkDataSizeAndToken(Event* event, int minimum_size);
@ -121,7 +122,7 @@ class Protocol
protected:
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
};

View File

@ -18,6 +18,7 @@
#include "network/protocol_manager.hpp"
#include "network/event.hpp"
#include "network/network_manager.hpp"
#include "network/protocol.hpp"
#include "utils/log.hpp"
@ -66,6 +67,8 @@ ProtocolManager::~ProtocolManager()
} // ~ProtocolManager
// ----------------------------------------------------------------------------
/** \brief Stops the protocol manager.
*/
void ProtocolManager::abort()
{
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_id_mutex);
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++)
delete m_events_to_process.getData()[i].event;
delete m_events_to_process.getData()[i].m_event;
m_protocols.getData().clear();
m_requests.clear();
m_events_to_process.getData().clear();
@ -95,63 +98,76 @@ void ProtocolManager::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();
Event* event2 = new Event(*event);
// register protocols that will receive this event
std::vector<unsigned int> protocols_ids;
PROTOCOL_TYPE searched_protocol = PROTOCOL_NONE;
ProtocolType searched_protocol = PROTOCOL_NONE;
if (event->getType() == EVENT_TYPE_MESSAGE)
{
if (event2->data().size() > 0)
if (event->data().size() > 0)
{
searched_protocol = (PROTOCOL_TYPE)(event2->data()[0]);
event2->removeFront(1);
searched_protocol = (ProtocolType)(event->data()[0]);
event->removeFront(1);
}
else
{
Log::warn("ProtocolManager", "Not enough data.");
}
}
if (event->getType() == EVENT_TYPE_CONNECTED)
else if (event->getType() == EVENT_TYPE_CONNECTED)
{
searched_protocol = PROTOCOL_CONNECTION;
}
Log::verbose("ProtocolManager", "Received event for protocols of type %d",
searched_protocol);
std::vector<unsigned int> protocols_ids;
m_protocols.lock();
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
if (m_protocols.getData()[i].protocol->getProtocolType() == searched_protocol ||
if (pi.m_protocol->getProtocolType() == searched_protocol ||
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();
// no protocol was aimed, show the msg to debug
if (searched_protocol == PROTOCOL_NONE)
{
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)
{
EventProcessingInfo epi;
epi.arrival_time = (double)StkTime::getTimeSinceEpoch();
epi.event = event2;
epi.protocols_ids = protocols_ids;
m_events_to_process.getData().push_back(epi); // add the event to the queue
epi.m_arrival_time = (double)StkTime::getTimeSinceEpoch();
epi.m_event = event;
epi.m_protocols_ids = protocols_ids;
// 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
{
Log::warn("ProtocolManager",
"Received an event for %d that has no destination protocol.",
searched_protocol);
m_events_to_process.lock();
} // notifyEvent
// Free the memory for the vent
delete event;
}
m_events_to_process.unlock();
} // propagateEvent
// ----------------------------------------------------------------------------
void ProtocolManager::sendMessage(Protocol* sender, const NetworkString& message,
@ -185,33 +201,42 @@ void ProtocolManager::sendMessageExcept(Protocol* sender, STKPeer* peer,
} // 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)
{
// create the request
ProtocolRequest req;
ProtocolInfo info;
info.protocol = protocol;
info.state = PROTOCOL_STATE_RUNNING;
assignProtocolId(&info); // assign a unique id to the protocol.
req.protocol_info = info;
req.type = PROTOCOL_REQUEST_START;
req.m_protocol_info.m_protocol = protocol;
req.m_protocol_info.m_state = PROTOCOL_STATE_INITIALISING;
assignProtocolId(&req.m_protocol_info); // assign a unique id to the protocol.
req.m_type = PROTOCOL_REQUEST_START;
// add it to the request stack
pthread_mutex_lock(&m_requests_mutex);
m_requests.push_back(req);
pthread_mutex_unlock(&m_requests_mutex);
return info.id;
return req.m_protocol_info.m_id;
} // 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)
{
if (!protocol)
return;
// create the request
ProtocolRequest req;
req.protocol_info.protocol = protocol;
req.type = PROTOCOL_REQUEST_STOP;
req.m_protocol_info.m_protocol = protocol;
req.m_type = PROTOCOL_REQUEST_STOP;
// add it to the request stack
pthread_mutex_lock(&m_requests_mutex);
m_requests.push_back(req);
@ -219,14 +244,19 @@ void ProtocolManager::requestStop(Protocol* protocol)
} // 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)
{
if (!protocol)
return;
// create the request
ProtocolRequest req;
req.protocol_info.protocol = protocol;
req.type = PROTOCOL_REQUEST_PAUSE;
req.m_protocol_info.m_protocol = protocol;
req.m_type = PROTOCOL_REQUEST_PAUSE;
// add it to the request stack
pthread_mutex_lock(&m_requests_mutex);
m_requests.push_back(req);
@ -234,14 +264,19 @@ void ProtocolManager::requestPause(Protocol* protocol)
} // 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)
{
if (!protocol)
return;
// create the request
ProtocolRequest req;
req.protocol_info.protocol = protocol;
req.type = PROTOCOL_REQUEST_UNPAUSE;
req.m_protocol_info.m_protocol = protocol;
req.m_type = PROTOCOL_REQUEST_UNPAUSE;
// add it to the request stack
pthread_mutex_lock(&m_requests_mutex);
m_requests.push_back(req);
@ -249,20 +284,25 @@ void ProtocolManager::requestUnpause(Protocol* protocol)
} // 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)
{
if (!protocol)
return;
// create the request
ProtocolRequest req;
req.protocol_info.protocol = protocol;
req.type = PROTOCOL_REQUEST_TERMINATE;
req.m_protocol_info.m_protocol = protocol;
req.m_type = PROTOCOL_REQUEST_TERMINATE;
// add it to the request stack
pthread_mutex_lock(&m_requests_mutex);
// check that the request does not already exist :
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);
return;
@ -273,19 +313,25 @@ void ProtocolManager::requestTerminate(Protocol* protocol)
} // 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
m_protocols.lock();
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
Log::info("ProtocolManager",
"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().push_back(protocol);
// setup the protocol and notify it that it's started
protocol.protocol->setListener(this);
protocol.protocol->setup();
protocol.m_protocol->setListener(this);
protocol.m_protocol->setup();
protocol.m_state = PROTOCOL_STATE_RUNNING;
m_protocols.unlock();
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
} // startProtocol
@ -301,12 +347,12 @@ void ProtocolManager::pauseProtocol(ProtocolInfo protocol)
// FIXME Does this need to be locked?
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{
ProtocolInfo &p = m_protocols.getData()[i];
if (p.protocol == protocol.protocol &&
p.state == PROTOCOL_STATE_RUNNING)
ProtocolInfo &pi = m_protocols.getData()[i];
if (pi.m_protocol == protocol.m_protocol &&
pi.m_state == PROTOCOL_STATE_RUNNING)
{
p.state = PROTOCOL_STATE_PAUSED;
p.protocol->pause();
pi.m_state = PROTOCOL_STATE_PAUSED;
pi.m_protocol->pause();
}
}
} // pauseProtocol
@ -318,11 +364,11 @@ void ProtocolManager::unpauseProtocol(ProtocolInfo protocol)
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{
ProtocolInfo &p = m_protocols.getData()[i];
if (p.protocol == protocol.protocol &&
p.state == PROTOCOL_STATE_PAUSED)
if (p.m_protocol == protocol.m_protocol &&
p.m_state == PROTOCOL_STATE_PAUSED)
{
p.state = PROTOCOL_STATE_RUNNING;
p.protocol->unpause();
p.m_state = PROTOCOL_STATE_RUNNING;
p.m_protocol->unpause();
}
}
} // unpauseProtocol
@ -334,12 +380,12 @@ void ProtocolManager::protocolTerminated(ProtocolInfo protocol)
m_protocols.lock();
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
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++)
{
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().begin()+(i-offset)+1);
offset++;
@ -353,46 +399,59 @@ void ProtocolManager::protocolTerminated(ProtocolInfo protocol)
} // 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;
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;
if (synchronous)
result = m_protocols.getData()[i].protocol
->notifyEvent(event->event);
result = m_protocols.getData()[i].m_protocol
->notifyEvent(event->m_event);
else
result = m_protocols.getData()[i].protocol
->notifyEventAsynchronous(event->event);
result = m_protocols.getData()[i].m_protocol
->notifyEventAsynchronous(event->m_event);
if (result)
event->protocols_ids.pop_back();
event->m_protocols_ids.pop_back();
else
index++;
}
}
if (event->protocols_ids.size() == 0 ||
(StkTime::getTimeSinceEpoch()-event->arrival_time) >= TIME_TO_KEEP_EVENTS)
m_protocols.unlock();
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->event;
delete event->m_event;
return true;
}
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()
{
// before updating, notice protocols that they have received events
// before updating, notify protocols that they have received events
m_events_to_process.lock();
int size = (int)m_events_to_process.getData().size();
int offset = 0;
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)
{
m_events_to_process.getData()
@ -406,13 +465,21 @@ void ProtocolManager::update()
m_protocols.lock();
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{
if (m_protocols.getData()[i].state == PROTOCOL_STATE_RUNNING)
m_protocols.getData()[i].protocol->update();
if (m_protocols.getData()[i].m_state == PROTOCOL_STATE_RUNNING)
m_protocols.getData()[i].m_protocol->update();
}
m_protocols.unlock();
} // 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()
{
// before updating, notice protocols that they have received information
@ -421,7 +488,7 @@ void ProtocolManager::asynchronousUpdate()
int offset = 0;
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)
{
m_events_to_process.getData()
@ -437,8 +504,8 @@ void ProtocolManager::asynchronousUpdate()
// FIXME: does m_protocols need to be locked???
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{
if (m_protocols.getData()[i].state == PROTOCOL_STATE_RUNNING)
m_protocols.getData()[i].protocol->asynchronousUpdate();
if (m_protocols.getData()[i].m_state == PROTOCOL_STATE_RUNNING)
m_protocols.getData()[i].m_protocol->asynchronousUpdate();
}
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
@ -447,22 +514,22 @@ void ProtocolManager::asynchronousUpdate()
pthread_mutex_lock(&m_requests_mutex);
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:
startProtocol(m_requests[i].protocol_info);
startProtocol(m_requests[i].m_protocol_info);
break;
case PROTOCOL_REQUEST_STOP:
stopProtocol(m_requests[i].protocol_info);
stopProtocol(m_requests[i].m_protocol_info);
break;
case PROTOCOL_REQUEST_PAUSE:
pauseProtocol(m_requests[i].protocol_info);
pauseProtocol(m_requests[i].m_protocol_info);
break;
case PROTOCOL_REQUEST_UNPAUSE:
unpauseProtocol(m_requests[i].protocol_info);
unpauseProtocol(m_requests[i].m_protocol_info);
break;
case PROTOCOL_REQUEST_TERMINATE:
protocolTerminated(m_requests[i].protocol_info);
protocolTerminated(m_requests[i].m_protocol_info);
break;
}
}
@ -471,38 +538,46 @@ void ProtocolManager::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
// a locked section anyway
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
return m_protocols.getData()[i].state;
if (m_protocols.getData()[i].m_id == id) // we know a protocol with that id
return m_protocols.getData()[i].m_state;
}
// the protocol isn't running right now
for (unsigned int i = 0; i < m_requests.size(); i++)
{
// 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_TERMINATED; // else, it's already finished
} // 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?
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{
if (m_protocols.getData()[i].protocol == protocol) // the protocol is known
return m_protocols.getData()[i].state;
if (m_protocols.getData()[i].m_protocol == protocol) // the protocol is known
return m_protocols.getData()[i].m_state;
}
for (unsigned int i = 0; i < m_requests.size(); i++)
{
// 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
}
// we don't know this protocol at all, it's finished
@ -510,48 +585,65 @@ PROTOCOL_STATE ProtocolManager::getProtocolState(Protocol* protocol)
} // 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)
{
// FIXME: Does this need to be locked?
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{
if (m_protocols.getData()[i].protocol == protocol)
return m_protocols.getData()[i].id;
if (m_protocols.getData()[i].m_protocol == protocol)
return m_protocols.getData()[i].m_id;
}
return 0;
} // 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)
{
// FIXME: does m_protocols need to be locked??
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{
if (m_protocols.getData()[i].id == id)
return m_protocols.getData()[i].protocol;
if (m_protocols.getData()[i].m_id == id)
return m_protocols.getData()[i].m_protocol;
}
return NULL;
} // 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?
for (unsigned int i = 0; i < m_protocols.getData().size(); i++)
{
if (m_protocols.getData()[i].protocol->getProtocolType() == type)
return m_protocols.getData()[i].protocol;
if (m_protocols.getData()[i].m_protocol->getProtocolType() == type)
return m_protocols.getData()[i].m_protocol;
}
return NULL;
} // getProtocol
// ----------------------------------------------------------------------------
/** \brief Know whether the app is a server.
* \return True if this application is in server mode, false elseway.
*/
bool ProtocolManager::isServer()
{
return NetworkManager::getInstance()->isServer();
} // isServer
// ----------------------------------------------------------------------------
/*! \brief Tells if we need to stop the update thread.
*/
int ProtocolManager::exit()
{
switch(pthread_mutex_trylock(&m_exit_mutex)) {
@ -568,7 +660,7 @@ int ProtocolManager::exit()
void ProtocolManager::assignProtocolId(ProtocolInfo* protocol_info)
{
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++;
pthread_mutex_unlock(&m_id_mutex);
} // assignProtocolId

View File

@ -23,7 +23,6 @@
#ifndef PROTOCOL_MANAGER_HPP
#define PROTOCOL_MANAGER_HPP
#include "network/event.hpp"
#include "network/network_string.hpp"
#include "network/protocol.hpp"
#include "utils/no_copy.hpp"
@ -33,77 +32,84 @@
#include <vector>
class Event;
class STKPeer;
#define TIME_TO_KEEP_EVENTS 1.0
/*!
* \enum PROTOCOL_STATE
* \brief Defines the three states that a protocol can have.
/** \enum PROTOCOL_STATE
* \brief Defines the three states that a protocol can have.
*/
enum PROTOCOL_STATE
enum ProtocolState
{
PROTOCOL_STATE_RUNNING, //!< The protocol is being updated everytime.
PROTOCOL_STATE_PAUSED, //!< The protocol is paused.
PROTOCOL_STATE_TERMINATED //!< The protocol is terminated/does not exist.
};
PROTOCOL_STATE_INITIALISING, //!< The protocol is waiting to be started
PROTOCOL_STATE_RUNNING, //!< The protocol is being updated everytime.
PROTOCOL_STATE_PAUSED, //!< The protocol is paused.
PROTOCOL_STATE_TERMINATED //!< The protocol is terminated/does not exist.
}; // ProtocolState
/*!
* \enum PROTOCOL_REQUEST_TYPE
* \brief Defines actions that can be done about protocols.
* This enum is used essentially to keep the manager thread-safe and
* to avoid protocols modifying directly their state.
// ----------------------------------------------------------------------------
/** \enum ProtocolRequestType
* \brief Defines actions that can be done about protocols.
* This enum is used essentially to keep the manager thread-safe and
* to avoid protocols modifying directly their state.
*/
enum PROTOCOL_REQUEST_TYPE
enum ProtocolRequestType
{
PROTOCOL_REQUEST_START, //!< Start a protocol
PROTOCOL_REQUEST_STOP, //!< Stop a protocol
PROTOCOL_REQUEST_PAUSE, //!< Pause a protocol
PROTOCOL_REQUEST_UNPAUSE, //!< Unpause a protocol
PROTOCOL_REQUEST_TERMINATE //!< Terminate a protocol
};
}; // ProtocolRequestType
/*!
* \struct ProtocolInfo
* \brief Stores the information needed to manage protocols
*/
// ----------------------------------------------------------------------------
/** \struct ProtocolInfo
* \brief Stores the information needed to manage protocols
*/
typedef struct ProtocolInfo
{
PROTOCOL_STATE state; //!< The state of the protocol
Protocol* protocol; //!< A pointer to the protocol
uint32_t id; //!< The unique id of the protocol
ProtocolState m_state; //!< The state of the protocol
Protocol* m_protocol; //!< A pointer to the protocol
uint32_t m_id; //!< The unique id of the protocol
} ProtocolInfo;
/*!
* \struct ProtocolRequest
* \brief Represents a request to do an action about a protocol.
*/
// ----------------------------------------------------------------------------
/** \struct ProtocolRequest
* \brief Represents a request to do an action about a protocol.
*/
typedef struct ProtocolRequest
{
PROTOCOL_REQUEST_TYPE type; //!< The type of request
ProtocolInfo protocol_info; //!< The concerned protocol information
/** The type of request. */
ProtocolRequestType m_type;
/** The concerned protocol information. */
ProtocolInfo m_protocol_info;
} ProtocolRequest;
/*! \struct ProtocolRequest
// ----------------------------------------------------------------------------
/** \struct ProtocolRequest
* \brief Used to pass the event to protocols that need it
*/
typedef struct EventProcessingInfo
{
Event* event;
double arrival_time;
std::vector<unsigned int> protocols_ids;
Event* m_event;
double m_arrival_time;
std::vector<unsigned int> m_protocols_ids;
} EventProcessingInfo;
/*!
* \class ProtocolManager
* \brief Manages the protocols at runtime.
// ----------------------------------------------------------------------------
/** \class ProtocolManager
* \brief Manages the protocols at runtime.
*
* This class is in charge of storing and managing protocols.
* It is a singleton as there can be only one protocol manager per game
* instance. Any game object that wants to start a protocol must create a
* protocol and give it to this singleton. The protocols are updated in a
* special thread, to ensure that they are processed independently from the
* frames per second. Then, the management of protocols is thread-safe: any
* object can start/pause/stop protocols whithout problems.
*/
* This class is in charge of storing and managing protocols.
* It is a singleton as there can be only one protocol manager per game
* instance. Any game object that wants to start a protocol must create a
* protocol and give it to this singleton. The protocols are updated in a
* special thread, to ensure that they are processed independently from the
* frames per second. Then, the management of protocols is thread-safe: any
* object can start/pause/stop protocols whithout problems.
*/
class ProtocolManager : public AbstractSingleton<ProtocolManager>,
public NoCopy
{
@ -111,126 +117,31 @@ class ProtocolManager : public AbstractSingleton<ProtocolManager>,
static void* mainLoop(void *data);
public:
/*! \brief Stops the protocol manager. */
virtual void abort();
/*!
* \brief Function that processes incoming events.
* This function is called by the network manager each time there is an
* incoming packet.
*/
virtual void notifyEvent(Event* event);
/*!
* \brief WILL BE COMMENTED LATER
*/
virtual void sendMessage(Protocol* sender, const NetworkString& message, 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);
/*!
* \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);
/*!
* \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);
/*!
* \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);
/*!
* \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);
/*!
* \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();
/*!
* \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();
/*!
* \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);
/*!
* \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);
/*!
* \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();
/*! \brief Tells if we need to stop the update thread. */
int exit();
virtual void abort();
virtual void propagateEvent(Event* event);
virtual void sendMessage(Protocol* sender,
const NetworkString& message,
bool reliable = true);
virtual void sendMessage(Protocol* sender, STKPeer* peer,
const NetworkString& message,
bool reliable = true);
virtual void sendMessageExcept(Protocol* sender, STKPeer* peer,
const NetworkString& message,
bool reliable = true);
virtual uint32_t requestStart(Protocol* protocol);
virtual void requestStop(Protocol* protocol);
virtual void requestPause(Protocol* protocol);
virtual void requestUnpause(Protocol* protocol);
virtual void requestTerminate(Protocol* protocol);
virtual void update();
virtual void asynchronousUpdate();
virtual ProtocolState getProtocolState(uint32_t id);
virtual ProtocolState getProtocolState(Protocol* protocol);
virtual uint32_t getProtocolID(Protocol* protocol);
virtual Protocol* getProtocol(uint32_t id);
virtual Protocol* getProtocol(ProtocolType type);
bool isServer();
int exit();
protected:
// protected functions
@ -251,12 +162,7 @@ class ProtocolManager : public AbstractSingleton<ProtocolManager>,
*/
void assignProtocolId(ProtocolInfo* protocol_info);
/*!
* \brief Starts a protocol.
* Add the protocol info to the m_protocols vector.
* \param protocol : ProtocolInfo to start.
*/
virtual void startProtocol(ProtocolInfo protocol);
virtual void startProtocol(ProtocolInfo &protocol);
/*!
* \brief Stops a protocol.
* Coes nothing. Noone can stop running protocols for now.
@ -282,7 +188,7 @@ class ProtocolManager : public AbstractSingleton<ProtocolManager>,
*/
virtual void protocolTerminated(ProtocolInfo protocol);
bool propagateEvent(EventProcessingInfo* event, bool synchronous);
bool sendEvent(EventProcessingInfo* event, bool synchronous);
// protected members
/** Contains the running protocols.

View File

@ -20,6 +20,7 @@
#include "config/player_manager.hpp"
#include "modes/world_with_rank.hpp"
#include "network/event.hpp"
#include "network/network_manager.hpp"
#include "network/network_world.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
if (event->getType() == EVENT_TYPE_MESSAGE)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
assert(data.size()); // assert that data isn't empty
uint8_t message_type = data[0];
if (message_type != 0x03 &&
@ -161,7 +162,7 @@ bool ClientLobbyRoomProtocol::notifyEventAsynchronous(Event* event)
assert(m_setup); // assert that the setup exists
if (event->getType() == EVENT_TYPE_MESSAGE)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
assert(data.size()); // assert that data isn't empty
uint8_t message_type = data[0];
if (message_type == 0x03 ||
@ -285,7 +286,7 @@ void ClientLobbyRoomProtocol::update()
*/
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
{
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)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (data.size() != 2 || data[0] != 1)
{
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)
{
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
{
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)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
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.");
@ -463,7 +464,7 @@ void ClientLobbyRoomProtocol::connectionRefused(Event* event)
*/
void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (data.size() != 2 || data[0] != 1)
{
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)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (data.size() < 3 || data[0] != 1)
{
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)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (data.size() < 5 || data[0] != 4)
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
@ -567,7 +568,7 @@ void ClientLobbyRoomProtocol::startGame(Event* event)
*/
void ClientLobbyRoomProtocol::startSelection(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (data.size() < 5 || data[0] != 4)
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
@ -599,12 +600,12 @@ void ClientLobbyRoomProtocol::startSelection(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.");
return;
}
NetworkString data = event->data();
if (event->getPeer()->getClientServerToken() != data.gui32(1))
{
Log::error("ClientLobbyRoomProtocol", "Bad token");
@ -675,7 +676,7 @@ void ClientLobbyRoomProtocol::raceFinished(Event* event)
*/
void ClientLobbyRoomProtocol::playerMajorVote(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 9))
return;
if (!isByteCorrect(event, 5, 1))
@ -698,7 +699,7 @@ void ClientLobbyRoomProtocol::playerMajorVote(Event* event)
*/
void ClientLobbyRoomProtocol::playerRaceCountVote(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 9))
return;
if (!isByteCorrect(event, 5, 1))
@ -721,7 +722,7 @@ void ClientLobbyRoomProtocol::playerRaceCountVote(Event* event)
*/
void ClientLobbyRoomProtocol::playerMinorVote(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 9))
return;
if (!isByteCorrect(event, 5, 1))
@ -745,7 +746,7 @@ void ClientLobbyRoomProtocol::playerMinorVote(Event* event)
*/
void ClientLobbyRoomProtocol::playerTrackVote(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 10))
return;
if (!isByteCorrect(event, 5, 1))
@ -771,7 +772,7 @@ void ClientLobbyRoomProtocol::playerTrackVote(Event* event)
*/
void ClientLobbyRoomProtocol::playerReversedVote(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 11))
return;
if (!isByteCorrect(event, 5, 1))
@ -797,7 +798,7 @@ void ClientLobbyRoomProtocol::playerReversedVote(Event* event)
*/
void ClientLobbyRoomProtocol::playerLapsVote(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (!checkDataSizeAndToken(event, 9))
return;
if (!isByteCorrect(event, 5, 1))

View File

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

View File

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

View File

@ -19,6 +19,7 @@
#include "network/protocols/connect_to_server.hpp"
#include "network/client_network_manager.hpp"
#include "network/event.hpp"
#include "network/protocols/get_public_address.hpp"
#include "network/protocols/get_peer_address.hpp"
#include "network/protocols/show_public_address.hpp"
@ -37,31 +38,36 @@
#endif
// ----------------------------------------------------------------------------
ConnectToServer::ConnectToServer() :
Protocol(NULL, PROTOCOL_CONNECTION)
/** Quick join/
*/
ConnectToServer::ConnectToServer() : Protocol(NULL, PROTOCOL_CONNECTION)
{
m_server_id = 0;
m_server_id = 0;
m_host_id = 0;
m_quick_join = true;
m_state = NONE;
}
m_state = NONE;
} // ConnectToServer()
// ----------------------------------------------------------------------------
ConnectToServer::ConnectToServer(uint32_t server_id, uint32_t host_id) :
Protocol(NULL, PROTOCOL_CONNECTION)
/** Specify server to connect to.
* \param server_id Id of server to connect to.
* \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_host_id = host_id;
m_server_id = server_id;
m_host_id = host_id;
m_quick_join = false;
m_state = NONE;
}
m_state = NONE;
} // ConnectToServer(server, host)
// ----------------------------------------------------------------------------
/** Destructor.
*/
ConnectToServer::~ConnectToServer()
{
}
} // ~ConnectToServer
// ----------------------------------------------------------------------------
@ -74,20 +80,18 @@ bool ConnectToServer::notifyEventAsynchronous(Event* event)
m_state = CONNECTED; // we received a message, we are connected
}
return true;
}
} // notifyEventAsynchronous
// ----------------------------------------------------------------------------
void ConnectToServer::setup()
{
Log::info("ConnectToServer", "SETUPP");
Log::info("ConnectToServer", "SETUP");
m_state = NONE;
m_server_address.clear();
m_current_protocol_id = 0;
}
} // setup
// ----------------------------------------------------------------------------
void ConnectToServer::asynchronousUpdate()
{
switch(m_state)
@ -95,154 +99,89 @@ void ConnectToServer::asynchronousUpdate()
case NONE:
{
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;
break;
}
case GETTING_SELF_ADDRESS:
if (m_listener->getProtocolState(m_current_protocol_id)
== PROTOCOL_STATE_TERMINATED) // now we know the public addr
if (m_listener->getProtocolState(m_current_protocol_id) ==
PROTOCOL_STATE_TERMINATED) // now we know the public addr
{
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");
/*
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;
case SHOWING_SELF_ADDRESS:
if (m_listener->getProtocolState(m_current_protocol_id)
== PROTOCOL_STATE_TERMINATED) // now our public address is in the database
if (m_listener->getProtocolState(m_current_protocol_id) ==
PROTOCOL_STATE_TERMINATED)
{
// now our public address is in the database
Log::info("ConnectToServer", "Public address shown");
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;
}
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;
}
}
break;
case GETTING_SERVER_ADDRESS:
if (m_listener->getProtocolState(m_current_protocol_id)
== PROTOCOL_STATE_TERMINATED) // we know the server address
if (m_listener->getProtocolState(m_current_protocol_id) ==
PROTOCOL_STATE_TERMINATED) // we know the server address
{
Log::info("ConnectToServer", "Server's address known");
// we're in the same lan (same public ip address) !!
if (m_server_address.getIP() ==
NetworkManager::getInstance()->getPublicAddress().getIP())
Log::info("ConnectToServer",
"Server appears to be in the same LAN.");
m_state = REQUESTING_CONNECTION;
m_current_protocol_id =
m_listener->requestStart(new RequestConnection(m_server_id));
}
break;
case REQUESTING_CONNECTION:
if (m_listener->getProtocolState(m_current_protocol_id)
== PROTOCOL_STATE_TERMINATED) // server knows we wanna connect
{
Log::info("ConnectToServer", "Connection request made");
if (m_server_address.getIP() == 0 ||
m_server_address.getPort() == 0 )
{ // server data not correct, hide address and stop
m_state = HIDING_ADDRESS;
Log::error("ConnectToServer", "Server address is %s",
m_server_address.toString().c_str());
m_current_protocol_id = m_listener->requestStart(new HidePublicAddress());
return;
}
// we're in the same lan (same public ip address) !!
if (m_server_address.getIP() ==
NetworkManager::getInstance()->getPublicAddress().getIP())
{
// just send a broadcast packet, the client will know our ip address and will connect
STKHost* host = NetworkManager::getInstance()->getHost();
host->stopListening(); // stop the listening
TransportAddress sender;
TransportAddress broadcast_address;
broadcast_address.setIP(-1); // 255.255.255.255
broadcast_address.setPort(7321); // 0b10101100000101101101111111111111; // for test
char data2[] = "aloha_stk\0";
host->sendRawPacket((uint8_t*)(data2), 10, broadcast_address);
Log::info("ConnectToServer", "Waiting broadcast message.");
const uint8_t* received_data = host->receiveRawPacket(&sender); // get the sender
host->startListening(); // start listening again
const char data[] = "aloha_stk\0";
if (strcmp(data, (char*)(received_data)) == 0)
{
Log::info("ConnectToServer", "LAN Server found : %s",
sender.toString().c_str());
#ifndef WIN32
// just check if the ip is ours : if so, then just use localhost (127.0.0.1)
struct ifaddrs *ifap, *ifa;
struct sockaddr_in *sa;
getifaddrs (&ifap); // get the info
for (ifa = ifap; ifa; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr->sa_family==AF_INET)
{
sa = (struct sockaddr_in *) ifa->ifa_addr;
// This interface is ours
if (ntohl(sa->sin_addr.s_addr) == sender.getIP())
sender.setIP(0x7f000001); // 127.0.0.1
}
}
freeifaddrs(ifap);
#else
// Query the list of all IP addresses on the local host
// First call to GetIpAddrTable with 0 bytes buffer
// will return insufficient buffer error, and size
// will contain the number of bytes needed for all
// data. Repeat the process of querying the size
// using GetIpAddrTable in a while loop since it
// can happen that an interface comes online between
// the previous call to GetIpAddrTable and the next
// call.
MIB_IPADDRTABLE *table = NULL;
unsigned long size = 0;
int error = GetIpAddrTable(table, &size, 0);
// Also add a count to limit the while loop - in
// case that something strange is going on.
int count = 0;
while(error==ERROR_INSUFFICIENT_BUFFER && count < 10)
{
delete[] table; // deleting NULL is legal
table = (MIB_IPADDRTABLE*)new char[size];
error = GetIpAddrTable(table, &size, 0);
count ++;
} // while insufficient buffer
for(unsigned int i=0; i<table->dwNumEntries; i++)
{
unsigned int ip = ntohl(table->table[i].dwAddr);
if(sender.getIP() == ip) // this interface is ours
{
sender.setIP(0x7f000001); // 127.0.0.1
break;
}
}
delete[] table;
#endif
m_server_address.copy(sender);
m_state = CONNECTING;
}
Log::info("ConnectToServer",
"Server appears to be in the same LAN.");
}
m_state = REQUESTING_CONNECTION;
m_current_protocol_id =
m_listener->requestStart(
new RequestConnection(m_server_id));
}
break;
case REQUESTING_CONNECTION:
if (m_listener->getProtocolState(m_current_protocol_id) ==
PROTOCOL_STATE_TERMINATED)
{
// Server knows we want to connect
Log::info("ConnectToServer", "Connection request made");
if (m_server_address.getIP() == 0 ||
m_server_address.getPort() == 0 )
{
// server data not correct, hide address and stop
m_state = HIDING_ADDRESS;
Log::error("ConnectToServer", "Server address is %s",
m_server_address.toString().c_str());
m_current_protocol_id =
m_listener->requestStart(new HidePublicAddress());
return;
}
if (m_server_address.getIP() == NetworkManager::getInstance()
->getPublicAddress().getIP())
{
// 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));
m_current_protocol_id = m_listener->requestStart(
new PingProtocol(m_server_address, 2.0));
}
}
break;
@ -261,20 +200,27 @@ void ConnectToServer::asynchronousUpdate()
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());
// 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
== 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));
// lobby room protocol if we're connected only
if (ClientNetworkManager::getInstance()->isConnected())
{
m_listener->requestStart(
new ClientLobbyRoomProtocol(m_server_address));
}
}
break;
case DONE:
@ -287,4 +233,88 @@ void ConnectToServer::asynchronousUpdate()
}
// ----------------------------------------------------------------------------
/** 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();
host->stopListening(); // stop the listening
TransportAddress broadcast_address;
broadcast_address.setIP(-1); // 255.255.255.255
broadcast_address.setPort(7321);
char data2[] = "aloha_stk\0";
host->sendRawPacket((uint8_t*)(data2), 10, broadcast_address);
Log::info("ConnectToServer", "Waiting broadcast message.");
TransportAddress sender;
// get the sender
const uint8_t* received_data = host->receiveRawPacket(&sender);
host->startListening(); // start listening again
const char data[] = "aloha_stk\0";
if (strcmp(data, (char*)(received_data)) == 0)
{
Log::info("ConnectToServer", "LAN Server found : %s",
sender.toString().c_str());
#ifndef WIN32
// just check if the ip is ours : if so,
// then just use localhost (127.0.0.1)
struct ifaddrs *ifap, *ifa;
struct sockaddr_in *sa;
getifaddrs(&ifap); // get the info
for (ifa = ifap; ifa; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr->sa_family == AF_INET)
{
sa = (struct sockaddr_in *) ifa->ifa_addr;
// This interface is ours
if (ntohl(sa->sin_addr.s_addr) == sender.getIP())
sender.setIP(0x7f000001); // 127.0.0.1
}
}
freeifaddrs(ifap);
#else
// Query the list of all IP addresses on the local host
// First call to GetIpAddrTable with 0 bytes buffer
// will return insufficient buffer error, and size
// will contain the number of bytes needed for all
// data. Repeat the process of querying the size
// using GetIpAddrTable in a while loop since it
// can happen that an interface comes online between
// the previous call to GetIpAddrTable and the next
// call.
MIB_IPADDRTABLE *table = NULL;
unsigned long size = 0;
int error = GetIpAddrTable(table, &size, 0);
// Also add a count to limit the while loop - in
// case that something strange is going on.
int count = 0;
while (error == ERROR_INSUFFICIENT_BUFFER && count < 10)
{
delete[] table; // deleting NULL is legal
table = (MIB_IPADDRTABLE*)new char[size];
error = GetIpAddrTable(table, &size, 0);
count++;
} // while insufficient buffer
for (unsigned int i = 0; i < table->dwNumEntries; i++)
{
unsigned int ip = ntohl(table->table[i].dwAddr);
if (sender.getIP() == ip) // this interface is ours
{
sender.setIP(0x7f000001); // 127.0.0.1
break;
}
}
delete[] table;
#endif
m_server_address.copy(sender);
m_state = CONNECTING;
}
} // handleSameLAN

View File

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

View File

@ -2,6 +2,9 @@
#include "modes/world.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_world.hpp"
#include "utils/log.hpp"
@ -63,7 +66,7 @@ void ControllerEventsProtocol::setup()
bool ControllerEventsProtocol::notifyEventAsynchronous(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
if (data.size() < 17)
{
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 "input/input.hpp"
#include "karts/controller/controller.hpp"
class Controller;
class STKPeer;
class ControllerEventsProtocol : public Protocol
{

View File

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

View File

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

View File

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

View File

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

View File

@ -21,6 +21,7 @@
#include "config/player_manager.hpp"
#include "config/user_config.hpp"
#include "modes/world.hpp"
#include "network/event.hpp"
#include "network/network_world.hpp"
#include "network/protocols/get_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
if (event->getType() == EVENT_TYPE_MESSAGE)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
assert(data.size()); // message not empty
uint8_t message_type;
message_type = data[0];
@ -335,7 +336,7 @@ void ServerLobbyRoomProtocol::kartDisconnected(Event* event)
void ServerLobbyRoomProtocol::connectionRequested(Event* event)
{
STKPeer* peer = event->getPeer();
NetworkString data = event->data();
const NetworkString &data = event->data();
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]);
@ -414,7 +415,7 @@ void ServerLobbyRoomProtocol::connectionRequested(Event* event)
*/
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
{
NetworkString data = event->data();
const NetworkString &data = event->data();
STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 6))
return;
@ -475,7 +476,7 @@ void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
*/
void ServerLobbyRoomProtocol::playerMajorVote(Event* event)
{
NetworkString data = event->data();
NetworkString &data = event->data();
STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 7))
return;
@ -506,7 +507,7 @@ void ServerLobbyRoomProtocol::playerMajorVote(Event* event)
*/
void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event)
{
NetworkString data = event->data();
NetworkString &data = event->data();
STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 7))
return;
@ -537,7 +538,7 @@ void ServerLobbyRoomProtocol::playerRaceCountVote(Event* event)
*/
void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
{
NetworkString data = event->data();
NetworkString &data = event->data();
STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 7))
return;
@ -568,7 +569,7 @@ void ServerLobbyRoomProtocol::playerMinorVote(Event* event)
*/
void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
{
NetworkString data = event->data();
NetworkString &data = event->data();
STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 8))
return;
@ -601,7 +602,7 @@ void ServerLobbyRoomProtocol::playerTrackVote(Event* event)
*/
void ServerLobbyRoomProtocol::playerReversedVote(Event* event)
{
NetworkString data = event->data();
NetworkString &data = event->data();
STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 9))
return;
@ -634,7 +635,7 @@ void ServerLobbyRoomProtocol::playerReversedVote(Event* event)
*/
void ServerLobbyRoomProtocol::playerLapsVote(Event* event)
{
NetworkString data = event->data();
NetworkString &data = event->data();
STKPeer* peer = event->getPeer();
if (!checkDataSizeAndToken(event, 9))
return;

View File

@ -34,7 +34,6 @@ class ServerLobbyRoomProtocol : public LobbyRoomProtocol
void playerLapsVote(Event* event);
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;
uint32_t m_current_protocol_id;
bool m_selection_enabled;

View File

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

View File

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

View File

@ -111,7 +111,7 @@ void ServerNetworkManager::run()
Log::info("ServerNetworkManager", "Host initialized.");
// 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);
NetworkManager::run();

View File

@ -20,6 +20,7 @@
#include "config/user_config.hpp"
#include "io/file_manager.hpp"
#include "network/event.hpp"
#include "network/network_manager.hpp"
#include "utils/log.hpp"
#include "utils/time.hpp"
@ -178,12 +179,19 @@ void* STKHost::mainLoop(void* self)
{
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);
if (stk_event->getType() == EVENT_TYPE_MESSAGE)
logPacket(stk_event->data(), true);
if (event.type != ENET_EVENT_TYPE_NONE)
NetworkManager::getInstance()->notifyEvent(stk_event);
delete stk_event;
// The event is forwarded to the NetworkManger and from there
// there to the ProtocolManager. The ProtocolManager is
// responsible for freeing the memory.
NetworkManager::getInstance()->propagateEvent(stk_event);
} // while enet_host_service
} // while !mustStopListening
@ -372,7 +380,7 @@ uint8_t* STKHost::receiveRawPacket(const TransportAddress& sender,
}
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",
a.toString(false).c_str());
}

View File

@ -18,54 +18,42 @@
#include "network/stk_peer.hpp"
#include "network/network_manager.hpp"
#include "network/game_setup.hpp"
#include "network/network_string.hpp"
#include "utils/log.hpp"
#include <string.h>
/** Constructor for an empty peer.
*/
STKPeer::STKPeer()
{
m_peer = NULL;
m_player_profile = new NetworkPlayerProfile*;
*m_player_profile = NULL;
m_client_server_token = new uint32_t;
*m_client_server_token = 0;
m_token_set = new bool;
*m_token_set = false;
}
m_enet_peer = NULL;
m_player_profile = NULL;
m_client_server_token = 0;
m_token_set = false;
} // STKPeer
//-----------------------------------------------------------------------------
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;
}
//-----------------------------------------------------------------------------
/** Destructor.
*/
STKPeer::~STKPeer()
{
if (m_peer)
m_peer = NULL;
if (m_enet_peer)
m_enet_peer = NULL;
if (m_player_profile)
delete m_player_profile;
m_player_profile = NULL;
if (m_client_server_token)
delete m_client_server_token;
m_client_server_token = NULL;
if (m_token_set)
delete m_token_set;
m_token_set = NULL;
}
m_client_server_token = 0;
} // ~STKPeer
//-----------------------------------------------------------------------------
/** Connect to the specified host.
*/
bool STKPeer::connectToHost(STKHost* localhost, const TransportAddress &host,
uint32_t channel_count, uint32_t data)
uint32_t channel_count, uint32_t data)
{
const ENetAddress address = host.toEnetAddress();
const ENetAddress address = host.toEnetAddress();
ENetPeer* peer = enet_host_connect(localhost->m_host, &address, 2, 0);
if (peer == NULL)
@ -76,70 +64,70 @@ bool STKPeer::connectToHost(STKHost* localhost, const TransportAddress &host,
TransportAddress a(peer->address);
Log::verbose("STKPeer", "Connecting to %s", a.toString().c_str());
return true;
}
} // connectToHost
//-----------------------------------------------------------------------------
/** Disconnect from the server.
*/
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)
{
TransportAddress a(m_peer->address);
TransportAddress a(m_enet_peer->address);
Log::verbose("STKPeer", "sending packet of size %d to %s",
a.toString().c_str());
ENetPacket* packet = enet_packet_create(data.getBytes(), data.size() + 1,
(reliable ? ENET_PACKET_FLAG_RELIABLE : ENET_PACKET_FLAG_UNSEQUENCED));
/* to debug the packet output
printf("STKPeer: ");
for (unsigned int i = 0; i < data.size(); i++)
{
printf("%d ", (uint8_t)(data[i]));
}
printf("\n");
*/
enet_peer_send(m_peer, 0, packet);
}
(reliable ? ENET_PACKET_FLAG_RELIABLE
: ENET_PACKET_FLAG_UNSEQUENCED));
enet_peer_send(m_enet_peer, 0, packet);
} // sendPacket
//-----------------------------------------------------------------------------
/** Returns the IP address (in host format) of this client.
*/
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
{
return m_peer->address.port;
return m_enet_peer->address.port;
}
//-----------------------------------------------------------------------------
/** Returns if the peer is connected or not.
*/
bool STKPeer::isConnected() const
{
Log::info("STKPeer", "The peer state is %i", m_peer->state);
return (m_peer->state == ENET_PEER_STATE_CONNECTED);
}
Log::info("STKPeer", "The peer state is %i", m_enet_peer->state);
return (m_enet_peer->state == ENET_PEER_STATE_CONNECTED);
} // isConnected
//-----------------------------------------------------------------------------
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
{
return peer->m_peer==m_peer;
return peer->m_enet_peer==m_enet_peer;
}
//-----------------------------------------------------------------------------

View File

@ -23,48 +23,75 @@
#ifndef STK_PEER_HPP
#define STK_PEER_HPP
#include "network/stk_host.hpp"
#include "network/network_string.hpp"
#include "network/game_setup.hpp"
#include "utils/no_copy.hpp"
#include "utils/types.hpp"
#include <enet/enet.h>
class NetworkPlayerProfile;
class NetworkString;
class STKHost;
class TransportAddress;
/*! \class STKPeer
* \brief Represents a peer.
* This class is used to interface the ENetPeer structure.
*/
class STKPeer
class STKPeer : public NoCopy
{
friend class Event;
protected:
ENetPeer* m_peer;
NetworkPlayerProfile** m_player_profile;
uint32_t *m_client_server_token;
bool *m_token_set;
/** Pointer to the corresponding ENet peer data structure. */
ENetPeer* m_enet_peer;
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:
STKPeer();
STKPeer(const STKPeer& peer);
virtual ~STKPeer();
STKPeer();
virtual ~STKPeer();
virtual void sendPacket(const NetworkString& data, bool reliable = true);
static bool connectToHost(STKHost* localhost, const TransportAddress& host,
uint32_t channel_count, uint32_t data);
void disconnect();
virtual void sendPacket(const NetworkString& data, bool reliable = true);
static bool connectToHost(STKHost* localhost, const TransportAddress& host,
uint32_t channel_count, uint32_t data);
void disconnect();
bool isConnected() const;
bool exists() const;
uint32_t getAddress() const;
uint16_t getPort() const;
bool isSamePeer(const STKPeer* peer) const;
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 exists() const;
uint32_t getAddress() 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;
// ------------------------------------------------------------------------
/** 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

View File

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

View File

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

View File

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