Oops - forgot files in previous commit.
git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/trunk@14621 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
99
src/network/event.cpp
Normal file
99
src/network/event.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/event.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
Event::Event(ENetEvent* event)
|
||||
{
|
||||
switch (event->type)
|
||||
{
|
||||
case ENET_EVENT_TYPE_CONNECT:
|
||||
type = EVENT_TYPE_CONNECTED;
|
||||
break;
|
||||
case ENET_EVENT_TYPE_DISCONNECT:
|
||||
type = EVENT_TYPE_DISCONNECTED;
|
||||
break;
|
||||
case ENET_EVENT_TYPE_RECEIVE:
|
||||
type = EVENT_TYPE_MESSAGE;
|
||||
break;
|
||||
case ENET_EVENT_TYPE_NONE:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if (type == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
data = NetworkString(std::string((char*)(event->packet->data), event->packet->dataLength-1));
|
||||
}
|
||||
else if (event->data)
|
||||
{
|
||||
}
|
||||
|
||||
m_packet = NULL;
|
||||
if (event->packet)
|
||||
m_packet = event->packet;
|
||||
|
||||
if (m_packet)
|
||||
enet_packet_destroy(m_packet); // we got all we need, just remove the data.
|
||||
m_packet = NULL;
|
||||
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
peer = new STKPeer*;
|
||||
*peer = NULL;
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
if (peers[i]->m_peer == event->peer)
|
||||
{
|
||||
*peer = peers[i];
|
||||
Log::verbose("Event", "The peer you sought has been found on %lx", (long int)(peer));
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (*peer == NULL) // peer does not exist, create him
|
||||
{
|
||||
STKPeer* new_peer = new STKPeer();
|
||||
new_peer->m_peer = event->peer;
|
||||
*peer = new_peer;
|
||||
Log::debug("Event", "Creating a new peer, address are STKPeer:%lx, Peer:%lx", (long int)(new_peer), (long int)(event->peer));
|
||||
}
|
||||
}
|
||||
|
||||
Event::Event(const Event& event)
|
||||
{
|
||||
m_packet = NULL;
|
||||
data = event.data;
|
||||
// copy the peer
|
||||
peer = event.peer;
|
||||
type = event.type;
|
||||
}
|
||||
|
||||
Event::~Event()
|
||||
{
|
||||
peer = NULL;
|
||||
m_packet = NULL;
|
||||
}
|
||||
|
||||
void Event::removeFront(int size)
|
||||
{
|
||||
data.removeFront(size);
|
||||
}
|
||||
|
||||
76
src/network/event.hpp
Normal file
76
src/network/event.hpp
Normal file
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef EVENT_HPP
|
||||
#define EVENT_HPP
|
||||
|
||||
#include "network/stk_peer.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
/*!
|
||||
* \enum EVENT_TYPE
|
||||
* \brief Represents a network event type.
|
||||
*/
|
||||
enum EVENT_TYPE
|
||||
{
|
||||
EVENT_TYPE_CONNECTED, //!< A peer is connected
|
||||
EVENT_TYPE_DISCONNECTED,//!< A peer is disconnected
|
||||
EVENT_TYPE_MESSAGE //!< A message between server and client protocols
|
||||
};
|
||||
|
||||
/*!
|
||||
* \class Event
|
||||
* \brief Class representing an event that need to pass trough the system.
|
||||
* This is used to remove ENet dependency in the network.
|
||||
* It interfaces the ENetEvent structure.
|
||||
* The user has to be extremely careful about the peer.
|
||||
* Indeed, when packets are logged, the state of the peer cannot be stored at
|
||||
* all times, and then the user of this class can rely only on the address/port
|
||||
* of the peer, and not on values that might change over time.
|
||||
*/
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
/*! \brief Constructor
|
||||
* \param event : The event that needs to be translated.
|
||||
*/
|
||||
Event(ENetEvent* event);
|
||||
/*! \brief Constructor
|
||||
* \param event : The event to copy.
|
||||
*/
|
||||
Event(const Event& event);
|
||||
/*! \brief Destructor
|
||||
* frees the memory of the ENetPacket.
|
||||
*/
|
||||
~Event();
|
||||
|
||||
/*! \brief Remove bytes at the beginning of data.
|
||||
* \param size : The number of bytes to remove.
|
||||
*/
|
||||
void removeFront(int size);
|
||||
|
||||
EVENT_TYPE type; //!< Type of the event.
|
||||
NetworkString data; //!< Copy of the data passed by the event.
|
||||
STKPeer** peer; //!< Pointer to the peer that triggered that event.
|
||||
|
||||
private:
|
||||
ENetPacket* m_packet; //!< A pointer on the ENetPacket to be deleted.
|
||||
};
|
||||
|
||||
#endif // EVENT_HPP
|
||||
145
src/network/game_setup.cpp
Normal file
145
src/network/game_setup.cpp
Normal file
@@ -0,0 +1,145 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/game_setup.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GameSetup::GameSetup()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
GameSetup::~GameSetup()
|
||||
{
|
||||
// remove all players
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
delete m_players[i];
|
||||
};
|
||||
m_players.clear();
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GameSetup::addPlayer(NetworkPlayerProfile* profile)
|
||||
{
|
||||
m_players.push_back(profile);
|
||||
Log::verbose("GameSetup", "New player in the game setup. Global id : %u, "
|
||||
"Race id : %d.", profile->user_profile->getID(), profile->race_id);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GameSetup::removePlayer(uint32_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->user_profile->getID() == id)
|
||||
{
|
||||
delete m_players[i];
|
||||
m_players.erase(m_players.begin()+i, m_players.begin()+i+1);
|
||||
Log::verbose("GameSetup", "Removed a player from the game setup. "
|
||||
"Remains %u.", m_players.size());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GameSetup::removePlayer(uint8_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->race_id == id) // check the given id
|
||||
{
|
||||
delete m_players[i];
|
||||
m_players.erase(m_players.begin()+i, m_players.begin()+i+1);
|
||||
Log::verbose("GameSetup", "Removed a player from the game setup. "
|
||||
"Remains %u.", m_players.size());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void GameSetup::setPlayerKart(uint8_t id, std::string kart_name)
|
||||
{
|
||||
bool found = false;
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->race_id == id)
|
||||
{
|
||||
m_players[i]->kart_name = kart_name;
|
||||
Log::info("GameSetup::setPlayerKart", "Player %d took kart %s",
|
||||
id, kart_name.c_str());
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
{
|
||||
Log::info("GameSetup::setPlayerKart", "The player %d was unknown.", id);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const NetworkPlayerProfile* GameSetup::getProfile(uint32_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->user_profile->getID() == id)
|
||||
{
|
||||
return m_players[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
const NetworkPlayerProfile* GameSetup::getProfile(uint8_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->race_id == id)
|
||||
{
|
||||
return m_players[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool GameSetup::isKartAvailable(std::string kart_name)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_players.size(); i++)
|
||||
{
|
||||
if (m_players[i]->kart_name == kart_name)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
72
src/network/game_setup.hpp
Normal file
72
src/network/game_setup.hpp
Normal file
@@ -0,0 +1,72 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file game_setup.hpp
|
||||
*/
|
||||
|
||||
#ifndef GAME_SETUP_HPP
|
||||
#define GAME_SETUP_HPP
|
||||
|
||||
#include "online/profile.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
/*! \class PlayerProfile
|
||||
* \brief Contains the profile of a player.
|
||||
*/
|
||||
class NetworkPlayerProfile
|
||||
{
|
||||
public:
|
||||
NetworkPlayerProfile() { race_id = 0; user_profile = NULL; }
|
||||
~NetworkPlayerProfile() {}
|
||||
|
||||
uint8_t race_id; //!< The id of the player for the race
|
||||
std::string kart_name; //!< The selected kart.
|
||||
Online::Profile* user_profile; //!< Pointer to the lobby profile
|
||||
};
|
||||
|
||||
/*! \class GameSetup
|
||||
* \brief Used to store the needed data about the players that join a game.
|
||||
* This class stores all the possible information about players in a lobby.
|
||||
*/
|
||||
class GameSetup
|
||||
{
|
||||
public:
|
||||
GameSetup();
|
||||
virtual ~GameSetup();
|
||||
|
||||
void addPlayer(NetworkPlayerProfile* profile); //!< Add a player.
|
||||
bool removePlayer(uint32_t id); //!< Remove a player by id.
|
||||
bool removePlayer(uint8_t id); //!< Remove a player by local id.
|
||||
void setPlayerKart(uint8_t id, std::string kart_name); //!< Set the kart of a player
|
||||
|
||||
std::vector<NetworkPlayerProfile*> getPlayers() { return m_players; }
|
||||
int getPlayerCount() { return m_players.size(); }
|
||||
const NetworkPlayerProfile* getProfile(uint32_t id); //!< Get a profile by database id
|
||||
const NetworkPlayerProfile* getProfile(uint8_t id); //!< Get the profile by the lobby id
|
||||
|
||||
bool isKartAvailable(std::string kart_name);
|
||||
bool isKartAllowed(std::string kart_name) {return true; }
|
||||
|
||||
protected:
|
||||
std::vector<NetworkPlayerProfile*> m_players; //!< Information about players
|
||||
NetworkPlayerProfile m_self_profile; //!< Information about self (client only)
|
||||
};
|
||||
|
||||
#endif // GAME_SETUP_HPP
|
||||
67
src/network/http_functions.cpp
Normal file
67
src/network/http_functions.cpp
Normal file
@@ -0,0 +1,67 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/http_functions.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <curl/curl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
|
||||
namespace HTTP
|
||||
{
|
||||
CURL *curl;
|
||||
CURLcode res;
|
||||
|
||||
static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp)
|
||||
{
|
||||
((std::string*)userp)->append((char*)contents, size * nmemb);
|
||||
return size * nmemb;
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
curl_global_init(CURL_GLOBAL_DEFAULT);
|
||||
curl = curl_easy_init();
|
||||
if(!curl)
|
||||
Log::error("HTTP", "Error while loading cURL library.\n");
|
||||
}
|
||||
|
||||
std::string getPage(std::string url)
|
||||
{
|
||||
std::string readBuffer;
|
||||
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
|
||||
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);
|
||||
res = curl_easy_perform(curl);
|
||||
if(res != CURLE_OK)
|
||||
Log::error("HTTP", "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
|
||||
return readBuffer;
|
||||
}
|
||||
|
||||
void shutdown()
|
||||
{
|
||||
curl_easy_cleanup(curl);
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
}
|
||||
35
src/network/http_functions.hpp
Normal file
35
src/network/http_functions.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HTTP_FUNCTIONS_HPP
|
||||
#define HTTP_FUNCTIONS_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace HTTP
|
||||
{
|
||||
|
||||
void init();
|
||||
void shutdown();
|
||||
|
||||
std::string getPage(std::string url);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // HTTP_FUNCTIONS_HPP
|
||||
28
src/network/network_interface.cpp
Normal file
28
src/network/network_interface.cpp
Normal file
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/network_interface.hpp"
|
||||
|
||||
|
||||
NetworkInterface::NetworkInterface()
|
||||
{
|
||||
}
|
||||
|
||||
NetworkInterface::~NetworkInterface()
|
||||
{
|
||||
}
|
||||
44
src/network/network_interface.hpp
Normal file
44
src/network/network_interface.hpp
Normal file
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef NETWORK_INTERFACE_H
|
||||
#define NETWORK_INTERFACE_H
|
||||
|
||||
#include "network/singleton.hpp"
|
||||
#include "network/types.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
class NetworkInterface : public Singleton<NetworkInterface>
|
||||
{
|
||||
friend class Singleton<NetworkInterface>;
|
||||
public:
|
||||
|
||||
void initNetwork(bool server);
|
||||
|
||||
protected:
|
||||
// protected functions
|
||||
NetworkInterface();
|
||||
virtual ~NetworkInterface();
|
||||
|
||||
};
|
||||
|
||||
#endif // NETWORK_INTERFACE_H
|
||||
8
src/network/network_string.cpp
Normal file
8
src/network/network_string.cpp
Normal file
@@ -0,0 +1,8 @@
|
||||
#include "network/network_string.hpp"
|
||||
|
||||
NetworkString operator+(NetworkString const& a, NetworkString const& b)
|
||||
{
|
||||
NetworkString ns(a);
|
||||
ns += b;
|
||||
return ns;
|
||||
}
|
||||
230
src/network/network_string.hpp
Normal file
230
src/network/network_string.hpp
Normal file
@@ -0,0 +1,230 @@
|
||||
#ifndef NETWORK_STRING_HPP
|
||||
#define NETWORK_STRING_HPP
|
||||
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <stdarg.h>
|
||||
#include <assert.h>
|
||||
|
||||
typedef unsigned char uchar;
|
||||
|
||||
class NetworkString
|
||||
{
|
||||
union {
|
||||
float f;
|
||||
uint8_t i[4];
|
||||
} f_as_i; // float as integer
|
||||
union {
|
||||
double d;
|
||||
uint8_t i[8];
|
||||
} d_as_i; // double as integer
|
||||
public:
|
||||
NetworkString() { }
|
||||
NetworkString(const uint8_t& value) { m_string.push_back(value); }
|
||||
NetworkString(NetworkString const& copy) { m_string = copy.m_string; }
|
||||
NetworkString(const std::string & value) { m_string = std::vector<uint8_t>(value.begin(), value.end()); }
|
||||
|
||||
NetworkString& removeFront(int size)
|
||||
{
|
||||
m_string.erase(m_string.begin(), m_string.begin()+size);
|
||||
return *this;
|
||||
}
|
||||
NetworkString& remove(int pos, int size)
|
||||
{
|
||||
m_string.erase(m_string.begin()+pos, m_string.begin()+pos+size);
|
||||
return *this;
|
||||
}
|
||||
|
||||
uint8_t operator[](const int& pos) const
|
||||
{
|
||||
return getUInt8(pos);
|
||||
}
|
||||
|
||||
NetworkString& addUInt8(const uint8_t& value)
|
||||
{
|
||||
m_string.push_back(value);
|
||||
return *this;
|
||||
}
|
||||
inline NetworkString& ai8(const uint8_t& value) { return addUInt8(value); }
|
||||
NetworkString& addUInt16(const uint16_t& value)
|
||||
{
|
||||
m_string.push_back((value>>8)&0xff);
|
||||
m_string.push_back(value&0xff);
|
||||
return *this;
|
||||
}
|
||||
inline NetworkString& ai16(const uint16_t& value) { return addUInt16(value); }
|
||||
NetworkString& addUInt32(const uint32_t& value)
|
||||
{
|
||||
m_string.push_back((value>>24)&0xff);
|
||||
m_string.push_back((value>>16)&0xff);
|
||||
m_string.push_back((value>>8)&0xff);
|
||||
m_string.push_back(value&0xff);
|
||||
return *this;
|
||||
}
|
||||
inline NetworkString& ai32(const uint32_t& value) { return addUInt32(value); }
|
||||
NetworkString& addInt(const int& value)
|
||||
{
|
||||
m_string.push_back((value>>24)&0xff);
|
||||
m_string.push_back((value>>16)&0xff);
|
||||
m_string.push_back((value>>8)&0xff);
|
||||
m_string.push_back(value&0xff);
|
||||
return *this;
|
||||
}
|
||||
inline NetworkString& ai(const int& value) { return addInt(value); }
|
||||
NetworkString& addFloat(const float& value) //!< BEWARE OF PRECISION
|
||||
{
|
||||
assert(sizeof(float)==4);
|
||||
f_as_i.f = value;
|
||||
m_string.push_back(f_as_i.i[0]);
|
||||
m_string.push_back(f_as_i.i[1]);
|
||||
m_string.push_back(f_as_i.i[2]);
|
||||
m_string.push_back(f_as_i.i[3]);
|
||||
return *this;
|
||||
}
|
||||
inline NetworkString& af(const float& value) { return addFloat(value); }
|
||||
NetworkString& addDouble(const double& value) //!< BEWARE OF PRECISION
|
||||
{
|
||||
assert(sizeof(double)==8);
|
||||
d_as_i.d = value;
|
||||
m_string.push_back(d_as_i.i[0]);
|
||||
m_string.push_back(d_as_i.i[1]);
|
||||
m_string.push_back(d_as_i.i[2]);
|
||||
m_string.push_back(d_as_i.i[3]);
|
||||
m_string.push_back(d_as_i.i[4]);
|
||||
m_string.push_back(d_as_i.i[5]);
|
||||
m_string.push_back(d_as_i.i[6]);
|
||||
m_string.push_back(d_as_i.i[7]);
|
||||
return *this;
|
||||
}
|
||||
inline NetworkString& ad(const double& value) { return addDouble(value); }
|
||||
NetworkString& addChar(const char& value)
|
||||
{
|
||||
m_string.push_back((uint8_t)(value));
|
||||
return *this;
|
||||
}
|
||||
inline NetworkString& ac(const char& value) { return addChar(value); }
|
||||
|
||||
NetworkString& addString(const std::string& value)
|
||||
{
|
||||
for (unsigned int i = 0; i < value.size(); i++)
|
||||
m_string.push_back((uint8_t)(value[i]));
|
||||
return *this;
|
||||
}
|
||||
inline NetworkString& as(const std::string& value) { return addString(value); }
|
||||
|
||||
NetworkString& operator+=(NetworkString const& value)
|
||||
{
|
||||
m_string.insert( m_string.end(), value.m_string.begin(), value.m_string.end() );
|
||||
return *this;
|
||||
}
|
||||
|
||||
const char* c_str() const
|
||||
{
|
||||
std::string str(m_string.begin(), m_string.end());
|
||||
return str.c_str();
|
||||
}
|
||||
int size() const
|
||||
{
|
||||
return m_string.size();
|
||||
}
|
||||
|
||||
template<typename T, size_t n>
|
||||
T get(int pos) const
|
||||
{
|
||||
int a = n;
|
||||
T result = 0;
|
||||
while(a--)
|
||||
{
|
||||
result <<= 8; // offset one byte
|
||||
result += ((uint8_t)(m_string[pos+n-1-a]) & 0xff); // add the data to result
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int getInt(int pos = 0) const { return get<int,4>(pos); }
|
||||
inline uint32_t getUInt(int pos = 0) const { return get<uint32_t,4>(pos); }
|
||||
inline uint32_t getUInt32(int pos = 0) const { return get<uint32_t,4>(pos); }
|
||||
inline uint16_t getUInt16(int pos = 0) const { return get<uint16_t,2>(pos); }
|
||||
inline uint8_t getUInt8(int pos = 0) const { return get<uint8_t,1>(pos); }
|
||||
inline char getChar(int pos = 0) const { return get<char,1>(pos); }
|
||||
inline unsigned char getUChar(int pos = 0) const { return get<unsigned char,1>(pos); }
|
||||
std::string getString(int pos, int len) const { return std::string(m_string.begin()+pos, m_string.begin()+pos+len); }
|
||||
|
||||
inline int gi(int pos = 0) const { return get<int,4>(pos); }
|
||||
inline uint32_t gui(int pos = 0) const { return get<uint32_t,4>(pos); }
|
||||
inline uint32_t gui32(int pos = 0) const { return get<uint32_t,4>(pos); }
|
||||
inline uint16_t gui16(int pos = 0) const { return get<uint16_t,2>(pos); }
|
||||
inline uint8_t gui8(int pos = 0) const { return get<uint8_t,1>(pos); }
|
||||
inline char gc(int pos = 0) const { return get<char,1>(pos); }
|
||||
inline unsigned char guc(int pos = 0) const { return get<unsigned char,1>(pos); }
|
||||
std::string gs(int pos, int len) const { return std::string(m_string.begin()+pos, m_string.begin()+pos+len); }
|
||||
|
||||
double getDouble(int pos = 0) //!< BEWARE OF PRECISION
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
d_as_i.i[i] = m_string[pos+i];
|
||||
return d_as_i.d;
|
||||
}
|
||||
float getFloat(int pos = 0) //!< BEWARE OF PRECISION
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
f_as_i.i[i] = m_string[pos+i];
|
||||
return f_as_i.f;
|
||||
}
|
||||
|
||||
//! Functions to get while removing
|
||||
template<typename T, size_t n>
|
||||
T getAndRemove(int pos)
|
||||
{
|
||||
int a = n;
|
||||
T result = 0;
|
||||
while(a--)
|
||||
{
|
||||
result <<= 8; // offset one byte
|
||||
result += ((uint8_t)(m_string[pos+n-1-a]) & 0xff); // add the data
|
||||
}
|
||||
remove(pos,n);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline int getAndRemoveInt(int pos = 0) { return getAndRemove<int,4>(pos); }
|
||||
inline uint32_t getAndRemoveUInt(int pos = 0) { return getAndRemove<uint32_t,4>(pos); }
|
||||
inline uint32_t getAndRemoveUInt32(int pos = 0) { return getAndRemove<uint32_t,4>(pos); }
|
||||
inline uint16_t getAndRemoveUInt16(int pos = 0) { return getAndRemove<uint16_t,2>(pos); }
|
||||
inline uint8_t getAndRemoveUInt8(int pos = 0) { return getAndRemove<uint8_t,1>(pos); }
|
||||
inline char getAndRemoveChar(int pos = 0) { return getAndRemove<char,1>(pos); }
|
||||
inline unsigned char getAndRemoveUChar(int pos = 0) { return getAndRemove<unsigned char,1>(pos); }
|
||||
double getAndRemoveDouble(int pos = 0) //!< BEWARE OF PRECISION
|
||||
{
|
||||
for (int i = 0; i < 8; i++)
|
||||
d_as_i.i[i] = m_string[pos+i];
|
||||
return d_as_i.d;
|
||||
remove(pos, 8);
|
||||
}
|
||||
float getAndRemoveFloat(int pos = 0) //!< BEWARE OF PRECISION
|
||||
{
|
||||
for (int i = 0; i < 4; i++)
|
||||
f_as_i.i[i] = m_string[pos+i];
|
||||
return f_as_i.f;
|
||||
remove(pos, 4);
|
||||
}
|
||||
|
||||
inline NetworkString& gui8(uint8_t* dst) { *dst = getAndRemoveUInt8(0); return *this; }
|
||||
inline NetworkString& gui16(uint16_t* dst) { *dst = getAndRemoveUInt16(0); return *this; }
|
||||
inline NetworkString& gui32(uint32_t* dst) { *dst = getAndRemoveUInt32(0); return *this; }
|
||||
inline NetworkString& gui(uint32_t* dst) { *dst = getAndRemoveUInt32(0); return *this; }
|
||||
inline NetworkString& gi(int* dst) { *dst = getAndRemoveInt(0); return *this; }
|
||||
inline NetworkString& gc(char* dst) { *dst = getAndRemoveChar(0); return *this; }
|
||||
inline NetworkString& guc(uchar* dst) { *dst = getAndRemoveUChar(0); return *this; }
|
||||
inline NetworkString& gd(double* dst) { *dst = getAndRemoveDouble(0); return *this; }
|
||||
inline NetworkString& gf(float* dst) { *dst = getAndRemoveFloat(0); return *this; }
|
||||
|
||||
protected:
|
||||
std::vector<uint8_t> m_string;
|
||||
};
|
||||
|
||||
NetworkString operator+(NetworkString const& a, NetworkString const& b);
|
||||
|
||||
#endif // NETWORK_STRING_HPP
|
||||
40
src/network/network_world.cpp
Normal file
40
src/network/network_world.cpp
Normal file
@@ -0,0 +1,40 @@
|
||||
#include "network/network_world.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/protocols/synchronization_protocol.hpp"
|
||||
#include "network/protocols/controller_events_protocol.hpp"
|
||||
#include "modes/world.hpp"
|
||||
|
||||
#include "karts/controller/controller.hpp"
|
||||
|
||||
NetworkWorld::NetworkWorld()
|
||||
{
|
||||
m_running = false;
|
||||
}
|
||||
|
||||
NetworkWorld::~NetworkWorld()
|
||||
{
|
||||
}
|
||||
|
||||
void NetworkWorld::update(float dt)
|
||||
{
|
||||
SynchronizationProtocol* protocol = static_cast<SynchronizationProtocol*>(
|
||||
ProtocolManager::getInstance()->getProtocol(PROTOCOL_SYNCHRONIZATION));
|
||||
if (protocol) // if this protocol exists, that's that we play online
|
||||
{
|
||||
Log::debug("NetworkWorld", "Coutdown value is %f", protocol->getCountdown());
|
||||
if (protocol->getCountdown() > 0.0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
World::getWorld()->updateWorld(dt);
|
||||
}
|
||||
|
||||
void NetworkWorld::controllerAction(Controller* controller, PlayerAction action, int value)
|
||||
{
|
||||
ControllerEventsProtocol* protocol = static_cast<ControllerEventsProtocol*>(
|
||||
ProtocolManager::getInstance()->getProtocol(PROTOCOL_CONTROLLER_EVENTS));
|
||||
if (protocol)
|
||||
protocol->controllerAction(controller, action, value);
|
||||
}
|
||||
37
src/network/network_world.hpp
Normal file
37
src/network/network_world.hpp
Normal file
@@ -0,0 +1,37 @@
|
||||
#ifndef NETWORK_WORLD_HPP
|
||||
#define NETWORK_WORLD_HPP
|
||||
|
||||
#include "network/singleton.hpp"
|
||||
#include "input/input.hpp"
|
||||
#include <map>
|
||||
|
||||
class Controller;
|
||||
class KartUpdateProtocol;
|
||||
class AbstractKart;
|
||||
|
||||
/*! \brief Manages the world updates during an online game
|
||||
* This function's update is to be called instead of the normal World update
|
||||
*/
|
||||
class NetworkWorld : public Singleton<NetworkWorld>
|
||||
{
|
||||
friend class Singleton<NetworkWorld>;
|
||||
public:
|
||||
void update(float dt);
|
||||
|
||||
void start() { m_running = true; }
|
||||
void stop() { m_running = false; }
|
||||
bool isRunning() { return m_running; }
|
||||
|
||||
void controllerAction(Controller* controller, PlayerAction action, int value);
|
||||
|
||||
std::string m_self_kart;
|
||||
protected:
|
||||
bool m_running;
|
||||
float m_race_time;
|
||||
|
||||
private:
|
||||
NetworkWorld();
|
||||
virtual ~NetworkWorld();
|
||||
};
|
||||
|
||||
#endif // NETWORK_WORLD_HPP
|
||||
54
src/network/protocol.cpp
Normal file
54
src/network/protocol.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
|
||||
Protocol::Protocol(CallbackObject* callback_object, PROTOCOL_TYPE type)
|
||||
{
|
||||
m_callback_object = callback_object;
|
||||
m_type = type;
|
||||
}
|
||||
|
||||
Protocol::~Protocol()
|
||||
{
|
||||
}
|
||||
|
||||
void Protocol::pause()
|
||||
{
|
||||
m_listener->requestPause(this);
|
||||
}
|
||||
void Protocol::unpause()
|
||||
{
|
||||
m_listener->requestUnpause(this);
|
||||
}
|
||||
|
||||
void Protocol::kill()
|
||||
{
|
||||
}
|
||||
|
||||
void Protocol::setListener(ProtocolManager* listener)
|
||||
{
|
||||
m_listener = listener;
|
||||
}
|
||||
|
||||
PROTOCOL_TYPE Protocol::getProtocolType()
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
119
src/network/protocol.hpp
Normal file
119
src/network/protocol.hpp
Normal file
@@ -0,0 +1,119 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef PROTOCOL_HPP
|
||||
#define PROTOCOL_HPP
|
||||
|
||||
#include "network/event.hpp"
|
||||
#include "network/types.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
class ProtocolManager;
|
||||
|
||||
/** \enum PROTOCOL_TYPE
|
||||
* \brief The types that protocols can have. This is used to select which protocol receives which event.
|
||||
* \ingroup network
|
||||
*/
|
||||
enum PROTOCOL_TYPE
|
||||
{
|
||||
PROTOCOL_NONE = 0, //!< No protocol type assigned.
|
||||
PROTOCOL_CONNECTION = 1, //!< Protocol that deals with client-server connection.
|
||||
PROTOCOL_LOBBY_ROOM = 2, //!< Protocol that is used during the lobby room phase.
|
||||
PROTOCOL_START_GAME = 3, //!< Protocol used when starting the game.
|
||||
PROTOCOL_SYNCHRONIZATION = 4,//!<Protocol used to synchronize clocks.
|
||||
PROTOCOL_KART_UPDATE = 5, //!< Protocol to update karts position, rotation etc...
|
||||
PROTOCOL_GAME_EVENTS = 6, //!< Protocol to communicate the game events.
|
||||
PROTOCOL_CONTROLLER_EVENTS = 7,//!< Protocol to transfer controller modifications
|
||||
PROTOCOL_SILENT = 0xffff //!< Used for protocols that do not subscribe to any network event.
|
||||
};
|
||||
|
||||
/** \class Protocol
|
||||
* \brief Abstract class used to define the global protocol functions.
|
||||
* A protocol is an entity that is started at a point, and that is updated by a thread.
|
||||
* A protocol can be terminated by an other class, or it can terminate itself if has fulfilled its role.
|
||||
* This class must be inherited to make any network job.
|
||||
* \ingroup network
|
||||
*/
|
||||
class Protocol
|
||||
{
|
||||
public:
|
||||
/*!
|
||||
* \brief Constructor
|
||||
*
|
||||
* Sets the basic protocol parameters, as the callback object and the protocol type.
|
||||
*
|
||||
* \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);
|
||||
/*!
|
||||
* \brief Destructor
|
||||
*/
|
||||
virtual ~Protocol();
|
||||
|
||||
/*!
|
||||
* \brief Notify a protocol matching the Event type of that event.
|
||||
* \param event : Pointer to the event.
|
||||
*/
|
||||
virtual void notifyEvent(Event* event) = 0;
|
||||
|
||||
/*!
|
||||
* \brief Set the protocol listener.
|
||||
* \param listener : Pointer to the listener.
|
||||
*/
|
||||
void setListener(ProtocolManager* listener);
|
||||
|
||||
/*!
|
||||
* \brief Called when the protocol is going to start. Must be re-defined by subclasses.
|
||||
*/
|
||||
virtual void setup() = 0;
|
||||
/*!
|
||||
* \brief Called when the protocol is paused (by an other entity or by itself).
|
||||
* This function must be called by the subclasse's pause function if re-defined.
|
||||
*/
|
||||
virtual void pause();
|
||||
/*!
|
||||
* \brief Called when the protocol is unpaused.
|
||||
* This function must be called by the subclasse's unpause function if re-defined.
|
||||
*/
|
||||
virtual void unpause();
|
||||
/*!
|
||||
* \brief Called by the protocol listener, synchronously with the main loop. Must be re-defined.
|
||||
*/
|
||||
virtual void update() = 0;
|
||||
/*!
|
||||
* \brief Called by the protocol listener as often as possible. Must be re-defined.
|
||||
*/
|
||||
virtual void asynchronousUpdate() = 0;
|
||||
/*!
|
||||
* \brief Called when the protocol is to be killed.
|
||||
*/
|
||||
virtual void kill();
|
||||
|
||||
/*!
|
||||
* \brief Method to get a protocol's type.
|
||||
* \return The protocol type.
|
||||
*/
|
||||
PROTOCOL_TYPE getProtocolType();
|
||||
protected:
|
||||
ProtocolManager* m_listener; //!< The protocol listener
|
||||
PROTOCOL_TYPE m_type; //!< The type of the protocol
|
||||
CallbackObject* m_callback_object; //!< The callback object, if needed
|
||||
};
|
||||
|
||||
#endif // PROTOCOL_HPP
|
||||
459
src/network/protocol_manager.cpp
Normal file
459
src/network/protocol_manager.cpp
Normal file
@@ -0,0 +1,459 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "graphics/irr_driver.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
#include <cstdlib>
|
||||
#include <errno.h>
|
||||
#include <typeinfo>
|
||||
|
||||
void* protocolManagerUpdate(void* data)
|
||||
{
|
||||
ProtocolManager* manager = static_cast<ProtocolManager*>(data);
|
||||
while(!manager->exit())
|
||||
{
|
||||
manager->update();
|
||||
irr_driver->getDevice()->sleep(20);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
void* protocolManagerAsynchronousUpdate(void* data)
|
||||
{
|
||||
ProtocolManager* manager = static_cast<ProtocolManager*>(data);
|
||||
while(!manager->exit())
|
||||
{
|
||||
manager->asynchronousUpdate();
|
||||
irr_driver->getDevice()->sleep(20);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ProtocolManager::ProtocolManager()
|
||||
{
|
||||
pthread_mutex_init(&m_events_mutex, NULL);
|
||||
pthread_mutex_init(&m_protocols_mutex, NULL);
|
||||
pthread_mutex_init(&m_asynchronous_protocols_mutex, NULL);
|
||||
pthread_mutex_init(&m_requests_mutex, NULL);
|
||||
pthread_mutex_init(&m_id_mutex, NULL);
|
||||
pthread_mutex_init(&m_exit_mutex, NULL);
|
||||
m_next_protocol_id = 0;
|
||||
|
||||
|
||||
pthread_mutex_lock(&m_exit_mutex); // will let the update function run
|
||||
/// FIXME used on server because mainloop never running
|
||||
/*if (NetworkManager::getInstance()->isServer())
|
||||
{
|
||||
m_update_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
|
||||
pthread_create(m_update_thread, NULL, protocolManagerUpdate, this);
|
||||
}*/
|
||||
// always run this one
|
||||
m_asynchronous_update_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
|
||||
pthread_create(m_asynchronous_update_thread, NULL, protocolManagerAsynchronousUpdate, this);
|
||||
}
|
||||
|
||||
ProtocolManager::~ProtocolManager()
|
||||
{
|
||||
pthread_mutex_unlock(&m_exit_mutex); // will stop the update function
|
||||
pthread_mutex_lock(&m_events_mutex);
|
||||
pthread_mutex_lock(&m_protocols_mutex);
|
||||
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
pthread_mutex_lock(&m_id_mutex);
|
||||
for (unsigned int i = 0; i < m_protocols.size() ; i++)
|
||||
delete m_protocols[i].protocol;
|
||||
for (unsigned int i = 0; i < m_events_to_process.size() ; i++)
|
||||
delete m_events_to_process[i];
|
||||
m_protocols.clear();
|
||||
m_requests.clear();
|
||||
m_events_to_process.clear();
|
||||
pthread_mutex_unlock(&m_events_mutex);
|
||||
pthread_mutex_unlock(&m_protocols_mutex);
|
||||
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
pthread_mutex_unlock(&m_id_mutex);
|
||||
|
||||
pthread_mutex_destroy(&m_events_mutex);
|
||||
pthread_mutex_destroy(&m_protocols_mutex);
|
||||
pthread_mutex_destroy(&m_asynchronous_protocols_mutex);
|
||||
pthread_mutex_destroy(&m_requests_mutex);
|
||||
pthread_mutex_destroy(&m_id_mutex);
|
||||
pthread_mutex_destroy(&m_exit_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::notifyEvent(Event* event)
|
||||
{
|
||||
pthread_mutex_lock(&m_events_mutex);
|
||||
Event* event2 = new Event(*event);
|
||||
m_events_to_process.push_back(event2); // add the event to the queue
|
||||
pthread_mutex_unlock(&m_events_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::sendMessage(Protocol* sender, const NetworkString& message, bool reliable)
|
||||
{
|
||||
NetworkString newMessage;
|
||||
newMessage.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
newMessage += message;
|
||||
NetworkManager::getInstance()->sendPacket(newMessage, reliable);
|
||||
}
|
||||
|
||||
void ProtocolManager::sendMessage(Protocol* sender, STKPeer* peer, const NetworkString& message, bool reliable)
|
||||
{
|
||||
NetworkString newMessage;
|
||||
newMessage.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
newMessage += message;
|
||||
NetworkManager::getInstance()->sendPacket(peer, newMessage, reliable);
|
||||
}
|
||||
void ProtocolManager::sendMessageExcept(Protocol* sender, STKPeer* peer, const NetworkString& message, bool reliable)
|
||||
{
|
||||
NetworkString newMessage;
|
||||
newMessage.ai8(sender->getProtocolType()); // add one byte to add protocol type
|
||||
newMessage += message;
|
||||
NetworkManager::getInstance()->sendPacketExcept(peer, newMessage, reliable);
|
||||
}
|
||||
|
||||
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;
|
||||
// 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;
|
||||
}
|
||||
|
||||
void ProtocolManager::requestStop(Protocol* protocol)
|
||||
{
|
||||
if (!protocol)
|
||||
return;
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
req.protocol_info.protocol = protocol;
|
||||
req.type = PROTOCOL_REQUEST_STOP;
|
||||
// add it to the request stack
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::requestPause(Protocol* protocol)
|
||||
{
|
||||
if (!protocol)
|
||||
return;
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
req.protocol_info.protocol = protocol;
|
||||
req.type = PROTOCOL_REQUEST_PAUSE;
|
||||
// add it to the request stack
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::requestUnpause(Protocol* protocol)
|
||||
{
|
||||
if (!protocol)
|
||||
return;
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
req.protocol_info.protocol = protocol;
|
||||
req.type = PROTOCOL_REQUEST_UNPAUSE;
|
||||
// add it to the request stack
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::requestTerminate(Protocol* protocol)
|
||||
{
|
||||
if (!protocol)
|
||||
return;
|
||||
// create the request
|
||||
ProtocolRequest req;
|
||||
req.protocol_info.protocol = protocol;
|
||||
req.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)
|
||||
{
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
return;
|
||||
}
|
||||
}
|
||||
m_requests.push_back(req);
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::startProtocol(ProtocolInfo protocol)
|
||||
{
|
||||
// add the protocol to the protocol vector so that it's updated
|
||||
pthread_mutex_lock(&m_protocols_mutex);
|
||||
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, m_protocols.size()+1);
|
||||
m_protocols.push_back(protocol);
|
||||
// setup the protocol and notify it that it's started
|
||||
protocol.protocol->setListener(this);
|
||||
protocol.protocol->setup();
|
||||
pthread_mutex_unlock(&m_protocols_mutex);
|
||||
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
|
||||
}
|
||||
void ProtocolManager::stopProtocol(ProtocolInfo protocol)
|
||||
{
|
||||
|
||||
}
|
||||
void ProtocolManager::pauseProtocol(ProtocolInfo protocol)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol == protocol.protocol && m_protocols[i].state == PROTOCOL_STATE_RUNNING)
|
||||
{
|
||||
m_protocols[i].state = PROTOCOL_STATE_PAUSED;
|
||||
m_protocols[i].protocol->pause();
|
||||
}
|
||||
}
|
||||
}
|
||||
void ProtocolManager::unpauseProtocol(ProtocolInfo protocol)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol == protocol.protocol && m_protocols[i].state == PROTOCOL_STATE_PAUSED)
|
||||
{
|
||||
m_protocols[i].state = PROTOCOL_STATE_RUNNING;
|
||||
m_protocols[i].protocol->unpause();
|
||||
}
|
||||
}
|
||||
}
|
||||
void ProtocolManager::protocolTerminated(ProtocolInfo protocol)
|
||||
{
|
||||
pthread_mutex_lock(&m_protocols_mutex); // be sure that noone accesses the protocols vector while we erase a protocol
|
||||
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
|
||||
int offset = 0;
|
||||
std::string protocol_type = typeid(*protocol.protocol).name();
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i-offset].protocol == protocol.protocol)
|
||||
{
|
||||
delete m_protocols[i].protocol;
|
||||
m_protocols.erase(m_protocols.begin()+(i-offset), m_protocols.begin()+(i-offset)+1);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
Log::info("ProtocolManager", "A %s protocol has been terminated. There are %ld protocols running.", protocol_type.c_str(), m_protocols.size());
|
||||
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
|
||||
pthread_mutex_unlock(&m_protocols_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::propagateEvent(Event* event)
|
||||
{
|
||||
PROTOCOL_TYPE searchedProtocol = PROTOCOL_NONE;
|
||||
if (event->type == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
if (event->data.size() > 0)
|
||||
searchedProtocol = (PROTOCOL_TYPE)(event->data.getAndRemoveUInt8());
|
||||
}
|
||||
if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
searchedProtocol = PROTOCOL_CONNECTION;
|
||||
}
|
||||
Log::verbose("ProtocolManager", "Received event for protocols of type %d", searchedProtocol);
|
||||
for (unsigned int i = 0; i < m_protocols.size() ; i++)
|
||||
{
|
||||
if (m_protocols[i].protocol->getProtocolType() == searchedProtocol || event->type == EVENT_TYPE_DISCONNECTED) // pass data to protocols even when paused
|
||||
m_protocols[i].protocol->notifyEvent(event);
|
||||
}
|
||||
if (searchedProtocol == PROTOCOL_NONE) // no protocol was aimed, show the msg to debug
|
||||
{
|
||||
Log::debug("ProtocolManager", "NO PROTOCOL : Message is \"%s\"", event->data.c_str());
|
||||
}
|
||||
|
||||
// because we made a copy of the event
|
||||
delete event->peer; // no more need of that
|
||||
delete event;
|
||||
}
|
||||
|
||||
void ProtocolManager::update()
|
||||
{
|
||||
// now update all protocols
|
||||
pthread_mutex_lock(&m_protocols_mutex);
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].state == PROTOCOL_STATE_RUNNING)
|
||||
m_protocols[i].protocol->update();
|
||||
}
|
||||
pthread_mutex_unlock(&m_protocols_mutex);
|
||||
}
|
||||
|
||||
void ProtocolManager::asynchronousUpdate()
|
||||
{
|
||||
// before updating, notice protocols that they have received information
|
||||
int size = m_events_to_process.size();
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
pthread_mutex_lock(&m_events_mutex); // secure threads
|
||||
Event* event = m_events_to_process.back();
|
||||
m_events_to_process.pop_back();
|
||||
pthread_mutex_unlock(&m_events_mutex); // release the mutex
|
||||
|
||||
propagateEvent(event);
|
||||
}
|
||||
|
||||
// now update all protocols that need to be updated in asynchronous mode
|
||||
pthread_mutex_lock(&m_asynchronous_protocols_mutex);
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].state == PROTOCOL_STATE_RUNNING)
|
||||
m_protocols[i].protocol->asynchronousUpdate();
|
||||
}
|
||||
pthread_mutex_unlock(&m_asynchronous_protocols_mutex);
|
||||
|
||||
// process queued events for protocols
|
||||
// these requests are asynchronous
|
||||
pthread_mutex_lock(&m_requests_mutex);
|
||||
for (unsigned int i = 0; i < m_requests.size(); i++)
|
||||
{
|
||||
switch (m_requests[i].type)
|
||||
{
|
||||
case PROTOCOL_REQUEST_START:
|
||||
startProtocol(m_requests[i].protocol_info);
|
||||
break;
|
||||
case PROTOCOL_REQUEST_STOP:
|
||||
stopProtocol(m_requests[i].protocol_info);
|
||||
break;
|
||||
case PROTOCOL_REQUEST_PAUSE:
|
||||
pauseProtocol(m_requests[i].protocol_info);
|
||||
break;
|
||||
case PROTOCOL_REQUEST_UNPAUSE:
|
||||
unpauseProtocol(m_requests[i].protocol_info);
|
||||
break;
|
||||
case PROTOCOL_REQUEST_TERMINATE:
|
||||
protocolTerminated(m_requests[i].protocol_info);
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_requests.clear();
|
||||
pthread_mutex_unlock(&m_requests_mutex);
|
||||
}
|
||||
|
||||
int ProtocolManager::runningProtocolsCount()
|
||||
{
|
||||
return m_protocols.size();
|
||||
}
|
||||
|
||||
PROTOCOL_STATE ProtocolManager::getProtocolState(uint32_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].id == id) // we know a protocol with that id
|
||||
return m_protocols[i].state; // return its state
|
||||
}
|
||||
// the protocol isn't running right now
|
||||
for (unsigned int i = 0; i < m_requests.size(); i++)
|
||||
{
|
||||
if (m_requests[i].protocol_info.id == id) // the protocol is going to be started
|
||||
return PROTOCOL_STATE_RUNNING; // we can say it's running
|
||||
}
|
||||
return PROTOCOL_STATE_TERMINATED; // else, it's already finished
|
||||
}
|
||||
|
||||
PROTOCOL_STATE ProtocolManager::getProtocolState(Protocol* protocol)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol == protocol) // the protocol is known
|
||||
return m_protocols[i].state; // return its state
|
||||
}
|
||||
for (unsigned int i = 0; i < m_requests.size(); i++)
|
||||
{
|
||||
if (m_requests[i].protocol_info.protocol == protocol) // the protocol is going to be started
|
||||
return PROTOCOL_STATE_RUNNING; // we can say it's running
|
||||
}
|
||||
return PROTOCOL_STATE_TERMINATED; // we don't know this protocol at all, it's finished
|
||||
}
|
||||
|
||||
uint32_t ProtocolManager::getProtocolID(Protocol* protocol)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol == protocol)
|
||||
return m_protocols[i].id;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
Protocol* ProtocolManager::getProtocol(uint32_t id)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].id == id)
|
||||
return m_protocols[i].protocol;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Protocol* ProtocolManager::getProtocol(PROTOCOL_TYPE type)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_protocols.size(); i++)
|
||||
{
|
||||
if (m_protocols[i].protocol->getProtocolType() == type)
|
||||
return m_protocols[i].protocol;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool ProtocolManager::isServer()
|
||||
{
|
||||
return NetworkManager::getInstance()->isServer();
|
||||
}
|
||||
|
||||
int ProtocolManager::exit()
|
||||
{
|
||||
switch(pthread_mutex_trylock(&m_exit_mutex)) {
|
||||
case 0: /* if we got the lock, unlock and return 1 (true) */
|
||||
pthread_mutex_unlock(&m_exit_mutex);
|
||||
return 1;
|
||||
case EBUSY: /* return 0 (false) if the mutex was locked */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void ProtocolManager::assignProtocolId(ProtocolInfo* protocol_info)
|
||||
{
|
||||
pthread_mutex_lock(&m_id_mutex);
|
||||
protocol_info->id = m_next_protocol_id;
|
||||
m_next_protocol_id++;
|
||||
pthread_mutex_unlock(&m_id_mutex);
|
||||
}
|
||||
|
||||
|
||||
317
src/network/protocol_manager.hpp
Normal file
317
src/network/protocol_manager.hpp
Normal file
@@ -0,0 +1,317 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file protocol_manager.hpp
|
||||
* \brief Contains structures and enumerations related to protocol management.
|
||||
*/
|
||||
|
||||
#ifndef PROTOCOL_MANAGER_HPP
|
||||
#define PROTOCOL_MANAGER_HPP
|
||||
|
||||
#include "network/singleton.hpp"
|
||||
#include "network/event.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/protocol.hpp"
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <vector>
|
||||
|
||||
/*!
|
||||
* \enum PROTOCOL_STATE
|
||||
* \brief Defines the three states that a protocol can have.
|
||||
*/
|
||||
enum PROTOCOL_STATE
|
||||
{
|
||||
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.
|
||||
};
|
||||
|
||||
/*!
|
||||
* \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 PROTOCOL_REQUEST_TYPE
|
||||
{
|
||||
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
|
||||
};
|
||||
|
||||
/*!
|
||||
* \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
|
||||
} ProtocolInfo;
|
||||
|
||||
/*!
|
||||
* \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
|
||||
} ProtocolRequest;
|
||||
|
||||
/*!
|
||||
* \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.
|
||||
*/
|
||||
class ProtocolManager : public Singleton<ProtocolManager>
|
||||
{
|
||||
friend class Singleton<ProtocolManager>;
|
||||
|
||||
public:
|
||||
/*!
|
||||
* \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 number of protocols running.
|
||||
* \return The number of protocols that are actually running.
|
||||
*/
|
||||
virtual int runningProtocolsCount();
|
||||
/*!
|
||||
* \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();
|
||||
|
||||
protected:
|
||||
// protected functions
|
||||
/*!
|
||||
* \brief Constructor
|
||||
*/
|
||||
ProtocolManager();
|
||||
/*!
|
||||
* \brief Destructor
|
||||
*/
|
||||
virtual ~ProtocolManager();
|
||||
/*!
|
||||
* \brief Assign an id to a protocol.
|
||||
* This function will assign m_next_protocol_id as the protocol id.
|
||||
* This id starts at 0 at the beginning and is increased by 1 each time
|
||||
* a protocol starts.
|
||||
* \param protocol_info : The protocol info that needs an id.
|
||||
*/
|
||||
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);
|
||||
/*!
|
||||
* \brief Stops a protocol.
|
||||
* Coes nothing. Noone can stop running protocols for now.
|
||||
* \param protocol : ProtocolInfo to stop.
|
||||
*/
|
||||
virtual void stopProtocol(ProtocolInfo protocol);
|
||||
/*!
|
||||
* \brief Pauses a protocol.
|
||||
* Pauses a protocol and tells it that it's being paused.
|
||||
* \param protocol : ProtocolInfo to pause.
|
||||
*/
|
||||
virtual void pauseProtocol(ProtocolInfo protocol);
|
||||
/*!
|
||||
* \brief Unpauses a protocol.
|
||||
* Unpauses a protocol and notifies it.
|
||||
* \param protocol : ProtocolInfo to unpause.
|
||||
*/
|
||||
virtual void unpauseProtocol(ProtocolInfo protocol);
|
||||
/*!
|
||||
* \brief Notes that a protocol is terminated.
|
||||
* Remove a protocol from the protocols vector.
|
||||
* \param protocol : ProtocolInfo concerned.
|
||||
*/
|
||||
virtual void protocolTerminated(ProtocolInfo protocol);
|
||||
|
||||
void propagateEvent(Event* event);
|
||||
|
||||
// protected members
|
||||
/*!
|
||||
* \brief Contains the running protocols.
|
||||
* This stores the protocols that are either running or paused, their
|
||||
* state and their unique id.
|
||||
*/
|
||||
std::vector<ProtocolInfo> m_protocols;
|
||||
/*!
|
||||
* \brief Contains the network events to pass to protocols.
|
||||
*/
|
||||
std::vector<Event*> m_events_to_process;
|
||||
/*!
|
||||
* \brief Contains the requests to start/stop etc... protocols.
|
||||
*/
|
||||
std::vector<ProtocolRequest> m_requests;
|
||||
/*! \brief The next id to assign to a protocol.
|
||||
* This value is incremented by 1 each time a protocol is started.
|
||||
* If a protocol has an id lower than this value, it means that it have
|
||||
* been formerly started.
|
||||
*/
|
||||
uint32_t m_next_protocol_id;
|
||||
|
||||
// mutexes:
|
||||
/*! Used to ensure that the event queue is used thread-safely. */
|
||||
pthread_mutex_t m_events_mutex;
|
||||
/*! Used to ensure that the protocol vector is used thread-safely. */
|
||||
pthread_mutex_t m_protocols_mutex;
|
||||
/*! Used to ensure that the protocol vector is used thread-safely. */
|
||||
pthread_mutex_t m_asynchronous_protocols_mutex;
|
||||
/*! Used to ensure that the request vector is used thread-safely. */
|
||||
pthread_mutex_t m_requests_mutex;
|
||||
/*! Used to ensure that the protocol id is used in a thread-safe way.*/
|
||||
pthread_mutex_t m_id_mutex;
|
||||
/*! Used when need to quit.*/
|
||||
pthread_mutex_t m_exit_mutex;
|
||||
|
||||
/*! Update thread.*/
|
||||
pthread_t* m_update_thread;
|
||||
/*! Asynchronous update thread.*/
|
||||
pthread_t* m_asynchronous_update_thread;
|
||||
|
||||
};
|
||||
|
||||
#endif // PROTOCOL_MANAGER_HPP
|
||||
457
src/network/protocols/client_lobby_room_protocol.cpp
Normal file
457
src/network/protocols/client_lobby_room_protocol.cpp
Normal file
@@ -0,0 +1,457 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/client_lobby_room_protocol.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/protocols/start_game_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/network_kart_selection.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
ClientLobbyRoomProtocol::ClientLobbyRoomProtocol(const TransportAddress& server_address)
|
||||
: LobbyRoomProtocol(NULL)
|
||||
{
|
||||
m_server_address = server_address;
|
||||
m_server = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ClientLobbyRoomProtocol::~ClientLobbyRoomProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::setup()
|
||||
{
|
||||
m_setup = NetworkManager::getInstance()->setupNewGame(); // create a new setup
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::requestKartSelection(std::string kart_name)
|
||||
{
|
||||
NetworkString request;
|
||||
// 0x02 : kart selection request, size_token (4), token, size kart name, kart name
|
||||
request.ai8(0x02).ai8(4).ai32(m_server->getClientServerToken()).ai8(kart_name.size()).as(kart_name);
|
||||
m_listener->sendMessage(this, request);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::leave()
|
||||
{
|
||||
m_server->disconnect();
|
||||
m_server_address.ip = 0;
|
||||
m_server_address.port = 0;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
assert(m_setup); // assert that the setup exists
|
||||
if (event->type == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
assert(event->data.size()); // assert that data isn't empty
|
||||
uint8_t message_type = event->data.getAndRemoveUInt8();
|
||||
|
||||
Log::info("ClientLobbyRoomProtocol", "Message of type %d", message_type);
|
||||
if (message_type == 0x01) // new player connected
|
||||
newPlayer(event);
|
||||
else if (message_type == 0x02) // player disconnected
|
||||
disconnectedPlayer(event);
|
||||
else if (message_type == 0x03) // kart selection update
|
||||
kartSelectionUpdate(event);
|
||||
else if (message_type == 0x04) // start race
|
||||
startGame(event);
|
||||
else if (message_type == 0x05) // start selection phase
|
||||
startSelection(event);
|
||||
else if (message_type == 0x80) // connection refused
|
||||
connectionRefused(event);
|
||||
else if (message_type == 0x81) // connection accepted
|
||||
connectionAccepted(event);
|
||||
else if (message_type == 0x82) // kart selection refused
|
||||
kartSelectionRefused(event);
|
||||
|
||||
} // message
|
||||
else if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
} // connection
|
||||
else if (event->type == EVENT_TYPE_DISCONNECTED) // means we left essentially
|
||||
{
|
||||
NetworkManager::getInstance()->removePeer(m_server);
|
||||
m_server = NULL;
|
||||
NetworkManager::getInstance()->disconnected();
|
||||
m_listener->requestTerminate(this);
|
||||
NetworkManager::getInstance()->reset();
|
||||
NetworkManager::getInstance()->removePeer(*event->peer); // prolly the same as m_server
|
||||
} // disconnection
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ClientLobbyRoomProtocol::update()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case NONE:
|
||||
if (NetworkManager::getInstance()->isConnectedTo(m_server_address))
|
||||
{
|
||||
m_state = LINKED;
|
||||
}
|
||||
break;
|
||||
case LINKED:
|
||||
{
|
||||
NetworkString ns;
|
||||
// 1 (connection request), 4 (size of id), global id
|
||||
ns.ai8(1).ai8(4).ai32(Online::CurrentUser::get()->getID());
|
||||
m_listener->sendMessage(this, ns);
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
} break;
|
||||
case REQUESTING_CONNECTION:
|
||||
break;
|
||||
case CONNECTED:
|
||||
break;
|
||||
case KART_SELECTION:
|
||||
{
|
||||
NetworkKartSelectionScreen* screen = NetworkKartSelectionScreen::getInstance();
|
||||
StateManager::get()->pushScreen(screen);
|
||||
m_state = SELECTING_KARTS;
|
||||
} break;
|
||||
case SELECTING_KARTS:
|
||||
break;
|
||||
case PLAYING:
|
||||
break;
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
case EXITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when a new player is connected to the server
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 7
|
||||
* ------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | 1 |
|
||||
* Data | 4 | player global id | 1 | 0 <= race id < 16 |
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::newPlayer(Event* event)
|
||||
{
|
||||
if (event->data.size() != 7 || event->data[0] != 4 || event->data[5] != 1) // 7 bytes remains now
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t global_id = event->data.gui32(1);
|
||||
uint8_t race_id = event->data.gui8(6);
|
||||
|
||||
if (global_id == Online::CurrentUser::get()->getID())
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "The server notified me that i'm a new player in the room (not normal).");
|
||||
}
|
||||
else if (m_setup->getProfile(race_id) == NULL || m_setup->getProfile(global_id) == NULL)
|
||||
{
|
||||
Log::verbose("ClientLobbyRoomProtocol", "New player connected.");
|
||||
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
|
||||
profile->kart_name = "";
|
||||
profile->race_id = race_id;
|
||||
profile->user_profile = new Online::Profile(global_id, "");
|
||||
m_setup->addPlayer(profile);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "One of the player notified in the list is myself.");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when a new player is disconnected
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* -------------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | 0 <= race id < 16 |
|
||||
* -------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::disconnectedPlayer(Event* event)
|
||||
{
|
||||
if (event->data.size() != 2 || event->data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t id = event->data[1];
|
||||
if (m_setup->removePlayer(id))
|
||||
{
|
||||
Log::info("ClientLobbyRoomProtocol", "Peer removed successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "The disconnected peer wasn't known.");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server accepts the connection.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2 3 7 8 12
|
||||
* ----------------------------------------------------------
|
||||
* Size | 1 | 1 | 1 | 4 | 1 | 4 |
|
||||
* Data | 1 | 0 <= race id < 16 | 4 | priv token | 4 | global id |
|
||||
* ----------------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::connectionAccepted(Event* event)
|
||||
{
|
||||
if (event->data.size() < 12 || event->data[0] != 1 || event->data[2] != 4 || event->data[7] != 4) // 12 bytes remains now
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying an accepted connection wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
STKPeer* peer = *(event->peer);
|
||||
|
||||
uint32_t global_id = event->data.gui32(8);
|
||||
if (global_id == Online::CurrentUser::get()->getID())
|
||||
{
|
||||
Log::info("ClientLobbyRoomProtocol", "The server accepted the connection.");
|
||||
|
||||
// self profile
|
||||
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
|
||||
profile->kart_name = "";
|
||||
profile->race_id = event->data.gui8(1);
|
||||
profile->user_profile = Online::CurrentUser::get()->getProfile();
|
||||
m_setup->addPlayer(profile);
|
||||
// connection token
|
||||
uint32_t token = event->data.gui32(3);
|
||||
peer->setClientServerToken(token);
|
||||
// add all players
|
||||
event->data.removeFront(12); // remove the 12 first bytes
|
||||
int remaining = event->data.size();
|
||||
if (remaining%7 != 0)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "ConnectionAccepted : Error in the server list");
|
||||
}
|
||||
remaining /= 7;
|
||||
for (int i = 0; i < remaining; i++)
|
||||
{
|
||||
if (event->data[0] != 1 || event->data[2] != 4)
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad format in players list.");
|
||||
uint8_t race_id = event->data[1];
|
||||
uint32_t global_id = event->data.gui32(3);
|
||||
Online::Profile* new_user = new Online::Profile(global_id, "");
|
||||
NetworkPlayerProfile* profile2 = new NetworkPlayerProfile();
|
||||
profile2->race_id = race_id;
|
||||
profile2->user_profile = new_user;
|
||||
profile2->kart_name = "";
|
||||
m_setup->addPlayer(profile2);
|
||||
event->data.removeFront(7);
|
||||
}
|
||||
|
||||
// add self
|
||||
m_server = *(event->peer);
|
||||
m_state = CONNECTED;
|
||||
}
|
||||
else
|
||||
Log::info("ClientLobbyRoomProtocol", "Failure during the connection acceptation process.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server refuses the connection.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* --------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | refusal code |
|
||||
* --------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::connectionRefused(Event* event)
|
||||
{
|
||||
if (event->data.size() != 2 || event->data[0] != 1) // 2 bytes remains now
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused connection wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->data[1]) // the second byte
|
||||
{
|
||||
case 0:
|
||||
Log::info("ClientLobbyRoomProtocol", "Connection refused : too many players.");
|
||||
break;
|
||||
case 1:
|
||||
Log::info("ClientLobbyRoomProtocol", "Connection refused : banned.");
|
||||
break;
|
||||
default:
|
||||
Log::info("ClientLobbyRoomProtocol", "Connection refused.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server refuses the kart selection request.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2
|
||||
* --------------------
|
||||
* Size | 1 | 1 |
|
||||
* Data | 1 | refusal code |
|
||||
* --------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::kartSelectionRefused(Event* event)
|
||||
{
|
||||
if (event->data.size() != 2 || event->data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused kart selection wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (event->data[1]) // the error code
|
||||
{
|
||||
case 0:
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection refused : already taken.");
|
||||
break;
|
||||
case 1:
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection refused : not available.");
|
||||
break;
|
||||
default:
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection refused.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the server tells to update a player's kart.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 2 3 N+3
|
||||
* ------------------------------------------------
|
||||
* Size | 1 | 1 | 1 | N |
|
||||
* Data | 1 | race id | N (kart name size) | kart name |
|
||||
* ------------------------------------------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::kartSelectionUpdate(Event* event)
|
||||
{
|
||||
if (event->data.size() < 3 || event->data[0] != 1)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart selection update wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t player_id = event->data[1];
|
||||
uint8_t kart_name_length = event->data[2];
|
||||
std::string data = event->data.getString(3, kart_name_length);
|
||||
if (data.size() != kart_name_length)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "Kart names sizes differ: told: %d, real: %d.", kart_name_length, data.size());
|
||||
return;
|
||||
}
|
||||
if (!m_setup->isKartAvailable(data))
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "The updated kart is taken already.");
|
||||
}
|
||||
m_setup->setPlayerKart(player_id, data);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the race needs to be started.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5
|
||||
* -------------
|
||||
* Size | 1 | 4 |
|
||||
* Data | 4 | token |
|
||||
* -------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::startGame(Event* event)
|
||||
{
|
||||
if (event->data.size() < 5 || event->data[0] != 4)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
|
||||
"selection update wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t token = event->data.gui32(1);
|
||||
if (token == NetworkManager::getInstance()->getPeers()[0]->getClientServerToken())
|
||||
{
|
||||
m_state = PLAYING;
|
||||
m_listener->requestStart(new StartGameProtocol(m_setup));
|
||||
Log::error("ClientLobbyRoomProtocol", "Starting new game");
|
||||
}
|
||||
else
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad token when starting game");
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when the kart selection starts.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5
|
||||
* -------------
|
||||
* Size | 1 | 4 |
|
||||
* Data | 4 | token |
|
||||
* -------------
|
||||
*/
|
||||
void ClientLobbyRoomProtocol::startSelection(Event* event)
|
||||
{
|
||||
if (event->data.size() < 5 || event->data[0] != 4)
|
||||
{
|
||||
Log::error("ClientLobbyRoomProtocol", "A message notifying a kart "
|
||||
"selection update wasn't formated as expected.");
|
||||
return;
|
||||
}
|
||||
uint8_t token = event->data.gui32(1);
|
||||
if (token == NetworkManager::getInstance()->getPeers()[0]->getClientServerToken())
|
||||
{
|
||||
m_state = KART_SELECTION;
|
||||
Log::info("ClientLobbyRoomProtocol", "Kart selection starts now");
|
||||
}
|
||||
else
|
||||
Log::error("ClientLobbyRoomProtocol", "Bad token");
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
49
src/network/protocols/client_lobby_room_protocol.hpp
Normal file
49
src/network/protocols/client_lobby_room_protocol.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
#ifndef CLIENT_LOBBY_ROOM_PROTOCOL_HPP
|
||||
#define CLIENT_LOBBY_ROOM_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocols/lobby_room_protocol.hpp"
|
||||
|
||||
class ClientLobbyRoomProtocol : public LobbyRoomProtocol
|
||||
{
|
||||
public:
|
||||
ClientLobbyRoomProtocol(const TransportAddress& server_address);
|
||||
virtual ~ClientLobbyRoomProtocol();
|
||||
|
||||
void requestKartSelection(std::string kart_name);
|
||||
void sendMessage(std::string message);
|
||||
void leave();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {}
|
||||
|
||||
protected:
|
||||
void newPlayer(Event* event);
|
||||
void disconnectedPlayer(Event* event);
|
||||
void connectionAccepted(Event* event); //!< Callback function on connection acceptation
|
||||
void connectionRefused(Event* event); //!< Callback function on connection refusal
|
||||
void kartSelectionRefused(Event* event);
|
||||
void kartSelectionUpdate(Event* event);
|
||||
void startGame(Event* event);
|
||||
void startSelection(Event* event);
|
||||
|
||||
TransportAddress m_server_address;
|
||||
STKPeer* m_server;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
LINKED,
|
||||
REQUESTING_CONNECTION,
|
||||
CONNECTED, // means in the lobby room
|
||||
KART_SELECTION,
|
||||
SELECTING_KARTS, // in the network kart selection screen
|
||||
PLAYING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // CLIENT_LOBBY_ROOM_PROTOCOL_HPP
|
||||
115
src/network/protocols/connect_to_peer.cpp
Normal file
115
src/network/protocols/connect_to_peer.cpp
Normal file
@@ -0,0 +1,115 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/connect_to_peer.hpp"
|
||||
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
#include "network/protocols/get_peer_address.hpp"
|
||||
#include "network/protocols/show_public_address.hpp"
|
||||
#include "network/protocols/hide_public_address.hpp"
|
||||
#include "network/protocols/request_connection.hpp"
|
||||
#include "network/protocols/ping_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToPeer::ConnectToPeer(uint32_t peer_id) :
|
||||
Protocol(NULL, PROTOCOL_CONNECTION)
|
||||
{
|
||||
m_peer_id = peer_id;
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToPeer::~ConnectToPeer()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToPeer::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
Log::debug("ConnectToPeer", "Received event notifying peer connection.");
|
||||
m_state = CONNECTED; // we received a message, we are connected
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToPeer::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
m_public_address.ip = 0;
|
||||
m_public_address.port = 0;
|
||||
m_peer_address.ip = 0;
|
||||
m_peer_address.port = 0;
|
||||
m_current_protocol_id = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToPeer::asynchronousUpdate()
|
||||
{
|
||||
switch(m_state)
|
||||
{
|
||||
case NONE:
|
||||
{
|
||||
m_current_protocol_id = m_listener->requestStart(new GetPeerAddress(m_peer_id, &m_peer_address));
|
||||
m_state = WAITING_PEER_ADDRESS;
|
||||
break;
|
||||
}
|
||||
case WAITING_PEER_ADDRESS:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // we know the peer address
|
||||
{
|
||||
if (m_peer_address.ip != 0 && m_peer_address.port != 0)
|
||||
{
|
||||
m_state = CONNECTING;
|
||||
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_peer_address, 2.0));
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ConnectToPeer", "The peer you want to connect to has hidden his address.");
|
||||
m_state = DONE;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CONNECTING: // waiting the peer to connect
|
||||
case CONNECTED:
|
||||
{
|
||||
m_listener->requestTerminate( m_listener->getProtocol(m_current_protocol_id)); // kill the ping protocol because we're connected
|
||||
m_state = DONE;
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
case EXITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
55
src/network/protocols/connect_to_peer.hpp
Normal file
55
src/network/protocols/connect_to_peer.hpp
Normal file
@@ -0,0 +1,55 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef CONNECT_TO_SERVER_HPP
|
||||
#define CONNECT_TO_SERVER_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "network/types.hpp"
|
||||
#include <string>
|
||||
|
||||
class ConnectToPeer : public Protocol, public CallbackObject
|
||||
{
|
||||
public:
|
||||
ConnectToPeer(uint32_t peer_id);
|
||||
virtual ~ConnectToPeer();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
TransportAddress m_peer_address;
|
||||
TransportAddress m_public_address;
|
||||
uint32_t m_peer_id;
|
||||
uint32_t m_current_protocol_id;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
WAITING_PEER_ADDRESS,
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // CONNECT_TO_SERVER_HPP
|
||||
192
src/network/protocols/connect_to_server.cpp
Normal file
192
src/network/protocols/connect_to_server.cpp
Normal file
@@ -0,0 +1,192 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
#include "network/protocols/get_peer_address.hpp"
|
||||
#include "network/protocols/show_public_address.hpp"
|
||||
#include "network/protocols/hide_public_address.hpp"
|
||||
#include "network/protocols/request_connection.hpp"
|
||||
#include "network/protocols/ping_protocol.hpp"
|
||||
#include "network/protocols/quick_join_protocol.hpp"
|
||||
#include "network/protocols/client_lobby_room_protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToServer::ConnectToServer() :
|
||||
Protocol(NULL, PROTOCOL_CONNECTION)
|
||||
{
|
||||
m_server_id = 0;
|
||||
m_quick_join = true;
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
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_quick_join = false;
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
ConnectToServer::~ConnectToServer()
|
||||
{
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToServer::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
Log::info("ConnectToServer", "The Connect To Server protocol has "
|
||||
"received an event notifying that he's connected to the peer.");
|
||||
m_state = CONNECTED; // we received a message, we are connected
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToServer::setup()
|
||||
{
|
||||
Log::info("ConnectToServer", "SETUPP");
|
||||
m_state = NONE;
|
||||
m_public_address.ip = 0;
|
||||
m_public_address.port = 0;
|
||||
m_server_address.ip = 0;
|
||||
m_server_address.port = 0;
|
||||
m_current_protocol_id = 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void ConnectToServer::asynchronousUpdate()
|
||||
{
|
||||
switch(m_state)
|
||||
{
|
||||
case NONE:
|
||||
{
|
||||
Log::info("ConnectToServer", "Protocol starting");
|
||||
m_current_protocol_id = m_listener->requestStart(new GetPublicAddress(&m_public_address));
|
||||
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
|
||||
{
|
||||
m_state = SHOWING_SELF_ADDRESS;
|
||||
NetworkManager::getInstance()->setPublicAddress(m_public_address); // set our public address
|
||||
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
|
||||
{
|
||||
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_state = REQUESTING_CONNECTION;
|
||||
}
|
||||
else
|
||||
{
|
||||
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
|
||||
{
|
||||
m_state = REQUESTING_CONNECTION;
|
||||
m_current_protocol_id = m_listener->requestStart(new RequestConnection(m_server_id));
|
||||
Log::info("ConnectToServer", "Server's address known");
|
||||
}
|
||||
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.ip == 0 || m_server_address.port == 0)
|
||||
{ // server data not correct, hide address and stop
|
||||
m_state = HIDING_ADDRESS;
|
||||
m_current_protocol_id = m_listener->requestStart(new HidePublicAddress());
|
||||
return;
|
||||
}
|
||||
m_state = CONNECTING;
|
||||
m_current_protocol_id = m_listener->requestStart(new PingProtocol(m_server_address, 2.0));
|
||||
}
|
||||
break;
|
||||
case CONNECTING: // waiting the server to answer our connection
|
||||
{
|
||||
static double timer = 0;
|
||||
if (StkTime::getRealTime() > timer+5.0) // every 5 seconds
|
||||
{
|
||||
timer = StkTime::getRealTime();
|
||||
NetworkManager::getInstance()->connect(m_server_address);
|
||||
Log::info("ConnectToServer", "Trying to connect");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CONNECTED:
|
||||
{
|
||||
Log::info("ConnectToServer", "Connected");
|
||||
m_listener->requestTerminate( m_listener->getProtocol(m_current_protocol_id)); // kill the ping protocol because we're connected
|
||||
m_current_protocol_id = m_listener->requestStart(new HidePublicAddress());
|
||||
ClientNetworkManager::getInstance()->setConnected(true);
|
||||
m_state = HIDING_ADDRESS;
|
||||
break;
|
||||
}
|
||||
case HIDING_ADDRESS:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id)
|
||||
== PROTOCOL_STATE_TERMINATED) // we have hidden our address
|
||||
{
|
||||
Log::info("ConnectToServer", "Address hidden");
|
||||
m_state = DONE;
|
||||
if (ClientNetworkManager::getInstance()->isConnected()) // lobby room protocol if we're connected only
|
||||
m_listener->requestStart(new ClientLobbyRoomProtocol(m_server_address));
|
||||
}
|
||||
break;
|
||||
case DONE:
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
61
src/network/protocols/connect_to_server.hpp
Normal file
61
src/network/protocols/connect_to_server.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef CONNECT_TO_SERVER_HPP
|
||||
#define CONNECT_TO_SERVER_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "network/types.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();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
TransportAddress m_server_address;
|
||||
TransportAddress m_public_address;
|
||||
uint32_t m_server_id;
|
||||
uint32_t m_host_id;
|
||||
uint32_t m_current_protocol_id;
|
||||
bool m_quick_join;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
GETTING_SELF_ADDRESS,
|
||||
SHOWING_SELF_ADDRESS,
|
||||
GETTING_SERVER_ADDRESS,
|
||||
REQUESTING_CONNECTION,
|
||||
CONNECTING,
|
||||
CONNECTED,
|
||||
HIDING_ADDRESS,
|
||||
DONE
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // CONNECT_TO_SERVER_HPP
|
||||
168
src/network/protocols/controller_events_protocol.cpp
Normal file
168
src/network/protocols/controller_events_protocol.cpp
Normal file
@@ -0,0 +1,168 @@
|
||||
#include "network/protocols/controller_events_protocol.hpp"
|
||||
|
||||
#include "modes/world.hpp"
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ControllerEventsProtocol::ControllerEventsProtocol() :
|
||||
Protocol(NULL, PROTOCOL_CONTROLLER_EVENTS)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ControllerEventsProtocol::~ControllerEventsProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControllerEventsProtocol::setup()
|
||||
{
|
||||
m_self_controller_index = 0;
|
||||
std::vector<AbstractKart*> karts = World::getWorld()->getKarts();
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
for (unsigned int i = 0; i < karts.size(); i++)
|
||||
{
|
||||
if (karts[i]->getIdent() == NetworkWorld::getInstance()->m_self_kart)
|
||||
{
|
||||
Log::info("ControllerEventsProtocol", "My id is %d", i);
|
||||
m_self_controller_index = i;
|
||||
}
|
||||
STKPeer* peer = NULL;
|
||||
if (m_listener->isServer())
|
||||
{
|
||||
for (unsigned int j = 0; j < peers.size(); j++)
|
||||
{
|
||||
if (peers[j]->getPlayerProfile()->kart_name == karts[i]->getIdent())
|
||||
{
|
||||
peer = peers[j];
|
||||
}
|
||||
Log::info("ControllerEventsProtocol", "Compared %s and %s",
|
||||
peers[j]->getPlayerProfile()->kart_name.c_str(), karts[i]->getIdent().c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (peers.size() > 0)
|
||||
peer = peers[0];
|
||||
}
|
||||
if (peer == NULL)
|
||||
{
|
||||
Log::error("ControllerEventsProtocol", "Couldn't find the peer corresponding to the kart.");
|
||||
}
|
||||
m_controllers.push_back(std::pair<Controller*, STKPeer*>(karts[i]->getController(), peer));
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControllerEventsProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->data.size() < 17)
|
||||
{
|
||||
Log::error("ControllerEventsProtocol", "The data supplied was not complete. Size was %d.", event->data.size());
|
||||
return;
|
||||
}
|
||||
uint32_t token = event->data.gui32();
|
||||
NetworkString pure_message = event->data;
|
||||
pure_message.removeFront(4);
|
||||
if (token != (*event->peer)->getClientServerToken())
|
||||
{
|
||||
Log::error("ControllerEventsProtocol", "Bad token from peer.");
|
||||
return;
|
||||
}
|
||||
NetworkString ns = pure_message;
|
||||
float event_timestamp = ns.getFloat();
|
||||
ns.removeFront(4);
|
||||
uint8_t client_index = -1;
|
||||
while (ns.size() >= 9)
|
||||
{
|
||||
uint8_t controller_index = ns.gui8();
|
||||
client_index = controller_index;
|
||||
uint8_t serialized_1 = ns.gui8(1), serialized_2 = ns.gui8(2), serialized_3 = ns.gui8(3);
|
||||
PlayerAction action = (PlayerAction)(ns.gui8(4));
|
||||
int action_value = ns.gui32(5);
|
||||
|
||||
KartControl* controls = m_controllers[controller_index].first->getControls();
|
||||
controls->m_brake = (serialized_1 & 0x40)!=0;
|
||||
controls->m_nitro = (serialized_1 & 0x20)!=0;
|
||||
controls->m_rescue = (serialized_1 & 0x10)!=0;
|
||||
controls->m_fire = (serialized_1 & 0x08)!=0;
|
||||
controls->m_look_back = (serialized_1 & 0x04)!=0;
|
||||
controls->m_skid = KartControl::SkidControl(serialized_1 & 0x03);
|
||||
|
||||
m_controllers[controller_index].first->action(action, action_value);
|
||||
ns.removeFront(9);
|
||||
//Log::info("ControllerEventProtocol", "Registered one action.");
|
||||
}
|
||||
if (ns.size() > 0 && ns.size() != 9)
|
||||
{
|
||||
Log::warn("ControllerEventProtocol", "The data seems corrupted. Remains %d", ns.size());
|
||||
return;
|
||||
}
|
||||
if (client_index < 0)
|
||||
{
|
||||
Log::warn("ControllerEventProtocol", "Couldn't have a client id.");
|
||||
return;
|
||||
}
|
||||
if (m_listener->isServer())
|
||||
{
|
||||
// notify everybody of the event :
|
||||
for (unsigned int i = 0; i < m_controllers.size(); i++)
|
||||
{
|
||||
if (i == client_index) // don't send that message to the sender
|
||||
continue;
|
||||
NetworkString ns2;
|
||||
ns2.ai32(m_controllers[i].second->getClientServerToken());
|
||||
ns2 += pure_message;
|
||||
m_listener->sendMessage(this, m_controllers[i].second, ns2, false);
|
||||
//Log::info("ControllerEventsProtocol", "Sizes are %d and %d", ns2.size(), pure_message.size());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControllerEventsProtocol::update()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ControllerEventsProtocol::controllerAction(Controller* controller,
|
||||
PlayerAction action, int value)
|
||||
{
|
||||
assert(!m_listener->isServer());
|
||||
|
||||
KartControl* controls = controller->getControls();
|
||||
uint8_t serialized_1 = 0;
|
||||
serialized_1 |= (controls->m_brake==true);
|
||||
serialized_1 <<= 1;
|
||||
serialized_1 |= (controls->m_nitro==true);
|
||||
serialized_1 <<= 1;
|
||||
serialized_1 |= (controls->m_rescue==true);
|
||||
serialized_1 <<= 1;
|
||||
serialized_1 |= (controls->m_fire==true);
|
||||
serialized_1 <<= 1;
|
||||
serialized_1 |= (controls->m_look_back==true);
|
||||
serialized_1 <<= 2;
|
||||
serialized_1 += controls->m_skid;
|
||||
uint8_t serialized_2 = (uint8_t)(controls->m_accel*255.0);
|
||||
uint8_t serialized_3 = (uint8_t)(controls->m_steer*127.0);
|
||||
|
||||
NetworkString ns;
|
||||
ns.ai32(m_controllers[m_self_controller_index].second->getClientServerToken());
|
||||
ns.af(World::getWorld()->getTime());
|
||||
ns.ai8(m_self_controller_index);
|
||||
ns.ai8(serialized_1).ai8(serialized_2).ai8(serialized_3);
|
||||
ns.ai8((uint8_t)(action)).ai32(value);
|
||||
|
||||
m_listener->sendMessage(this, ns, false); // send message to server
|
||||
}
|
||||
|
||||
|
||||
28
src/network/protocols/controller_events_protocol.hpp
Normal file
28
src/network/protocols/controller_events_protocol.hpp
Normal file
@@ -0,0 +1,28 @@
|
||||
#ifndef CONTROLLER_EVENTS_PROTOCOL_HPP
|
||||
#define CONTROLLER_EVENTS_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "input/input.hpp"
|
||||
#include "karts/controller/controller.hpp"
|
||||
|
||||
class ControllerEventsProtocol : public Protocol
|
||||
{
|
||||
protected:
|
||||
std::vector<std::pair<Controller*, STKPeer*> > m_controllers;
|
||||
uint32_t m_self_controller_index;
|
||||
|
||||
public:
|
||||
ControllerEventsProtocol();
|
||||
virtual ~ControllerEventsProtocol();
|
||||
|
||||
virtual void setup();
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {}
|
||||
|
||||
void controllerAction(Controller* controller, PlayerAction action, int value);
|
||||
|
||||
};
|
||||
|
||||
#endif // CONTROLLER_EVENTS_PROTOCOL_HPP
|
||||
21
src/network/protocols/game_events_protocol.cpp
Normal file
21
src/network/protocols/game_events_protocol.cpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#include "network/protocols/game_events_protocol.hpp"
|
||||
|
||||
GameEventsProtocol::GameEventsProtocol() : Protocol(NULL, PROTOCOL_GAME_EVENTS)
|
||||
{
|
||||
}
|
||||
|
||||
GameEventsProtocol::~GameEventsProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void GameEventsProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void GameEventsProtocol::setup()
|
||||
{
|
||||
}
|
||||
|
||||
void GameEventsProtocol::update()
|
||||
{
|
||||
}
|
||||
21
src/network/protocols/game_events_protocol.hpp
Normal file
21
src/network/protocols/game_events_protocol.hpp
Normal file
@@ -0,0 +1,21 @@
|
||||
#ifndef GAME_EVENTS_PROTOCOL_HPP
|
||||
#define GAME_EVENTS_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
|
||||
class GameEventsProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
GameEventsProtocol();
|
||||
virtual ~GameEventsProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {}
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
#endif // GAME_EVENTS_PROTOCOL_HPP
|
||||
99
src/network/protocols/get_peer_address.cpp
Normal file
99
src/network/protocols/get_peer_address.cpp
Normal file
@@ -0,0 +1,99 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/get_peer_address.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/http_functions.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
GetPeerAddress::GetPeerAddress(uint32_t peer_id, CallbackObject* callback_object) : Protocol(callback_object, PROTOCOL_SILENT)
|
||||
{
|
||||
m_peer_id = peer_id;
|
||||
}
|
||||
|
||||
GetPeerAddress::~GetPeerAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void GetPeerAddress::notifyEvent(Event* event)
|
||||
{
|
||||
// nothing there. If we receive events, they must be ignored
|
||||
}
|
||||
|
||||
void GetPeerAddress::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
m_request = NULL;
|
||||
}
|
||||
|
||||
void GetPeerAddress::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("peer_id",m_peer_id);
|
||||
m_request->setParameter("action","get");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if (rec_success == "yes")
|
||||
{
|
||||
TransportAddress* addr = static_cast<TransportAddress*>(m_callback_object);
|
||||
result->get("ip", &addr->ip);
|
||||
result->get("port", &addr->port);
|
||||
Log::debug("GetPeerAddress", "Address gotten successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("GetPeerAddress", "Fail to get address.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("GetPeerAddress", "Fail to get address.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
||||
|
||||
void GetPeerAddress::setPeerID(uint32_t peer_id)
|
||||
{
|
||||
m_peer_id = peer_id;
|
||||
}
|
||||
51
src/network/protocols/get_peer_address.hpp
Normal file
51
src/network/protocols/get_peer_address.hpp
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef GET_PEER_ADDRESS_HPP
|
||||
#define GET_PEER_ADDRESS_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
|
||||
class GetPeerAddress : public Protocol
|
||||
{
|
||||
public:
|
||||
GetPeerAddress(uint32_t peer_id, CallbackObject* callback_object);
|
||||
virtual ~GetPeerAddress();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
void setPeerID(uint32_t m_peer_id);
|
||||
protected:
|
||||
uint32_t m_peer_id;
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
|
||||
};
|
||||
|
||||
#endif // GET_PEER_ADDRESS_HPP
|
||||
210
src/network/protocols/get_public_address.cpp
Normal file
210
src/network/protocols/get_public_address.cpp
Normal file
@@ -0,0 +1,210 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/client_network_manager.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "network/network_interface.hpp"
|
||||
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
int stunRand()
|
||||
{
|
||||
static bool init = false;
|
||||
if (!init)
|
||||
{
|
||||
srand((unsigned int)time(NULL));
|
||||
init = true;
|
||||
}
|
||||
return rand();
|
||||
}
|
||||
|
||||
GetPublicAddress::GetPublicAddress(CallbackObject* callback_object) : Protocol(callback_object, PROTOCOL_SILENT)
|
||||
{
|
||||
}
|
||||
|
||||
GetPublicAddress::~GetPublicAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void GetPublicAddress::notifyEvent(Event* event)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void GetPublicAddress::setup()
|
||||
{
|
||||
m_state = NOTHING_DONE;
|
||||
}
|
||||
|
||||
void GetPublicAddress::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NOTHING_DONE)
|
||||
{
|
||||
// format : 00MMMMMCMMMCMMMM (cf rfc 5389)
|
||||
uint16_t message_type = 0x0001; // binding request
|
||||
m_stun_tansaction_id[0] = stunRand();
|
||||
m_stun_tansaction_id[1] = stunRand();
|
||||
m_stun_tansaction_id[2] = stunRand();
|
||||
uint16_t message_length = 0x0000;
|
||||
|
||||
uint8_t bytes[21]; // the message to be sent
|
||||
// bytes 0-1 : the type of the message,
|
||||
bytes[0] = (uint8_t)(message_type>>8);
|
||||
bytes[1] = (uint8_t)(message_type);
|
||||
|
||||
// bytes 2-3 : message length added to header (attributes)
|
||||
bytes[2] = (uint8_t)(message_length>>8);
|
||||
bytes[3] = (uint8_t)(message_length);
|
||||
|
||||
// bytes 4-7 : magic cookie to recognize the stun protocol
|
||||
bytes[4] = (uint8_t)(m_stun_magic_cookie>>24);
|
||||
bytes[5] = (uint8_t)(m_stun_magic_cookie>>16);
|
||||
bytes[6] = (uint8_t)(m_stun_magic_cookie>>8);
|
||||
bytes[7] = (uint8_t)(m_stun_magic_cookie);
|
||||
|
||||
// bytes 8-19 : the transaction id
|
||||
bytes[8] = (uint8_t)(m_stun_tansaction_id[0]>>24);
|
||||
bytes[9] = (uint8_t)(m_stun_tansaction_id[0]>>16);
|
||||
bytes[10] = (uint8_t)(m_stun_tansaction_id[0]>>8);
|
||||
bytes[11] = (uint8_t)(m_stun_tansaction_id[0]);
|
||||
bytes[12] = (uint8_t)(m_stun_tansaction_id[1]>>24);
|
||||
bytes[13] = (uint8_t)(m_stun_tansaction_id[1]>>16);
|
||||
bytes[14] = (uint8_t)(m_stun_tansaction_id[1]>>8);
|
||||
bytes[15] = (uint8_t)(m_stun_tansaction_id[1]);
|
||||
bytes[16] = (uint8_t)(m_stun_tansaction_id[2]>>24);
|
||||
bytes[17] = (uint8_t)(m_stun_tansaction_id[2]>>16);
|
||||
bytes[18] = (uint8_t)(m_stun_tansaction_id[2]>>8);
|
||||
bytes[19] = (uint8_t)(m_stun_tansaction_id[2]);
|
||||
bytes[20] = '\0';
|
||||
|
||||
Log::verbose("GetPublicAddress", "Querrying STUN server 132.177.123.6");
|
||||
unsigned int dst = (132<<24)+(177<<16)+(123<<8)+6;
|
||||
NetworkManager::getInstance()->setManualSocketsMode(true);
|
||||
NetworkManager::getInstance()->getHost()->sendRawPacket(bytes, 20, TransportAddress(dst, 3478));
|
||||
m_state = TEST_SENT;
|
||||
}
|
||||
if (m_state == TEST_SENT)
|
||||
{
|
||||
unsigned int dst = (132<<24)+(177<<16)+(123<<8)+6;
|
||||
uint8_t* data = NetworkManager::getInstance()->getHost()->receiveRawPacket(TransportAddress(dst, 3478));
|
||||
assert(data);
|
||||
|
||||
// check that the stun response is a response, contains the magic cookie and the transaction ID
|
||||
if ( data[0] == 0x01 &&
|
||||
data[1] == 0x01 &&
|
||||
data[4] == (uint8_t)(m_stun_magic_cookie>>24) &&
|
||||
data[5] == (uint8_t)(m_stun_magic_cookie>>16) &&
|
||||
data[6] == (uint8_t)(m_stun_magic_cookie>>8) &&
|
||||
data[7] == (uint8_t)(m_stun_magic_cookie) )
|
||||
{
|
||||
if(
|
||||
data[8] == (uint8_t)(m_stun_tansaction_id[0]>>24) &&
|
||||
data[9] == (uint8_t)(m_stun_tansaction_id[0]>>16) &&
|
||||
data[10] == (uint8_t)(m_stun_tansaction_id[0]>>8 ) &&
|
||||
data[11] == (uint8_t)(m_stun_tansaction_id[0] ) &&
|
||||
data[12] == (uint8_t)(m_stun_tansaction_id[1]>>24) &&
|
||||
data[13] == (uint8_t)(m_stun_tansaction_id[1]>>16) &&
|
||||
data[14] == (uint8_t)(m_stun_tansaction_id[1]>>8 ) &&
|
||||
data[15] == (uint8_t)(m_stun_tansaction_id[1] ) &&
|
||||
data[16] == (uint8_t)(m_stun_tansaction_id[2]>>24) &&
|
||||
data[17] == (uint8_t)(m_stun_tansaction_id[2]>>16) &&
|
||||
data[18] == (uint8_t)(m_stun_tansaction_id[2]>>8 ) &&
|
||||
data[19] == (uint8_t)(m_stun_tansaction_id[2] ))
|
||||
{
|
||||
Log::verbose("GetPublicAddress", "The STUN server responded with a valid answer");
|
||||
int message_size = data[2]*256+data[3];
|
||||
|
||||
// parse the stun message now:
|
||||
bool finish = false;
|
||||
uint8_t* attributes = data+20;
|
||||
if (message_size == 0)
|
||||
{
|
||||
Log::error("GetPublicAddress", "STUN answer does not contain any information.");
|
||||
finish = true;
|
||||
}
|
||||
if (message_size < 4) // cannot even read the size
|
||||
{
|
||||
Log::error("GetPublicAddress", "STUN message is not valid.");
|
||||
finish = true;
|
||||
}
|
||||
uint16_t port;
|
||||
uint32_t address;
|
||||
bool valid = false;
|
||||
while(!finish)
|
||||
{
|
||||
int type = attributes[0]*256+attributes[1];
|
||||
int size = attributes[2]*256+attributes[3];
|
||||
switch(type)
|
||||
{
|
||||
case 0:
|
||||
case 1:
|
||||
assert(size == 8);
|
||||
assert(attributes[5] = 0x01); // IPv4 only
|
||||
port = attributes[6]*256+attributes[7];
|
||||
address = (attributes[8]<<24 & 0xFF000000)+(attributes[9]<<16 & 0x00FF0000)+(attributes[10]<<8 & 0x0000FF00)+(attributes[11] & 0x000000FF);
|
||||
finish = true;
|
||||
valid = true;
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
attributes = attributes + 4 + size;
|
||||
message_size -= 4 + size;
|
||||
if (message_size == 0)
|
||||
finish = true;
|
||||
if (message_size < 4) // cannot even read the size
|
||||
{
|
||||
Log::error("GetPublicAddress", "STUN message is not valid.");
|
||||
finish = true;
|
||||
}
|
||||
}
|
||||
// finished parsing, we know our public transport address
|
||||
if (valid)
|
||||
{
|
||||
Log::debug("GetPublicAddress", "The public address has been found : %i.%i.%i.%i:%i", address>>24&0xff, address>>16&0xff, address>>8&0xff, address&0xff, port);
|
||||
m_state = ADDRESS_KNOWN;
|
||||
NetworkManager::getInstance()->setManualSocketsMode(false);
|
||||
TransportAddress* addr = static_cast<TransportAddress*>(m_callback_object);
|
||||
addr->ip = address;
|
||||
addr->port = port;
|
||||
}
|
||||
else
|
||||
m_state = NOTHING_DONE; // need to re-send the stun request
|
||||
}
|
||||
else
|
||||
{
|
||||
m_state = NOTHING_DONE; // need to re-send the stun request
|
||||
}
|
||||
}
|
||||
}
|
||||
if (m_state == ADDRESS_KNOWN)
|
||||
{
|
||||
m_state = EXITING;
|
||||
// terminate the protocol
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
if (m_state == EXITING)
|
||||
{
|
||||
}
|
||||
}
|
||||
49
src/network/protocols/get_public_address.hpp
Normal file
49
src/network/protocols/get_public_address.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef GET_PUBLIC_ADDRESS_HPP
|
||||
#define GET_PUBLIC_ADDRESS_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
class GetPublicAddress : public Protocol
|
||||
{
|
||||
public:
|
||||
GetPublicAddress(CallbackObject* callback_object);
|
||||
virtual ~GetPublicAddress();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
enum STATE
|
||||
{
|
||||
NOTHING_DONE,
|
||||
TEST_SENT,
|
||||
ADDRESS_KNOWN,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
uint32_t m_stun_tansaction_id[3];
|
||||
static const uint32_t m_stun_magic_cookie = 0x2112A442;
|
||||
};
|
||||
|
||||
#endif // GET_PUBLIC_ADDRESS_HPP
|
||||
86
src/network/protocols/hide_public_address.cpp
Normal file
86
src/network/protocols/hide_public_address.cpp
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/hide_public_address.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
HidePublicAddress::HidePublicAddress() : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
}
|
||||
|
||||
HidePublicAddress::~HidePublicAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void HidePublicAddress::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void HidePublicAddress::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void HidePublicAddress::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("action","unset");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if(rec_success == "yes")
|
||||
{
|
||||
Log::debug("ShowPublicAddress", "Address hidden successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ShowPublicAddress", "Fail to hide address.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ShowPublicAddress", "Fail to hide address.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
||||
49
src/network/protocols/hide_public_address.hpp
Normal file
49
src/network/protocols/hide_public_address.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HIDE_PUBLIC_ADDRESS_HPP
|
||||
#define HIDE_PUBLIC_ADDRESS_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
#include <string>
|
||||
|
||||
class HidePublicAddress : public Protocol
|
||||
{
|
||||
public:
|
||||
HidePublicAddress();
|
||||
virtual ~HidePublicAddress();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // HIDE_PUBLIC_ADDRESS_HPP
|
||||
134
src/network/protocols/kart_update_protocol.cpp
Normal file
134
src/network/protocols/kart_update_protocol.cpp
Normal file
@@ -0,0 +1,134 @@
|
||||
#include "network/protocols/kart_update_protocol.hpp"
|
||||
|
||||
#include "karts/abstract_kart.hpp"
|
||||
#include "modes/world.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
|
||||
KartUpdateProtocol::KartUpdateProtocol()
|
||||
: Protocol(NULL, PROTOCOL_KART_UPDATE)
|
||||
{
|
||||
m_karts = World::getWorld()->getKarts();
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
//if (m_karts[i]->getWorldKartId())
|
||||
{
|
||||
Log::info("KartUpdateProtocol", "Kart %d has id %d and name %s", i, m_karts[i]->getWorldKartId(), m_karts[i]->getIdent().c_str());
|
||||
}
|
||||
if (m_karts[i]->getIdent() == NetworkWorld::getInstance()->m_self_kart)
|
||||
{
|
||||
Log::info("KartUpdateProtocol", "My id is %d", i);
|
||||
m_self_kart_index = i;
|
||||
}
|
||||
}
|
||||
pthread_mutex_init(&m_positions_updates_mutex, NULL);
|
||||
}
|
||||
|
||||
KartUpdateProtocol::~KartUpdateProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void KartUpdateProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->type != EVENT_TYPE_MESSAGE)
|
||||
return;
|
||||
NetworkString ns = event->data;
|
||||
if (ns.size() < 36)
|
||||
{
|
||||
Log::info("KartUpdateProtocol", "Message too short.");
|
||||
return;
|
||||
}
|
||||
ns.removeFront(4);
|
||||
while(ns.size() >= 16)
|
||||
{
|
||||
uint32_t kart_id = ns.getUInt32(0);
|
||||
|
||||
float a,b,c;
|
||||
a = ns.getFloat(4);
|
||||
b = ns.getFloat(8);
|
||||
c = ns.getFloat(12);
|
||||
float d,e,f,g;
|
||||
d = ns.getFloat(16);
|
||||
e = ns.getFloat(20);
|
||||
f = ns.getFloat(24);
|
||||
g = ns.getFloat(28);
|
||||
pthread_mutex_trylock(&m_positions_updates_mutex);
|
||||
m_next_positions.push_back(Vec3(a,b,c));
|
||||
m_next_quaternions.push_back(btQuaternion(d,e,f,g));
|
||||
m_karts_ids.push_back(kart_id);
|
||||
pthread_mutex_unlock(&m_positions_updates_mutex);
|
||||
ns.removeFront(32);
|
||||
}
|
||||
}
|
||||
|
||||
void KartUpdateProtocol::setup()
|
||||
{
|
||||
}
|
||||
|
||||
void KartUpdateProtocol::update()
|
||||
{
|
||||
static double time = 0;
|
||||
double current_time = StkTime::getRealTime();
|
||||
if (current_time > time + 0.1) // 10 updates per second
|
||||
{
|
||||
time = current_time;
|
||||
if (m_listener->isServer())
|
||||
{
|
||||
NetworkString ns;
|
||||
ns.af( World::getWorld()->getTime());
|
||||
for (unsigned int i = 0; i < m_karts.size(); i++)
|
||||
{
|
||||
AbstractKart* kart = m_karts[i];
|
||||
Vec3 v = kart->getXYZ();
|
||||
btQuaternion quat = kart->getRotation();
|
||||
ns.ai32( kart->getWorldKartId());
|
||||
ns.af(v[0]).af(v[1]).af(v[2]); // add position
|
||||
ns.af(quat.x()).af(quat.y()).af(quat.z()).af(quat.w()); // add rotation
|
||||
Log::verbose("KartUpdateProtocol", "Sending %d's positions %f %f %f", kart->getWorldKartId(), v[0], v[1], v[2]);
|
||||
}
|
||||
m_listener->sendMessage(this, ns, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
AbstractKart* kart = m_karts[m_self_kart_index];
|
||||
Vec3 v = kart->getXYZ();
|
||||
btQuaternion quat = kart->getRotation();
|
||||
NetworkString ns;
|
||||
ns.af( World::getWorld()->getTime());
|
||||
ns.ai32( kart->getWorldKartId());
|
||||
ns.af(v[0]).af(v[1]).af(v[2]); // add position
|
||||
ns.af(quat.x()).af(quat.y()).af(quat.z()).af(quat.w()); // add rotation
|
||||
Log::verbose("KartUpdateProtocol", "Sending %d's positions %f %f %f", kart->getWorldKartId(), v[0], v[1], v[2]);
|
||||
m_listener->sendMessage(this, ns, false);
|
||||
}
|
||||
}
|
||||
switch(pthread_mutex_trylock(&m_positions_updates_mutex))
|
||||
{
|
||||
case 0: /* if we got the lock */
|
||||
while (!m_next_positions.empty())
|
||||
{
|
||||
uint32_t id = m_karts_ids.back();
|
||||
if (id != m_self_kart_index || m_listener->isServer()) // server takes all updates
|
||||
{
|
||||
Vec3 pos = m_next_positions.back();
|
||||
btTransform transform = m_karts[id]->getBody()->getInterpolationWorldTransform();
|
||||
transform.setOrigin(pos);
|
||||
transform.setRotation(m_next_quaternions.back());
|
||||
m_karts[id]->getBody()->setCenterOfMassTransform(transform);
|
||||
//m_karts[id]->getBody()->setLinearVelocity(Vec3(0,0,0));
|
||||
Log::verbose("KartUpdateProtocol", "Update kart %i pos to %f %f %f", id, pos[0], pos[1], pos[2]);
|
||||
}
|
||||
m_next_positions.pop_back();
|
||||
m_next_quaternions.pop_back();
|
||||
m_karts_ids.pop_back();
|
||||
}
|
||||
pthread_mutex_unlock(&m_positions_updates_mutex);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
33
src/network/protocols/kart_update_protocol.hpp
Normal file
33
src/network/protocols/kart_update_protocol.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef KART_UPDATE_PROTOCOL_HPP
|
||||
#define KART_UPDATE_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "utils/vec3.hpp"
|
||||
#include "LinearMath/btQuaternion.h"
|
||||
#include <list>
|
||||
|
||||
class AbstractKart;
|
||||
|
||||
class KartUpdateProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
KartUpdateProtocol();
|
||||
virtual ~KartUpdateProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {};
|
||||
|
||||
protected:
|
||||
std::vector<AbstractKart*> m_karts;
|
||||
uint32_t m_self_kart_index;
|
||||
|
||||
std::list<Vec3> m_next_positions;
|
||||
std::list<btQuaternion> m_next_quaternions;
|
||||
std::list<uint32_t> m_karts_ids;
|
||||
|
||||
pthread_mutex_t m_positions_updates_mutex;
|
||||
};
|
||||
|
||||
#endif // KART_UPDATE_PROTOCOL_HPP
|
||||
31
src/network/protocols/lobby_room_protocol.cpp
Normal file
31
src/network/protocols/lobby_room_protocol.cpp
Normal file
@@ -0,0 +1,31 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/lobby_room_protocol.hpp"
|
||||
|
||||
LobbyRoomProtocol::LobbyRoomProtocol(CallbackObject* callback_object) :
|
||||
Protocol(callback_object, PROTOCOL_LOBBY_ROOM)
|
||||
{
|
||||
m_setup = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
LobbyRoomProtocol::~LobbyRoomProtocol()
|
||||
{
|
||||
}
|
||||
47
src/network/protocols/lobby_room_protocol.hpp
Normal file
47
src/network/protocols/lobby_room_protocol.hpp
Normal file
@@ -0,0 +1,47 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef LOBBY_ROOM_PROTOCOL_HPP
|
||||
#define LOBBY_ROOM_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
|
||||
/*!
|
||||
* \class LobbyRoomProtocol
|
||||
* \brief Class used while the game is being prepared.
|
||||
* This protocol starts when a server opens a game, or when a client joins a game.
|
||||
* It is used to exchange data about the race settings, like kart selection.
|
||||
*/
|
||||
class LobbyRoomProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
LobbyRoomProtocol(CallbackObject* callback_object);
|
||||
virtual ~LobbyRoomProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event) = 0;
|
||||
virtual void setup() = 0;
|
||||
virtual void update() = 0;
|
||||
|
||||
protected:
|
||||
GameSetup* m_setup; //!< The game setup.
|
||||
};
|
||||
|
||||
#endif // LOBBY_ROOM_PROTOCOL_HPP
|
||||
52
src/network/protocols/ping_protocol.cpp
Normal file
52
src/network/protocols/ping_protocol.cpp
Normal file
@@ -0,0 +1,52 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/ping_protocol.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
PingProtocol::PingProtocol(const TransportAddress& ping_dst, double delay_between_pings) : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
m_ping_dst = ping_dst;
|
||||
m_delay_between_pings = delay_between_pings;
|
||||
}
|
||||
|
||||
PingProtocol::~PingProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void PingProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void PingProtocol::setup()
|
||||
{
|
||||
m_last_ping_time = 0;
|
||||
}
|
||||
|
||||
void PingProtocol::asynchronousUpdate()
|
||||
{
|
||||
if (StkTime::getRealTime() > m_last_ping_time+m_delay_between_pings)
|
||||
{
|
||||
m_last_ping_time = StkTime::getRealTime();
|
||||
uint8_t data = 0;
|
||||
NetworkManager::getInstance()->getHost()->sendRawPacket(&data, 1, m_ping_dst);
|
||||
Log::info("PingProtocol", "Ping message sent");
|
||||
}
|
||||
}
|
||||
24
src/network/protocols/ping_protocol.hpp
Normal file
24
src/network/protocols/ping_protocol.hpp
Normal file
@@ -0,0 +1,24 @@
|
||||
#ifndef PING_PROTOCOL_HPP
|
||||
#define PING_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
|
||||
|
||||
class PingProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
PingProtocol(const TransportAddress& ping_dst, double delay_between_pings);
|
||||
virtual ~PingProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
TransportAddress m_ping_dst;
|
||||
double m_delay_between_pings;
|
||||
double m_last_ping_time;
|
||||
};
|
||||
|
||||
#endif // PING_PROTOCOL_HPP
|
||||
92
src/network/protocols/quick_join_protocol.cpp
Normal file
92
src/network/protocols/quick_join_protocol.cpp
Normal file
@@ -0,0 +1,92 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "quick_join_protocol.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
QuickJoinProtocol::QuickJoinProtocol(CallbackObject* callback_object, uint32_t* server_id) : Protocol(callback_object, PROTOCOL_SILENT)
|
||||
{
|
||||
m_server_id = server_id;
|
||||
}
|
||||
|
||||
QuickJoinProtocol::~QuickJoinProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void QuickJoinProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void QuickJoinProtocol::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void QuickJoinProtocol::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("action","quick-join");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
TransportAddress* res = static_cast<TransportAddress*>(m_callback_object);
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if(rec_success == "yes")
|
||||
{
|
||||
result->get("ip", &res->ip);
|
||||
result->get("port", &res->port);
|
||||
result->get("hostid", m_server_id);
|
||||
Log::info("QuickJoinProtocol", "Quick joining %d:%d (server#%d).", res->ip, res->port, *m_server_id);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("QuickJoinProtocol", "Fail to quick join.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("QuickJoinProtocol", "Fail to quick join.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
||||
31
src/network/protocols/quick_join_protocol.hpp
Normal file
31
src/network/protocols/quick_join_protocol.hpp
Normal file
@@ -0,0 +1,31 @@
|
||||
#ifndef QUICK_JOIN_PROTOCOL_HPP
|
||||
#define QUICK_JOIN_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
|
||||
class QuickJoinProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
QuickJoinProtocol(CallbackObject* callback_object, uint32_t* server_id);
|
||||
virtual ~QuickJoinProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
uint32_t* m_server_id;
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // QUICK_JOIN_PROTOCOL_HPP
|
||||
97
src/network/protocols/request_connection.cpp
Normal file
97
src/network/protocols/request_connection.cpp
Normal file
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/request_connection.hpp"
|
||||
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
|
||||
RequestConnection::RequestConnection(uint32_t server_id) : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
m_server_id = server_id;
|
||||
}
|
||||
|
||||
RequestConnection::~RequestConnection()
|
||||
{
|
||||
}
|
||||
|
||||
void RequestConnection::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void RequestConnection::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void RequestConnection::asynchronousUpdate()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case NONE:
|
||||
{
|
||||
m_request = new Online::CurrentUser::ServerJoinRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("server_id",m_server_id);
|
||||
m_request->setParameter("action","request-connection");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
break;
|
||||
}
|
||||
case REQUEST_PENDING:
|
||||
{
|
||||
if (!m_request->isDone())
|
||||
return;
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if (rec_success == "yes")
|
||||
{
|
||||
Log::debug("RequestConnection", "Connection Request made successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("RequestConnection", "Fail to make a request to connecto to server %d", m_server_id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("RequestConnection", "Fail to make a request.");
|
||||
}
|
||||
m_state = DONE;
|
||||
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
case EXITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
32
src/network/protocols/request_connection.hpp
Normal file
32
src/network/protocols/request_connection.hpp
Normal file
@@ -0,0 +1,32 @@
|
||||
#ifndef REQUEST_CONNECTION_HPP
|
||||
#define REQUEST_CONNECTION_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
|
||||
class RequestConnection : public Protocol
|
||||
{
|
||||
public:
|
||||
RequestConnection(uint32_t server_id);
|
||||
virtual ~RequestConnection();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
uint32_t m_server_id;
|
||||
Online::CurrentUser::ServerJoinRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
|
||||
};
|
||||
|
||||
#endif // REQUEST_CONNECTION_HPP
|
||||
369
src/network/protocols/server_lobby_room_protocol.cpp
Normal file
369
src/network/protocols/server_lobby_room_protocol.cpp
Normal file
@@ -0,0 +1,369 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/server_lobby_room_protocol.hpp"
|
||||
|
||||
#include "network/server_network_manager.hpp"
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
#include "network/protocols/show_public_address.hpp"
|
||||
#include "network/protocols/connect_to_peer.hpp"
|
||||
#include "network/protocols/start_server.hpp"
|
||||
#include "network/protocols/start_game_protocol.hpp"
|
||||
|
||||
#include "online/current_user.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/time.hpp"
|
||||
#include "utils/random_generator.hpp"
|
||||
|
||||
ServerLobbyRoomProtocol::ServerLobbyRoomProtocol() : LobbyRoomProtocol(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
ServerLobbyRoomProtocol::~ServerLobbyRoomProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ServerLobbyRoomProtocol::setup()
|
||||
{
|
||||
m_setup = NetworkManager::getInstance()->setupNewGame(); // create a new setup
|
||||
m_next_id = 0;
|
||||
m_state = NONE;
|
||||
m_public_address.ip = 0;
|
||||
m_public_address.port = 0;
|
||||
m_selection_enabled = false;
|
||||
Log::info("ServerLobbyRoomProtocol", "Starting the protocol.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ServerLobbyRoomProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
assert(m_setup); // assert that the setup exists
|
||||
if (event->type == EVENT_TYPE_MESSAGE)
|
||||
{
|
||||
assert(event->data.size()); // message not empty
|
||||
uint8_t message_type;
|
||||
message_type = event->data.getAndRemoveUInt8();
|
||||
Log::info("ServerLobbyRoomProtocol", "Message received with type %d.", message_type);
|
||||
if (message_type == 0x01) // player requesting connection
|
||||
connectionRequested(event);
|
||||
if (message_type == 0x02) // player requesting kart selection
|
||||
kartSelectionRequested(event);
|
||||
} // if (event->type == EVENT_TYPE_MESSAGE)
|
||||
else if (event->type == EVENT_TYPE_CONNECTED)
|
||||
{
|
||||
} // if (event->type == EVENT_TYPE_CONNECTED)
|
||||
else if (event->type == EVENT_TYPE_DISCONNECTED)
|
||||
{
|
||||
kartDisconnected(event);
|
||||
} // if (event->type == EVENT_TYPE_DISCONNECTED)
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ServerLobbyRoomProtocol::update()
|
||||
{
|
||||
switch (m_state)
|
||||
{
|
||||
case NONE:
|
||||
m_current_protocol_id = m_listener->requestStart(new GetPublicAddress(&m_public_address));
|
||||
m_state = GETTING_PUBLIC_ADDRESS;
|
||||
break;
|
||||
case GETTING_PUBLIC_ADDRESS:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id) == PROTOCOL_STATE_TERMINATED)
|
||||
{
|
||||
NetworkManager::getInstance()->setPublicAddress(m_public_address);
|
||||
m_current_protocol_id = m_listener->requestStart(new StartServer());
|
||||
m_state = LAUNCHING_SERVER;
|
||||
Log::debug("ServerLobbyRoomProtocol", "Public address known.");
|
||||
}
|
||||
break;
|
||||
case LAUNCHING_SERVER:
|
||||
if (m_listener->getProtocolState(m_current_protocol_id) == PROTOCOL_STATE_TERMINATED)
|
||||
{
|
||||
m_state = WORKING;
|
||||
Log::info("ServerLobbyRoomProtocol", "Server setup");
|
||||
}
|
||||
break;
|
||||
case WORKING:
|
||||
{
|
||||
// first poll every 5 seconds
|
||||
static double last_poll_time = 0;
|
||||
if (StkTime::getRealTime() > last_poll_time+10.0)
|
||||
{
|
||||
last_poll_time = StkTime::getRealTime();
|
||||
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
|
||||
Online::XMLRequest* request = new Online::XMLRequest();
|
||||
request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
request->setParameter("id",Online::CurrentUser::get()->getID());
|
||||
request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
request->setParameter("address",addr.ip);
|
||||
request->setParameter("port",addr.port);
|
||||
request->setParameter("action","poll-connection-requests");
|
||||
|
||||
Online::HTTPManager::get()->synchronousRequest(request);
|
||||
assert(request->isDone());
|
||||
|
||||
const XMLNode * result = request->getResult();
|
||||
std::string rec_success;
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if(rec_success == "yes")
|
||||
{
|
||||
const XMLNode * users_xml = result->getNode("users");
|
||||
uint32_t id = 0;
|
||||
for (unsigned int i = 0; i < users_xml->getNumNodes(); i++)
|
||||
{
|
||||
users_xml->getNode(i)->get("id", &id);
|
||||
Log::debug("ServerLobbyRoomProtocol", "User with id %d wants to connect.", id);
|
||||
m_incoming_peers_ids.push_back(id);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobbyRoomProtocol", "Error while reading the list.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ServerLobbyRoomProtocol", "Cannot retrieve the list.");
|
||||
}
|
||||
delete request;
|
||||
}
|
||||
|
||||
// now
|
||||
for (unsigned int i = 0; i < m_incoming_peers_ids.size(); i++)
|
||||
{
|
||||
m_listener->requestStart(new ConnectToPeer(m_incoming_peers_ids[i]));
|
||||
}
|
||||
m_incoming_peers_ids.clear();
|
||||
|
||||
break;
|
||||
}
|
||||
case DONE:
|
||||
m_state = EXITING;
|
||||
m_listener->requestTerminate(this);
|
||||
break;
|
||||
case EXITING:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ServerLobbyRoomProtocol::startGame()
|
||||
{
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns;
|
||||
ns.ai8(0x04).ai8(4).ai32(peers[i]->getClientServerToken()); // start game
|
||||
m_listener->sendMessage(this, peers[i], ns, true); // reliably
|
||||
}
|
||||
m_listener->requestStart(new StartGameProtocol(m_setup));
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ServerLobbyRoomProtocol::startSelection()
|
||||
{
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns;
|
||||
ns.ai8(0x05).ai8(4).ai32(peers[i]->getClientServerToken()); // start selection
|
||||
m_listener->sendMessage(this, peers[i], ns, true); // reliably
|
||||
}
|
||||
m_selection_enabled = true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void ServerLobbyRoomProtocol::kartDisconnected(Event* event)
|
||||
{
|
||||
STKPeer* peer = *(event->peer);
|
||||
if (peer->getPlayerProfile() != NULL) // others knew him
|
||||
{
|
||||
NetworkString msg;
|
||||
msg.ai8(0x02).ai8(1).ai8(peer->getPlayerProfile()->race_id);
|
||||
m_listener->sendMessage(this, msg);
|
||||
Log::info("ServerLobbyRoomProtocol", "Player disconnected : id %d",
|
||||
peer->getPlayerProfile()->race_id);
|
||||
m_setup->removePlayer(peer->getPlayerProfile()->race_id);
|
||||
NetworkManager::getInstance()->removePeer(peer);
|
||||
}
|
||||
else
|
||||
Log::info("ServerLobbyRoomProtocol", "The DC peer wasn't registered.");
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when a player asks for a connection.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5
|
||||
* ------------------------
|
||||
* Size | 1 | 4 |
|
||||
* Data | 4 | global player id |
|
||||
* ------------------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::connectionRequested(Event* event)
|
||||
{
|
||||
STKPeer* peer = *(event->peer);
|
||||
if (event->data.size() != 5 || event->data[0] != 4)
|
||||
{
|
||||
Log::warn("ServerLobbyRoomProtocol", "The server is sending a badly formated message. Size is %d and first byte %d", event->data.size(), event->data[0]);
|
||||
return;
|
||||
}
|
||||
uint32_t player_id = 0;
|
||||
player_id = event->data.getUInt32(1);
|
||||
// can we add the player ?
|
||||
if (m_setup->getPlayerCount() < 16) // accept player
|
||||
{
|
||||
// add the player to the game setup
|
||||
while(m_setup->getProfile(m_next_id)!=NULL)
|
||||
m_next_id++;
|
||||
// notify everybody that there is a new player
|
||||
NetworkString message;
|
||||
// new player (1) -- size of id -- id -- size of local id -- local id;
|
||||
message.ai8(1).ai8(4).ai32(player_id).ai8(1).ai8(m_next_id);
|
||||
m_listener->sendMessageExcept(this, peer, message);
|
||||
|
||||
/// now answer to the peer that just connected
|
||||
RandomGenerator token_generator;
|
||||
// use 4 random numbers because rand_max is probably 2^15-1.
|
||||
uint32_t token = (uint32_t)(((token_generator.get(RAND_MAX)<<24) & 0xff) +
|
||||
((token_generator.get(RAND_MAX)<<16) & 0xff) +
|
||||
((token_generator.get(RAND_MAX)<<8) & 0xff) +
|
||||
((token_generator.get(RAND_MAX) & 0xff)));
|
||||
|
||||
// send a message to the one that asked to connect
|
||||
NetworkString message_ack;
|
||||
// connection success (129) -- size of token -- token
|
||||
message_ack.ai8(0x81).ai8(1).ai8(m_next_id).ai8(4).ai32(token).ai8(4).ai32(player_id);
|
||||
// add all players so that this user knows
|
||||
std::vector<NetworkPlayerProfile*> players = m_setup->getPlayers();
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
// do not make a duplicate of the player
|
||||
if (players[i]->race_id != m_next_id && players[i]->user_profile->getID() != player_id)
|
||||
message_ack.ai8(1).ai8(players[i]->race_id).ai8(4).ai32(players[i]->user_profile->getID());
|
||||
}
|
||||
m_listener->sendMessage(this, peer, message_ack);
|
||||
|
||||
peer->setClientServerToken(token);
|
||||
|
||||
NetworkPlayerProfile* profile = new NetworkPlayerProfile();
|
||||
profile->race_id = m_next_id;
|
||||
profile->kart_name = "";
|
||||
profile->user_profile = new Online::Profile(player_id, "");
|
||||
m_setup->addPlayer(profile);
|
||||
peer->setPlayerProfile(profile);
|
||||
Log::verbose("ServerLobbyRoomProtocol", "New player.");
|
||||
} // accept player
|
||||
else // refuse the connection with code 0 (too much players)
|
||||
{
|
||||
NetworkString message;
|
||||
message.ai8(0x80); // 128 means connection refused
|
||||
message.ai8(1); // 1 bytes for the error code
|
||||
message.ai8(0); // 0 = too much players
|
||||
// send only to the peer that made the request
|
||||
m_listener->sendMessage(this, peer, message);
|
||||
Log::verbose("ServerLobbyRoomProtocol", "Player refused");
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
/*! \brief Called when a player asks to select a kart.
|
||||
* \param event : Event providing the information.
|
||||
*
|
||||
* Format of the data :
|
||||
* Byte 0 1 5 6 N+6
|
||||
* ---------------------------------------------------
|
||||
* Size | 1 | 4 | 1 | N |
|
||||
* Data | 4 | priv token | N (kart name size) | kart name |
|
||||
* ---------------------------------------------------
|
||||
*/
|
||||
void ServerLobbyRoomProtocol::kartSelectionRequested(Event* event)
|
||||
{
|
||||
if (event->data.size() < 6 || event->data[0] != 4)
|
||||
{
|
||||
Log::warn("ServerLobbyRoomProtocol", "The server is sending a badly "
|
||||
"formated message. Size is %d and first byte %d",
|
||||
event->data.size(), event->data[0]);
|
||||
return;
|
||||
}
|
||||
STKPeer* peer = *(event->peer);
|
||||
uint32_t token = event->data.gui32(1);
|
||||
if (token != peer->getClientServerToken())
|
||||
{
|
||||
Log::warn("ServerLobbyRoomProtocol", "Peer sending bad token. Request "
|
||||
"aborted.");
|
||||
return;
|
||||
}
|
||||
uint8_t kart_name_size = event->data.gui8(5);
|
||||
std::string kart_name = event->data.gs(6, kart_name_size);
|
||||
if (kart_name.size() != kart_name_size)
|
||||
{
|
||||
Log::error("ServerLobbyRoomProtocol", "Kart names sizes differ: told:"
|
||||
"%d, real: %d.", kart_name_size, kart_name.size());
|
||||
return;
|
||||
}
|
||||
// check if selection is possible
|
||||
if (!m_selection_enabled)
|
||||
{
|
||||
NetworkString answer;
|
||||
answer.ai8(0x82).ai8(1).ai8(2); // selection still not started
|
||||
m_listener->sendMessage(this, peer, answer);
|
||||
return;
|
||||
}
|
||||
// check if somebody picked that kart
|
||||
if (!m_setup->isKartAvailable(kart_name))
|
||||
{
|
||||
NetworkString answer;
|
||||
answer.ai8(0x82).ai8(1).ai8(0); // kart is already taken
|
||||
m_listener->sendMessage(this, peer, answer);
|
||||
return;
|
||||
}
|
||||
// check if this kart is authorized
|
||||
if (!m_setup->isKartAllowed(kart_name))
|
||||
{
|
||||
NetworkString answer;
|
||||
answer.ai8(0x82).ai8(1).ai8(1); // kart is not authorized
|
||||
m_listener->sendMessage(this, peer, answer);
|
||||
return;
|
||||
}
|
||||
// send a kart update to everyone
|
||||
NetworkString answer;
|
||||
// kart update (3), 1, race id
|
||||
answer.ai8(0x03).ai8(1).ai8(peer->getPlayerProfile()->race_id);
|
||||
// kart name size, kart name
|
||||
answer.ai8(kart_name.size()).as(kart_name);
|
||||
m_listener->sendMessage(this, answer);
|
||||
m_setup->setPlayerKart(peer->getPlayerProfile()->race_id, kart_name);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
43
src/network/protocols/server_lobby_room_protocol.hpp
Normal file
43
src/network/protocols/server_lobby_room_protocol.hpp
Normal file
@@ -0,0 +1,43 @@
|
||||
#ifndef SERVER_LOBBY_ROOM_PROTOCOL_HPP
|
||||
#define SERVER_LOBBY_ROOM_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocols/lobby_room_protocol.hpp"
|
||||
|
||||
class ServerLobbyRoomProtocol : public LobbyRoomProtocol
|
||||
{
|
||||
public:
|
||||
ServerLobbyRoomProtocol();
|
||||
virtual ~ServerLobbyRoomProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {};
|
||||
|
||||
void startGame();
|
||||
void startSelection();
|
||||
|
||||
protected:
|
||||
void kartDisconnected(Event* event);
|
||||
void connectionRequested(Event* event);
|
||||
void kartSelectionRequested(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;
|
||||
TransportAddress m_public_address;
|
||||
bool m_selection_enabled;
|
||||
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
GETTING_PUBLIC_ADDRESS,
|
||||
LAUNCHING_SERVER,
|
||||
WORKING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
#endif // SERVER_LOBBY_ROOM_PROTOCOL_HPP
|
||||
89
src/network/protocols/show_public_address.cpp
Normal file
89
src/network/protocols/show_public_address.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/show_public_address.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
ShowPublicAddress::ShowPublicAddress() : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
}
|
||||
|
||||
ShowPublicAddress::~ShowPublicAddress()
|
||||
{
|
||||
}
|
||||
|
||||
void ShowPublicAddress::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void ShowPublicAddress::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void ShowPublicAddress::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("address",addr.ip);
|
||||
m_request->setParameter("port",addr.port);
|
||||
m_request->setParameter("action","set");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if(rec_success == "yes")
|
||||
{
|
||||
Log::debug("ShowPublicAddress", "Address shown successfully.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ShowPublicAddress", "Fail to show address.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("ShowPublicAddress", "Fail to show address.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
||||
49
src/network/protocols/show_public_address.hpp
Normal file
49
src/network/protocols/show_public_address.hpp
Normal file
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef SHOW_PUBLIC_ADDRESS_HPP
|
||||
#define SHOW_PUBLIC_ADDRESS_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
#include <string>
|
||||
|
||||
class ShowPublicAddress : public Protocol
|
||||
{
|
||||
public:
|
||||
ShowPublicAddress();
|
||||
virtual ~ShowPublicAddress();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // HIDE_PUBLIC_ADDRESS_HPP
|
||||
199
src/network/protocols/start_game_protocol.cpp
Normal file
199
src/network/protocols/start_game_protocol.cpp
Normal file
@@ -0,0 +1,199 @@
|
||||
#include "network/protocols/start_game_protocol.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/protocol_manager.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include "network/network_world.hpp"
|
||||
#include "network/protocols/synchronization_protocol.hpp"
|
||||
#include "race/race_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
#include "input/device_manager.hpp"
|
||||
#include "input/input_manager.hpp"
|
||||
#include "challenges/unlock_manager.hpp"
|
||||
#include "states_screens/state_manager.hpp"
|
||||
#include "states_screens/kart_selection.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
|
||||
StartGameProtocol::StartGameProtocol(GameSetup* game_setup) :
|
||||
Protocol(NULL, PROTOCOL_START_GAME)
|
||||
{
|
||||
m_game_setup = game_setup;
|
||||
std::vector<NetworkPlayerProfile*> players = m_game_setup->getPlayers();
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
m_player_states.insert(std::pair<NetworkPlayerProfile*, STATE>(players[i], LOADING));
|
||||
}
|
||||
m_ready_count = 0;
|
||||
}
|
||||
|
||||
StartGameProtocol::~StartGameProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
void StartGameProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->data.size() < 5)
|
||||
{
|
||||
Log::error("StartGameProtocol", "Too short message.");
|
||||
return;
|
||||
}
|
||||
uint32_t token = event->data.gui32();
|
||||
uint8_t ready = event->data.gui8(4);
|
||||
STKPeer* peer = (*(event->peer));
|
||||
if (peer->getClientServerToken() != token)
|
||||
{
|
||||
Log::error("StartGameProtocol", "Bad token received.");
|
||||
return;
|
||||
}
|
||||
if (m_listener->isServer() && ready) // on server, player is ready
|
||||
{
|
||||
Log::info("StartGameProtocol", "One of the players is ready.");
|
||||
m_player_states[peer->getPlayerProfile()] = READY;
|
||||
m_ready_count++;
|
||||
if (m_ready_count == m_game_setup->getPlayerCount())
|
||||
{
|
||||
// everybody ready, synchronize
|
||||
SynchronizationProtocol* protocol = static_cast<SynchronizationProtocol*>(m_listener->getProtocol(PROTOCOL_SYNCHRONIZATION));
|
||||
if (protocol)
|
||||
{
|
||||
protocol->startCountdown(5000); // 5 seconds countdown
|
||||
Log::info("StartGameProtocol", "All players ready, starting countdown.");
|
||||
m_ready = true;
|
||||
return;
|
||||
}
|
||||
else
|
||||
Log::error("StartGameProtocol", "The Synchronization protocol hasn't been started.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("StartGameProtocol", "Received a message with bad format.");
|
||||
}
|
||||
// on the client, we shouldn't even receive messages.
|
||||
}
|
||||
|
||||
void StartGameProtocol::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
m_ready_count = 0;
|
||||
m_ready = false;
|
||||
Log::info("SynchronizationProtocol", "Ready !");
|
||||
}
|
||||
|
||||
bool sort_karts (NetworkPlayerProfile* a, NetworkPlayerProfile* b)
|
||||
{ return (a->race_id < b->race_id); }
|
||||
|
||||
void StartGameProtocol::update()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
// if no synchronization protocol exists, create one
|
||||
m_listener->requestStart(new SynchronizationProtocol());
|
||||
Log::info("StartGameProtocol", "SynchronizationProtocol started.");
|
||||
// race startup sequence
|
||||
|
||||
NetworkWorld::getInstance<NetworkWorld>()->start(); // builds it and starts
|
||||
race_manager->setNumKarts(m_game_setup->getPlayerCount());
|
||||
race_manager->setNumPlayers(m_game_setup->getPlayerCount());
|
||||
race_manager->setNumLocalPlayers(1);
|
||||
std::vector<NetworkPlayerProfile*> players = m_game_setup->getPlayers();
|
||||
std::sort(players.begin(), players.end(), sort_karts);
|
||||
// have to add self first
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
bool is_me = (players[i]->user_profile == Online::CurrentUser::get()->getProfile());
|
||||
if (is_me)
|
||||
{
|
||||
NetworkPlayerProfile* profile = players[i];
|
||||
RemoteKartInfo rki(profile->race_id, profile->kart_name,
|
||||
profile->user_profile->getUserName(), profile->race_id, !is_me);
|
||||
rki.setGlobalPlayerId(profile->race_id);
|
||||
rki.setLocalPlayerId(is_me?0:1);
|
||||
rki.setHostId(profile->race_id);
|
||||
PlayerProfile* profileToUse = unlock_manager->getCurrentPlayer();
|
||||
assert(profileToUse);
|
||||
InputDevice* device = input_manager->getDeviceList()->getLatestUsedDevice();
|
||||
int new_player_id = StateManager::get()->createActivePlayer( profileToUse, device , players[i]->user_profile);
|
||||
device->setPlayer(StateManager::get()->getActivePlayer(new_player_id));
|
||||
input_manager->getDeviceList()->setSinglePlayer(StateManager::get()->getActivePlayer(new_player_id));
|
||||
|
||||
race_manager->setPlayerKart(i, rki);
|
||||
race_manager->setLocalKartInfo(new_player_id, profile->kart_name);
|
||||
Log::info("StartGameProtocol", "Self player device added."); // self config
|
||||
NetworkWorld::getInstance()->m_self_kart = profile->kart_name;
|
||||
}
|
||||
}
|
||||
for (unsigned int i = 0; i < players.size(); i++)
|
||||
{
|
||||
bool is_me = (players[i]->user_profile == Online::CurrentUser::get()->getProfile());
|
||||
NetworkPlayerProfile* profile = players[i];
|
||||
RemoteKartInfo rki(profile->race_id, profile->kart_name,
|
||||
profile->user_profile->getUserName(), profile->race_id, !is_me);
|
||||
rki.setGlobalPlayerId(profile->race_id);
|
||||
// on the server, the race id must be the local one.
|
||||
rki.setLocalPlayerId(m_listener->isServer()?profile->race_id:(is_me?0:1));
|
||||
rki.setHostId(profile->race_id);
|
||||
Log::info("StartGameProtocol", "Creating kart %s for Player#%d with race_id %d", profile->kart_name.c_str(), i, profile->race_id);
|
||||
|
||||
if (!is_me)
|
||||
{
|
||||
StateManager::get()->createActivePlayer( NULL, NULL , players[i]->user_profile);
|
||||
|
||||
race_manager->setPlayerKart(i, rki);
|
||||
}
|
||||
}
|
||||
race_manager->computeRandomKartList();
|
||||
Log::info("StartGameProtocol", "Player configuration ready.");
|
||||
m_state = SYNCHRONIZATION_WAIT;
|
||||
/*
|
||||
KartSelectionScreen* s = KartSelectionScreen::getInstance();
|
||||
s->setMultiplayer(false);
|
||||
s->setFromOverworld(false);
|
||||
StateManager::get()->pushScreen( s );*/
|
||||
}
|
||||
else if (m_state == SYNCHRONIZATION_WAIT)
|
||||
{
|
||||
SynchronizationProtocol* protocol = static_cast<SynchronizationProtocol*>
|
||||
(m_listener->getProtocol(PROTOCOL_SYNCHRONIZATION));
|
||||
if (protocol)
|
||||
{
|
||||
// now the synchronization protocol exists.
|
||||
Log::info("StartGameProtocol", "Starting the race loading.");
|
||||
race_manager->startSingleRace("jungle", 1, false);
|
||||
m_state = LOADING;
|
||||
}
|
||||
}
|
||||
else if (m_state == LOADING)
|
||||
{
|
||||
if (m_ready)
|
||||
{
|
||||
m_state = READY;
|
||||
}
|
||||
}
|
||||
else if (m_state == READY)
|
||||
{
|
||||
m_state = EXITING;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
||||
|
||||
void StartGameProtocol::ready() // on clients, means the loading is finished
|
||||
{
|
||||
if (!m_listener->isServer()) // if we're a client
|
||||
{
|
||||
assert(NetworkManager::getInstance()->getPeerCount() == 1);
|
||||
NetworkString ns;
|
||||
ns.ai32(NetworkManager::getInstance()->getPeers()[0]->getClientServerToken()).ai8(1);
|
||||
Log::info("StartGameProtocol", "Player ready, notifying server.");
|
||||
m_listener->sendMessage(this, ns, true);
|
||||
m_state = READY;
|
||||
m_ready = true;
|
||||
return;
|
||||
}
|
||||
else // on the server
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
36
src/network/protocols/start_game_protocol.hpp
Normal file
36
src/network/protocols/start_game_protocol.hpp
Normal file
@@ -0,0 +1,36 @@
|
||||
#ifndef START_GAME_PROTOCOL_HPP
|
||||
#define START_GAME_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include <map>
|
||||
|
||||
class GameSetup;
|
||||
class NetworkPlayerProfile;
|
||||
|
||||
class StartGameProtocol : public Protocol
|
||||
{
|
||||
protected:
|
||||
enum STATE { NONE, SYNCHRONIZATION_WAIT, LOADING, READY, EXITING };
|
||||
std::map<NetworkPlayerProfile*, STATE> m_player_states;
|
||||
|
||||
GameSetup* m_game_setup;
|
||||
int m_ready_count;
|
||||
double m_sending_time;
|
||||
|
||||
STATE m_state;
|
||||
bool m_ready;
|
||||
|
||||
public:
|
||||
StartGameProtocol(GameSetup* game_setup);
|
||||
virtual ~StartGameProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update();
|
||||
virtual void asynchronousUpdate() {}
|
||||
|
||||
void ready();
|
||||
|
||||
};
|
||||
|
||||
#endif // START_GAME_PROTOCOL_HPP
|
||||
89
src/network/protocols/start_server.cpp
Normal file
89
src/network/protocols/start_server.cpp
Normal file
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/start_server.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
|
||||
StartServer::StartServer() : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
}
|
||||
|
||||
StartServer::~StartServer()
|
||||
{
|
||||
}
|
||||
|
||||
void StartServer::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void StartServer::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void StartServer::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("address",addr.ip);
|
||||
m_request->setParameter("port",addr.port);
|
||||
m_request->setParameter("max_players",UserConfigParams::m_server_max_players);
|
||||
m_request->setParameter("action","start-server");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if(rec_success == "yes")
|
||||
{
|
||||
Log::info("StartServer", "Server is now online.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("StartServer", "Fail to start server.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("StartServer", "Fail to start server.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
||||
34
src/network/protocols/start_server.hpp
Normal file
34
src/network/protocols/start_server.hpp
Normal file
@@ -0,0 +1,34 @@
|
||||
#ifndef START_SERVER_HPP
|
||||
#define START_SERVER_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
|
||||
/*!
|
||||
* This protocol tells to the database that the server is up and running,
|
||||
* and shows online the public IP:port that stores the NetworkManager.
|
||||
*/
|
||||
class StartServer : public Protocol
|
||||
{
|
||||
public:
|
||||
StartServer();
|
||||
virtual ~StartServer();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // START_SERVER_HPP
|
||||
88
src/network/protocols/stop_server.cpp
Normal file
88
src/network/protocols/stop_server.cpp
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/protocols/stop_server.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "online/current_user.hpp"
|
||||
#include "online/http_manager.hpp"
|
||||
#include "config/user_config.hpp"
|
||||
|
||||
StopServer::StopServer() : Protocol(NULL, PROTOCOL_SILENT)
|
||||
{
|
||||
}
|
||||
|
||||
StopServer::~StopServer()
|
||||
{
|
||||
}
|
||||
|
||||
void StopServer::notifyEvent(Event* event)
|
||||
{
|
||||
}
|
||||
|
||||
void StopServer::setup()
|
||||
{
|
||||
m_state = NONE;
|
||||
}
|
||||
|
||||
void StopServer::asynchronousUpdate()
|
||||
{
|
||||
if (m_state == NONE)
|
||||
{
|
||||
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
|
||||
m_request = new Online::XMLRequest();
|
||||
m_request->setURL((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
|
||||
m_request->setParameter("id",Online::CurrentUser::get()->getID());
|
||||
m_request->setParameter("token",Online::CurrentUser::get()->getToken());
|
||||
m_request->setParameter("address",addr.ip);
|
||||
m_request->setParameter("port",addr.port);
|
||||
m_request->setParameter("action","stop-server");
|
||||
|
||||
Online::HTTPManager::get()->addRequest(m_request);
|
||||
m_state = REQUEST_PENDING;
|
||||
}
|
||||
else if (m_state == REQUEST_PENDING && m_request->isDone())
|
||||
{
|
||||
const XMLNode * result = m_request->getResult();
|
||||
std::string rec_success;
|
||||
|
||||
if(result->get("success", &rec_success))
|
||||
{
|
||||
if(rec_success == "yes")
|
||||
{
|
||||
Log::info("StopServer", "Server is now offline.");
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("StopServer", "Fail to stop server.");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Log::error("StopServer", "Fail to stop server.");
|
||||
}
|
||||
m_state = DONE;
|
||||
}
|
||||
else if (m_state == DONE)
|
||||
{
|
||||
m_state = EXITING;
|
||||
delete m_request;
|
||||
m_request = NULL;
|
||||
m_listener->requestTerminate(this);
|
||||
}
|
||||
}
|
||||
33
src/network/protocols/stop_server.hpp
Normal file
33
src/network/protocols/stop_server.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#ifndef STOP_SERVER_HPP
|
||||
#define STOP_SERVER_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include "online/request.hpp"
|
||||
|
||||
/*! \brief Removes the server info from the database
|
||||
*/
|
||||
|
||||
class StopServer : public Protocol
|
||||
{
|
||||
public:
|
||||
StopServer();
|
||||
virtual ~StopServer();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
protected:
|
||||
Online::XMLRequest* m_request;
|
||||
enum STATE
|
||||
{
|
||||
NONE,
|
||||
REQUEST_PENDING,
|
||||
DONE,
|
||||
EXITING
|
||||
};
|
||||
STATE m_state;
|
||||
};
|
||||
|
||||
#endif // STOP_SERVER_HPP
|
||||
179
src/network/protocols/synchronization_protocol.cpp
Normal file
179
src/network/protocols/synchronization_protocol.cpp
Normal file
@@ -0,0 +1,179 @@
|
||||
#include "network/protocols/synchronization_protocol.hpp"
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
#include "network/protocols/kart_update_protocol.hpp"
|
||||
#include "network/protocols/controller_events_protocol.hpp"
|
||||
#include "utils/time.hpp"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SynchronizationProtocol::SynchronizationProtocol() : Protocol(NULL, PROTOCOL_SYNCHRONIZATION)
|
||||
{
|
||||
unsigned int size = NetworkManager::getInstance()->getPeerCount();
|
||||
m_pings.resize(size, std::map<uint32_t,double>());
|
||||
m_pings_count.resize(size);
|
||||
for (unsigned int i = 0; i < size; i++)
|
||||
{
|
||||
m_pings_count[i] = 0;
|
||||
}
|
||||
m_successed_pings.resize(size);
|
||||
m_total_diff.resize(size);
|
||||
m_average_ping.resize(size);
|
||||
m_countdown_activated = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
SynchronizationProtocol::~SynchronizationProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SynchronizationProtocol::notifyEvent(Event* event)
|
||||
{
|
||||
if (event->type != EVENT_TYPE_MESSAGE)
|
||||
return;
|
||||
if (event->data.size() < 10)
|
||||
{
|
||||
Log::warn("SynchronizationProtocol", "Received a message too short.");
|
||||
return;
|
||||
}
|
||||
uint8_t talk_id = event->data.gui8();
|
||||
uint32_t token = event->data.gui32(1);
|
||||
uint32_t request = event->data.gui8(5);
|
||||
uint32_t sequence = event->data.gui32(6);
|
||||
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
|
||||
if (m_listener->isServer())
|
||||
{
|
||||
if (talk_id > peers.size())
|
||||
{
|
||||
Log::warn("SynchronizationProtocol", "The ID isn't known.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t peer_id;
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
if (peers[i]->isSamePeer(*event->peer))
|
||||
{
|
||||
peer_id = i;
|
||||
}
|
||||
}
|
||||
if (peers[peer_id]->getClientServerToken() != token)
|
||||
{
|
||||
Log::warn("SynchronizationProtocol", "Bad token from peer %d", talk_id);
|
||||
return;
|
||||
}
|
||||
|
||||
if (request)
|
||||
{
|
||||
NetworkString response;
|
||||
response.ai8(event->data.gui8(talk_id)).ai32(token).ai8(0).ai32(sequence);
|
||||
m_listener->sendMessage(this, peers[peer_id], response, false);
|
||||
Log::verbose("SynchronizationProtocol", "Answering sequence %u", sequence);
|
||||
if (event->data.size() == 14 && !m_listener->isServer()) // countdown time in the message
|
||||
{
|
||||
uint32_t time_to_start = event->data.gui32(10);
|
||||
Log::debug("SynchronizationProtocol", "Request to start game in %d.", time_to_start);
|
||||
if (!m_countdown_activated)
|
||||
startCountdown(time_to_start);
|
||||
else
|
||||
m_countdown = (double)(time_to_start/1000.0);
|
||||
}
|
||||
else
|
||||
Log::verbose("SynchronizationProtocol", "No countdown for now.");
|
||||
}
|
||||
else // response
|
||||
{
|
||||
if (sequence >= m_pings[peer_id].size())
|
||||
{
|
||||
Log::warn("SynchronizationProtocol", "The sequence# %u isn't known.", sequence);
|
||||
return;
|
||||
}
|
||||
double current_time = StkTime::getRealTime();
|
||||
m_total_diff[peer_id] += current_time - m_pings[peer_id][sequence];
|
||||
Log::verbose("SynchronizationProtocol", "InstantPing is %u",
|
||||
(unsigned int)((current_time - m_pings[peer_id][sequence])*1000));
|
||||
m_successed_pings[peer_id]++;
|
||||
m_average_ping[peer_id] = (int)((m_total_diff[peer_id]/m_successed_pings[peer_id])*1000.0);
|
||||
|
||||
Log::debug("SynchronizationProtocol", "Ping is %u", m_average_ping[peer_id]);
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SynchronizationProtocol::setup()
|
||||
{
|
||||
Log::info("SynchronizationProtocol", "Ready !");
|
||||
m_countdown = 5.0; // init the countdown to 5s
|
||||
m_has_quit = false;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SynchronizationProtocol::asynchronousUpdate()
|
||||
{
|
||||
static double timer = StkTime::getRealTime();
|
||||
double current_time = StkTime::getRealTime();
|
||||
if (m_countdown_activated)
|
||||
{
|
||||
m_countdown -= (current_time - m_last_countdown_update);
|
||||
m_last_countdown_update = current_time;
|
||||
Log::debug("SynchronizationProtocol", "Update! Countdown remaining : %f", m_countdown);
|
||||
if (m_countdown < 0.0 && !m_has_quit)
|
||||
{
|
||||
m_has_quit = true;
|
||||
Log::info("SynchronizationProtocol", "Countdown finished. Starting now.");
|
||||
m_listener->requestStart(new KartUpdateProtocol());
|
||||
m_listener->requestStart(new ControllerEventsProtocol());
|
||||
m_listener->requestTerminate(this);
|
||||
return;
|
||||
}
|
||||
static int seconds = -1;
|
||||
if (seconds == -1)
|
||||
{
|
||||
seconds = (int)(ceil(m_countdown));
|
||||
}
|
||||
else if (seconds != (int)(ceil(m_countdown)))
|
||||
{
|
||||
seconds = (int)(ceil(m_countdown));
|
||||
Log::info("SynchronizationProtocol", "Starting in %d seconds.", seconds);
|
||||
}
|
||||
}
|
||||
if (current_time > timer+0.1)
|
||||
{
|
||||
std::vector<STKPeer*> peers = NetworkManager::getInstance()->getPeers();
|
||||
for (unsigned int i = 0; i < peers.size(); i++)
|
||||
{
|
||||
NetworkString ns;
|
||||
ns.ai8(i).addUInt32(peers[i]->getClientServerToken()).addUInt8(1).addUInt32(m_pings[i].size());
|
||||
// now add the countdown if necessary
|
||||
if (m_countdown_activated && m_listener->isServer())
|
||||
{
|
||||
ns.addUInt32((int)(m_countdown*1000.0));
|
||||
Log::debug("SynchronizationProtocol", "CNTActivated: Countdown value : %f", m_countdown);
|
||||
}
|
||||
Log::verbose("SynchronizationProtocol", "Added sequence number %u for peer %d", m_pings[i].size(), i);
|
||||
timer = current_time;
|
||||
m_pings[i].insert(std::pair<int,double>(m_pings_count[i], timer));
|
||||
m_listener->sendMessage(this, peers[i], ns, false);
|
||||
m_pings_count[i]++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void SynchronizationProtocol::startCountdown(int ms_countdown)
|
||||
{
|
||||
m_countdown_activated = true;
|
||||
m_countdown = (double)(ms_countdown)/1000.0;
|
||||
m_last_countdown_update = StkTime::getRealTime();
|
||||
Log::info("SynchronizationProtocol", "Countdown started with value %f", m_countdown);
|
||||
}
|
||||
35
src/network/protocols/synchronization_protocol.hpp
Normal file
35
src/network/protocols/synchronization_protocol.hpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#ifndef SYNCHRONIZATION_PROTOCOL_HPP
|
||||
#define SYNCHRONIZATION_PROTOCOL_HPP
|
||||
|
||||
#include "network/protocol.hpp"
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class SynchronizationProtocol : public Protocol
|
||||
{
|
||||
public:
|
||||
SynchronizationProtocol();
|
||||
virtual ~SynchronizationProtocol();
|
||||
|
||||
virtual void notifyEvent(Event* event);
|
||||
virtual void setup();
|
||||
virtual void update() {}
|
||||
virtual void asynchronousUpdate();
|
||||
|
||||
void startCountdown(int ms_countdown);
|
||||
|
||||
int getCountdown() { return (int)(m_countdown*1000.0); }
|
||||
|
||||
protected:
|
||||
std::vector<std::map<uint32_t, double> > m_pings;
|
||||
std::vector<uint32_t> m_average_ping;
|
||||
std::vector<uint32_t> m_pings_count;
|
||||
std::vector<uint32_t> m_successed_pings;
|
||||
std::vector<double> m_total_diff;
|
||||
bool m_countdown_activated;
|
||||
double m_countdown;
|
||||
double m_last_countdown_update;
|
||||
bool m_has_quit;
|
||||
};
|
||||
|
||||
#endif // SYNCHRONIZATION_PROTOCOL_HPP
|
||||
122
src/network/server_network_manager.cpp
Normal file
122
src/network/server_network_manager.cpp
Normal file
@@ -0,0 +1,122 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/server_network_manager.hpp"
|
||||
|
||||
#include "network/protocols/get_public_address.hpp"
|
||||
#include "network/protocols/hide_public_address.hpp"
|
||||
#include "network/protocols/show_public_address.hpp"
|
||||
#include "network/protocols/get_peer_address.hpp"
|
||||
#include "network/protocols/connect_to_server.hpp"
|
||||
#include "network/protocols/stop_server.hpp"
|
||||
#include "network/protocols/server_lobby_room_protocol.hpp"
|
||||
|
||||
#include "main_loop.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <enet/enet.h>
|
||||
#include <pthread.h>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <stdlib.h>
|
||||
|
||||
void* waitInput2(void* data)
|
||||
{
|
||||
std::string str = "";
|
||||
bool stop = false;
|
||||
while(!stop)
|
||||
{
|
||||
getline(std::cin, str);
|
||||
if (str == "quit")
|
||||
{
|
||||
stop = true;
|
||||
}
|
||||
else if (str == "kickall")
|
||||
{
|
||||
ServerNetworkManager::getInstance()->kickAllPlayers();
|
||||
}
|
||||
else if (str == "start")
|
||||
{
|
||||
ServerLobbyRoomProtocol* protocol = static_cast<ServerLobbyRoomProtocol*>(ProtocolManager::getInstance()->getProtocol(PROTOCOL_LOBBY_ROOM));
|
||||
assert(protocol);
|
||||
protocol->startGame();
|
||||
}
|
||||
else if (str == "selection")
|
||||
{
|
||||
ServerLobbyRoomProtocol* protocol = static_cast<ServerLobbyRoomProtocol*>(ProtocolManager::getInstance()->getProtocol(PROTOCOL_LOBBY_ROOM));
|
||||
assert(protocol);
|
||||
protocol->startSelection();
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t id = ProtocolManager::getInstance()->requestStart(new StopServer());
|
||||
while(ProtocolManager::getInstance()->getProtocolState(id) != PROTOCOL_STATE_TERMINATED)
|
||||
{
|
||||
}
|
||||
|
||||
main_loop->abort();
|
||||
exit(0);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ServerNetworkManager::ServerNetworkManager()
|
||||
{
|
||||
m_localhost = NULL;
|
||||
m_thread_keyboard = NULL;
|
||||
}
|
||||
|
||||
ServerNetworkManager::~ServerNetworkManager()
|
||||
{
|
||||
if (m_thread_keyboard)
|
||||
pthread_cancel(*m_thread_keyboard);//, SIGKILL);
|
||||
}
|
||||
|
||||
void ServerNetworkManager::run()
|
||||
{
|
||||
if (enet_initialize() != 0)
|
||||
{
|
||||
Log::error("ServerNetworkManager", "Could not initialize enet.");
|
||||
return;
|
||||
}
|
||||
m_localhost = new STKHost();
|
||||
m_localhost->setupServer(STKHost::HOST_ANY, 7321, 16, 2, 0, 0);
|
||||
m_localhost->startListening();
|
||||
|
||||
Log::info("ServerNetworkManager", "Host initialized.");
|
||||
|
||||
// listen keyboard console input
|
||||
m_thread_keyboard = (pthread_t*)(malloc(sizeof(pthread_t)));
|
||||
pthread_create(m_thread_keyboard, NULL, waitInput2, NULL);
|
||||
|
||||
NetworkManager::run();
|
||||
Log::info("ServerNetworkManager", "Ready.");
|
||||
}
|
||||
|
||||
void ServerNetworkManager::kickAllPlayers()
|
||||
{
|
||||
for (unsigned int i = 0; i < m_peers.size(); i++)
|
||||
{
|
||||
m_peers[i]->disconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void ServerNetworkManager::sendPacket(const NetworkString& data, bool reliable)
|
||||
{
|
||||
m_localhost->broadcastPacket(data, reliable);
|
||||
}
|
||||
50
src/network/server_network_manager.hpp
Normal file
50
src/network/server_network_manager.hpp
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef SERVER_NETWORK_MANAGER_HPP
|
||||
#define SERVER_NETWORK_MANAGER_HPP
|
||||
|
||||
#include "network/network_manager.hpp"
|
||||
|
||||
|
||||
class ServerNetworkManager : public NetworkManager
|
||||
{
|
||||
friend class Singleton<NetworkManager>;
|
||||
public:
|
||||
static ServerNetworkManager* getInstance()
|
||||
{
|
||||
return Singleton<NetworkManager>::getInstance<ServerNetworkManager>();
|
||||
}
|
||||
|
||||
virtual void run();
|
||||
|
||||
void kickAllPlayers();
|
||||
|
||||
virtual void sendPacket(const NetworkString& data, bool reliable = true);
|
||||
|
||||
virtual bool isServer() { return true; }
|
||||
|
||||
protected:
|
||||
ServerNetworkManager();
|
||||
virtual ~ServerNetworkManager();
|
||||
|
||||
pthread_t* m_thread_keyboard;
|
||||
|
||||
};
|
||||
|
||||
#endif // SERVER_NETWORK_MANAGER_HPP
|
||||
65
src/network/singleton.hpp
Normal file
65
src/network/singleton.hpp
Normal file
@@ -0,0 +1,65 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef SINGLETON_HPP
|
||||
#define SINGLETON_HPP
|
||||
|
||||
#include "utils/log.hpp"
|
||||
|
||||
template <typename T>
|
||||
class Singleton
|
||||
{
|
||||
protected:
|
||||
Singleton () { m_singleton = NULL; }
|
||||
virtual ~Singleton ()
|
||||
{
|
||||
Log::info("Singleton", "Destroyed singleton.");
|
||||
}
|
||||
|
||||
public:
|
||||
template<typename S>
|
||||
static S *getInstance ()
|
||||
{
|
||||
if (m_singleton == NULL)
|
||||
m_singleton = new S;
|
||||
|
||||
S* result = (dynamic_cast<S*> (m_singleton));
|
||||
if (result == NULL)
|
||||
Log::debug("Singleton", "THE SINGLETON HAS NOT BEEN REALOCATED, IT IS NOT OF THE REQUESTED TYPE.");
|
||||
return result;
|
||||
}
|
||||
static T *getInstance()
|
||||
{
|
||||
return (dynamic_cast<T*> (m_singleton));
|
||||
}
|
||||
|
||||
static void kill ()
|
||||
{
|
||||
if (m_singleton)
|
||||
{
|
||||
delete m_singleton;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static T *m_singleton;
|
||||
};
|
||||
|
||||
template <typename T> T *Singleton<T>::m_singleton = NULL;
|
||||
|
||||
#endif // SINGLETON_HPP
|
||||
242
src/network/stk_host.cpp
Normal file
242
src/network/stk_host.cpp
Normal file
@@ -0,0 +1,242 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/stk_host.hpp"
|
||||
|
||||
#include "graphics/irr_driver.hpp" // get access to irrlicht sleep function
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <string.h>
|
||||
#ifdef WIN32
|
||||
# include "Ws2tcpip.h"
|
||||
# define inet_ntop InetNtop
|
||||
#else
|
||||
# include <arpa/inet.h>
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void* STKHost::receive_data(void* self)
|
||||
{
|
||||
ENetEvent event;
|
||||
ENetHost* host = (((STKHost*)(self))->m_host);
|
||||
while (1)
|
||||
{
|
||||
while (enet_host_service(host, &event, 20) != 0) {
|
||||
Event* evt = new Event(&event);
|
||||
if (event.type != ENET_EVENT_TYPE_NONE)
|
||||
NetworkManager::getInstance()->notifyEvent(evt);
|
||||
delete evt;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
STKHost::STKHost()
|
||||
{
|
||||
m_host = NULL;
|
||||
m_listening_thread = NULL;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
STKHost::~STKHost()
|
||||
{
|
||||
if (m_listening_thread)
|
||||
{
|
||||
pthread_cancel(*m_listening_thread);//, SIGKILL); with kill
|
||||
delete m_listening_thread;
|
||||
m_listening_thread = NULL;
|
||||
}
|
||||
if (m_host)
|
||||
{
|
||||
enet_host_destroy(m_host);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void STKHost::setupServer(uint32_t address, uint16_t port, int peer_count,
|
||||
int channel_limit, uint32_t max_incoming_bandwidth,
|
||||
uint32_t max_outgoing_bandwidth)
|
||||
{
|
||||
ENetAddress* addr = (ENetAddress*)(malloc(sizeof(ENetAddress)));
|
||||
addr->host = address;
|
||||
addr->port = port;
|
||||
|
||||
m_host = enet_host_create(addr, peer_count, channel_limit,
|
||||
max_incoming_bandwidth, max_outgoing_bandwidth);
|
||||
if (m_host == NULL)
|
||||
{
|
||||
Log::error("STKHost", "An error occurred while trying to create an ENet"
|
||||
" server host.");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void STKHost::setupClient(int peer_count, int channel_limit,
|
||||
uint32_t max_incoming_bandwidth,
|
||||
uint32_t max_outgoing_bandwidth)
|
||||
{
|
||||
m_host = enet_host_create(NULL, peer_count, channel_limit,
|
||||
max_incoming_bandwidth, max_outgoing_bandwidth);
|
||||
if (m_host == NULL)
|
||||
{
|
||||
Log::error("STKHost", "An error occurred while trying to create an ENet"
|
||||
" client host.");
|
||||
exit (EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void STKHost::startListening()
|
||||
{
|
||||
m_listening_thread = (pthread_t*)(malloc(sizeof(pthread_t)));
|
||||
pthread_create(m_listening_thread, NULL, &STKHost::receive_data, this);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void STKHost::stopListening()
|
||||
{
|
||||
if(m_listening_thread)
|
||||
{
|
||||
pthread_cancel(*m_listening_thread);
|
||||
m_listening_thread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void STKHost::sendRawPacket(uint8_t* data, int length, TransportAddress dst)
|
||||
{
|
||||
struct sockaddr_in to;
|
||||
int to_len = sizeof(to);
|
||||
memset(&to,0,to_len);
|
||||
|
||||
to.sin_family = AF_INET;
|
||||
to.sin_port = htons(dst.port);
|
||||
to.sin_addr.s_addr = htonl(dst.ip);
|
||||
|
||||
sendto(m_host->socket, (char*)data, length, 0,(sockaddr*)&to, to_len);
|
||||
Log::verbose("STKHost", "Raw packet sent to %i.%i.%i.%i:%u", ((dst.ip>>24)&0xff)
|
||||
, ((dst.ip>>16)&0xff), ((dst.ip>>8)&0xff), ((dst.ip>>0)&0xff), dst.port);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t* STKHost::receiveRawPacket()
|
||||
{
|
||||
uint8_t* buffer; // max size needed normally (only used for stun)
|
||||
buffer = (uint8_t*)(malloc(sizeof(uint8_t)*2048));
|
||||
memset(buffer, 0, 2048);
|
||||
|
||||
int len = recv(m_host->socket,(char*)buffer,2048, 0);
|
||||
int i = 0;
|
||||
// wait to receive the message because enet sockets are non-blocking
|
||||
while(len < 0)
|
||||
{
|
||||
i++;
|
||||
len = recv(m_host->socket,(char*)buffer,2048, 0);
|
||||
irr_driver->getDevice()->sleep(1);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
uint8_t* STKHost::receiveRawPacket(TransportAddress sender)
|
||||
{
|
||||
uint8_t* buffer; // max size needed normally (only used for stun)
|
||||
buffer = (uint8_t*)(malloc(sizeof(uint8_t)*2048));
|
||||
memset(buffer, 0, 2048);
|
||||
|
||||
socklen_t from_len;
|
||||
struct sockaddr addr;
|
||||
|
||||
from_len = sizeof(addr);
|
||||
int len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
|
||||
|
||||
int i = 0;
|
||||
// wait to receive the message because enet sockets are non-blocking
|
||||
while(len < 0 || (
|
||||
(uint8_t)(addr.sa_data[2]) != (sender.ip>>24&0xff)
|
||||
&& (uint8_t)(addr.sa_data[3]) != (sender.ip>>16&0xff)
|
||||
&& (uint8_t)(addr.sa_data[4]) != (sender.ip>>8&0xff)
|
||||
&& (uint8_t)(addr.sa_data[5]) != (sender.ip&0xff)))
|
||||
{
|
||||
i++;
|
||||
len = recvfrom(m_host->socket, (char*)buffer, 2048, 0, &addr, &from_len);
|
||||
irr_driver->getDevice()->sleep(1); // wait 1 millisecond between two checks
|
||||
}
|
||||
if (addr.sa_family == AF_INET)
|
||||
{
|
||||
char s[20];
|
||||
inet_ntop(AF_INET, &(((struct sockaddr_in *)&addr)->sin_addr), s, 20);
|
||||
Log::info("STKHost", "IPv4 Address of the sender was %s", s);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
void STKHost::broadcastPacket(const NetworkString& data, bool reliable)
|
||||
{
|
||||
ENetPacket* packet = enet_packet_create(data.c_str(), data.size()+1,
|
||||
(reliable ? ENET_PACKET_FLAG_RELIABLE : ENET_PACKET_FLAG_UNSEQUENCED));
|
||||
enet_host_broadcast(m_host, 0, packet);
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool STKHost::peerExists(TransportAddress peer)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_host->peerCount; i++)
|
||||
{
|
||||
if (m_host->peers[i].address.host == turnEndianness(peer.ip) &&
|
||||
m_host->peers[i].address.port == peer.port)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
bool STKHost::isConnectedTo(TransportAddress peer)
|
||||
{
|
||||
for (unsigned int i = 0; i < m_host->peerCount; i++)
|
||||
{
|
||||
if (m_host->peers[i].address.host == turnEndianness(peer.ip) &&
|
||||
m_host->peers[i].address.port == peer.port &&
|
||||
m_host->peers[i].state == ENET_PEER_STATE_CONNECTED)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
146
src/network/stk_host.hpp
Normal file
146
src/network/stk_host.hpp
Normal file
@@ -0,0 +1,146 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file stk_host.hpp
|
||||
* \brief Defines an interface to use network low-level functions easily.
|
||||
*/
|
||||
#ifndef STK_HOST_HPP
|
||||
#define STK_HOST_HPP
|
||||
|
||||
#include "network/types.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <enet/enet.h>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
/*! \class STKHost
|
||||
* \brief Represents the local host.
|
||||
* This host is either a server host or a client host. A client host is in
|
||||
* charge of connecting to a server. A server opens a socket for incoming
|
||||
* connections.
|
||||
* By default, this host will use ENet to exchange packets. It also defines an
|
||||
* interface for ENet use. Nevertheless, this class can be used to send and/or
|
||||
* receive packets whithout ENet adding its headers.
|
||||
* This class is used by the Network Manager to send packets.
|
||||
*/
|
||||
class STKHost
|
||||
{
|
||||
friend class STKPeer; // allow direct enet modifications in implementations
|
||||
public:
|
||||
/*! \enum HOST_TYPE
|
||||
* \brief Defines three host types for the server.
|
||||
* These values tells the host where he will accept connections from.
|
||||
*/
|
||||
enum HOST_TYPE
|
||||
{
|
||||
HOST_ANY = 0, //!< Any host.
|
||||
HOST_BROADCAST = 0xFFFFFFFF, //!< Defines the broadcast address.
|
||||
PORT_ANY = 0 //!< Any port.
|
||||
};
|
||||
|
||||
/*! \brief Constructor */
|
||||
STKHost();
|
||||
/*! \brief Destructor */
|
||||
virtual ~STKHost();
|
||||
|
||||
/*! \brief Thread function checking if data is received.
|
||||
* This function tries to get data from network low-level functions as
|
||||
* often as possible. When something is received, it generates an
|
||||
* event and passes it to the Network Manager.
|
||||
* \param self : used to pass the ENet host to the function.
|
||||
*/
|
||||
static void* receive_data(void* self);
|
||||
|
||||
/*! \brief Setups the host as a server.
|
||||
* \param address : The IPv4 address of incoming connections.
|
||||
* \param port : The port on which the server listens.
|
||||
* \param peer_count : The maximum number of peers.
|
||||
* \param channel_limit : The maximum number of channels per peer.
|
||||
* \param max_incoming_bandwidth : The maximum incoming bandwidth.
|
||||
* \param max_outgoing_bandwidth : The maximum outgoing bandwidth.
|
||||
*/
|
||||
void setupServer(uint32_t address, uint16_t port,
|
||||
int peer_count, int channel_limit,
|
||||
uint32_t max_incoming_bandwidth,
|
||||
uint32_t max_outgoing_bandwidth);
|
||||
/*! \brief Setups the host as a client.
|
||||
* In fact there is only one peer connected to this host.
|
||||
* \param peer_count : The maximum number of peers.
|
||||
* \param channel_limit : The maximum number of channels per peer.
|
||||
* \param max_incoming_bandwidth : The maximum incoming bandwidth.
|
||||
* \param max_outgoing_bandwidth : The maximum outgoing bandwidth.
|
||||
*/
|
||||
void setupClient(int peer_count, int channel_limit,
|
||||
uint32_t max_incoming_bandwidth,
|
||||
uint32_t max_outgoing_bandwidth);
|
||||
|
||||
/*! \brief Starts the listening of events from ENet.
|
||||
* Starts a thread that updates it as often as possible.
|
||||
*/
|
||||
void startListening();
|
||||
/*! \brief Stops the listening of events from ENet.
|
||||
* Stops the thread that was receiving events.
|
||||
*/
|
||||
void stopListening();
|
||||
|
||||
/*! \brief Sends a packet whithout ENet adding its headers.
|
||||
* This function is used in particular to achieve the STUN protocol.
|
||||
* \param data : Data to send.
|
||||
* \param length : Length of the sent data.
|
||||
* \param dst : Destination of the packet.
|
||||
*/
|
||||
void sendRawPacket(uint8_t* data, int length,
|
||||
TransportAddress dst);
|
||||
/*! \brief Receives a packet directly from the network interface.
|
||||
* Receive a packet whithout ENet processing it.
|
||||
* \return A string containing the data of the received packet.
|
||||
*/
|
||||
uint8_t* receiveRawPacket();
|
||||
/*! \brief Receives a packet directly from the network interface and
|
||||
* filter its address.
|
||||
* Receive a packet whithout ENet processing it. Checks that the
|
||||
* sender of the packet is the one that corresponds to the sender
|
||||
* parameter. Does not check the port right now.
|
||||
* \param sender : Transport address of the original sender of the
|
||||
* wanted packet.
|
||||
* \return A string containing the data of the received packet
|
||||
* matching the sender's ip address.
|
||||
*/
|
||||
uint8_t* receiveRawPacket(TransportAddress sender);
|
||||
/*! \brief Broadcasts a packet to all peers.
|
||||
* \param data : Data to send.
|
||||
*/
|
||||
void broadcastPacket(const NetworkString& data, bool reliable = true);
|
||||
|
||||
/*! \brief Tells if a peer is known.
|
||||
* \return True if the peer is known, false elseway.
|
||||
*/
|
||||
bool peerExists(TransportAddress peer_address);
|
||||
/*! \brief Tells if a peer is known and connected.
|
||||
* \return True if the peer is known and connected, false elseway.
|
||||
*/
|
||||
bool isConnectedTo(TransportAddress peer_address);
|
||||
protected:
|
||||
ENetHost* m_host; //!< ENet host interfacing sockets.
|
||||
pthread_t* m_listening_thread; //!< Thread listening network events.
|
||||
|
||||
};
|
||||
|
||||
#endif // STK_HOST_HPP
|
||||
148
src/network/stk_peer.cpp
Normal file
148
src/network/stk_peer.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#include "network/stk_peer.hpp"
|
||||
#include "network/network_manager.hpp"
|
||||
#include "utils/log.hpp"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
STKPeer::STKPeer(const STKPeer& peer)
|
||||
{
|
||||
m_peer = peer.m_peer;
|
||||
m_player_profile = peer.m_player_profile;
|
||||
m_client_server_token = peer.m_client_server_token;
|
||||
m_token_set = peer.m_token_set;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
STKPeer::~STKPeer()
|
||||
{
|
||||
if (m_peer)
|
||||
m_peer = NULL;
|
||||
if (m_player_profile)
|
||||
delete m_player_profile;
|
||||
m_player_profile = NULL;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool STKPeer::connectToHost(STKHost* localhost, TransportAddress host,
|
||||
uint32_t channel_count, uint32_t data)
|
||||
{
|
||||
ENetAddress address;
|
||||
address.host =
|
||||
((host.ip & 0xff000000) >> 24)
|
||||
+ ((host.ip & 0x00ff0000) >> 8)
|
||||
+ ((host.ip & 0x0000ff00) << 8)
|
||||
+ ((host.ip & 0x000000ff) << 24); // because ENet wants little endian
|
||||
address.port = host.port;
|
||||
|
||||
ENetPeer* peer = enet_host_connect(localhost->m_host, &address, 2, 0);
|
||||
if (peer == NULL)
|
||||
{
|
||||
Log::error("STKPeer", "Could not try to connect to server.\n");
|
||||
return false;
|
||||
}
|
||||
Log::verbose("STKPeer", "Connecting to %i.%i.%i.%i:%i.\nENetPeer address "
|
||||
"is %ld", (peer->address.host>>0)&0xff,
|
||||
(peer->address.host>>8)&0xff,(peer->address.host>>16)&0xff,
|
||||
(peer->address.host>>24)&0xff,peer->address.port, (long int)(peer));
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void STKPeer::disconnect()
|
||||
{
|
||||
enet_peer_disconnect(m_peer, 0);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
void STKPeer::sendPacket(NetworkString const& data, bool reliable)
|
||||
{
|
||||
Log::verbose("STKPeer", "sending packet of size %d to %i.%i.%i.%i:%i",
|
||||
data.size(), (m_peer->address.host>>0)&0xff,
|
||||
(m_peer->address.host>>8)&0xff,(m_peer->address.host>>16)&0xff,
|
||||
(m_peer->address.host>>24)&0xff,m_peer->address.port);
|
||||
ENetPacket* packet = enet_packet_create(data.c_str(), 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);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uint32_t STKPeer::getAddress() const
|
||||
{
|
||||
return turnEndianness(m_peer->address.host);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
uint16_t STKPeer::getPort() const
|
||||
{
|
||||
return m_peer->address.port;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool STKPeer::isConnected() const
|
||||
{
|
||||
Log::info("STKPeer", "The peer state is %i\n", m_peer->state);
|
||||
return (m_peer->state == ENET_PEER_STATE_CONNECTED);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool STKPeer::exists() const
|
||||
{
|
||||
return (m_peer != NULL); // assert that the peer exists
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
bool STKPeer::isSamePeer(const STKPeer* peer) const
|
||||
{
|
||||
return peer->m_peer==m_peer;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
61
src/network/stk_peer.hpp
Normal file
61
src/network/stk_peer.hpp
Normal file
@@ -0,0 +1,61 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef STK_PEER_HPP
|
||||
#define STK_PEER_HPP
|
||||
|
||||
#include "network/stk_host.hpp"
|
||||
#include "network/network_string.hpp"
|
||||
#include "network/game_setup.hpp"
|
||||
#include <enet/enet.h>
|
||||
|
||||
class STKPeer
|
||||
{
|
||||
friend class Event;
|
||||
public:
|
||||
STKPeer();
|
||||
STKPeer(const STKPeer& peer);
|
||||
virtual ~STKPeer();
|
||||
|
||||
virtual void sendPacket(const NetworkString& data, bool reliable = true);
|
||||
static bool connectToHost(STKHost* localhost, TransportAddress host, uint32_t channel_count, uint32_t data);
|
||||
void disconnect();
|
||||
|
||||
void setClientServerToken(const uint32_t& token) { *m_client_server_token = token; *m_token_set = true; }
|
||||
void unsetClientServerToken() { *m_token_set = false; }
|
||||
void setPlayerProfile(NetworkPlayerProfile* profile) { *m_player_profile = profile; }
|
||||
void setPlayerProfilePtr(NetworkPlayerProfile** profile) { m_player_profile = profile; }
|
||||
|
||||
bool isConnected() const;
|
||||
bool exists() const;
|
||||
uint32_t getAddress() const;
|
||||
uint16_t getPort() const;
|
||||
NetworkPlayerProfile* getPlayerProfile() { return *m_player_profile; }
|
||||
uint32_t getClientServerToken() const { return *m_client_server_token; }
|
||||
bool isClientServerTokenSet() const { return *m_token_set; }
|
||||
|
||||
bool isSamePeer(const STKPeer* peer) const;
|
||||
|
||||
protected:
|
||||
ENetPeer* m_peer;
|
||||
NetworkPlayerProfile** m_player_profile;
|
||||
uint32_t *m_client_server_token;
|
||||
bool *m_token_set;
|
||||
};
|
||||
|
||||
#endif // STK_PEER_HPP
|
||||
9
src/network/types.cpp
Normal file
9
src/network/types.cpp
Normal file
@@ -0,0 +1,9 @@
|
||||
#include "network/types.hpp"
|
||||
|
||||
uint32_t turnEndianness(uint32_t val)
|
||||
{
|
||||
return ((val&0xff000000)>>24)
|
||||
+((val&0x00ff0000)>>8)
|
||||
+((val&0x0000ff00)<<8)
|
||||
+((val&0x000000ff)<<24);
|
||||
}
|
||||
71
src/network/types.hpp
Normal file
71
src/network/types.hpp
Normal file
@@ -0,0 +1,71 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 SuperTuxKart-Team
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
/*! \file types.hpp
|
||||
* \brief Declares the general types that are used by the network.
|
||||
*/
|
||||
#ifndef TYPES_HPP
|
||||
#define TYPES_HPP
|
||||
|
||||
#include "utils/types.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
/*! \class CallbackObject
|
||||
* \brief Class that must be inherited to pass objects to protocols.
|
||||
*/
|
||||
class CallbackObject
|
||||
{
|
||||
public:
|
||||
CallbackObject() {}
|
||||
~CallbackObject() {}
|
||||
|
||||
};
|
||||
|
||||
/*! \class TransportAddress
|
||||
* \brief Describes a transport-layer address.
|
||||
* For IP networks, a transport address is the couple ip:port.
|
||||
*/
|
||||
class TransportAddress : public CallbackObject
|
||||
{
|
||||
public:
|
||||
TransportAddress(uint32_t p_ip = 0, uint16_t p_port = 0)
|
||||
{ ip = p_ip; port = p_port; }
|
||||
~TransportAddress() {}
|
||||
|
||||
uint32_t ip; //!< The IPv4 address
|
||||
uint16_t port; //!< The port number
|
||||
};
|
||||
|
||||
/*! \class PlayerLogin
|
||||
* \brief Contains the information needed to authenticate a user.
|
||||
*/
|
||||
class PlayerLogin : public CallbackObject
|
||||
{
|
||||
public:
|
||||
PlayerLogin() {}
|
||||
~PlayerLogin() { username.clear(); password.clear(); }
|
||||
|
||||
std::string username; //!< Username of the player
|
||||
std::string password; //!< Password of the player
|
||||
};
|
||||
|
||||
uint32_t turnEndianness(uint32_t val);
|
||||
|
||||
|
||||
#endif // TYPES_HPP
|
||||
33
src/utils/types.hpp
Normal file
33
src/utils/types.hpp
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// SuperTuxKart - a fun racing game with go-kart
|
||||
// Copyright (C) 2013 Glenn De Jonghe
|
||||
//
|
||||
// This program is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU General Public License
|
||||
// as published by the Free Software Foundation; either version 3
|
||||
// of the License, or (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
#ifndef HEADER_TYPES_HPP
|
||||
#define HEADER_TYPES_HPP
|
||||
|
||||
#ifdef _MSC_VER
|
||||
typedef unsigned char uint8_t;
|
||||
typedef unsigned short uint16_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef unsigned __int64 uint64_t;
|
||||
#else
|
||||
# include <stdint.h>
|
||||
#endif
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user