adding features in the client lobby room protocol, separating client and server lobby room protocols in their own files to have clearer code

git-svn-id: svn+ssh://svn.code.sf.net/p/supertuxkart/code/main/branches/hilnius@13162 178a84e3-b1eb-0310-8ba1-8eac791a3b58
This commit is contained in:
hilnius 2013-07-10 20:15:17 +00:00
parent 8ca4b62038
commit 212b77fef3
22 changed files with 639 additions and 399 deletions

Binary file not shown.

View File

@ -150,6 +150,8 @@ src/network/protocols/get_peer_address.cpp
src/network/protocols/get_public_address.cpp
src/network/protocols/hide_public_address.cpp
src/network/protocols/lobby_room_protocol.cpp
src/network/protocols/client_lobby_room_protocol.cpp
src/network/protocols/server_lobby_room_protocol.cpp
src/network/protocols/ping_protocol.cpp
src/network/protocols/quick_join_protocol.cpp
src/network/protocols/request_connection.cpp
@ -421,6 +423,8 @@ src/network/protocols/get_peer_address.hpp
src/network/protocols/get_public_address.hpp
src/network/protocols/hide_public_address.hpp
src/network/protocols/lobby_room_protocol.hpp
src/network/protocols/client_lobby_room_protocol.hpp
src/network/protocols/server_lobby_room_protocol.hpp
src/network/protocols/ping_protocol.hpp
src/network/protocols/quick_join_protocol.hpp
src/network/protocols/request_connection.hpp

View File

@ -172,7 +172,7 @@
#include "network/client_network_manager.hpp"
#include "network/server_network_manager.hpp"
#include "network/protocol_manager.hpp"
#include "network/protocols/lobby_room_protocol.hpp"
#include "network/protocols/server_lobby_room_protocol.hpp"
#include "online/current_online_user.hpp"
#include "race/grand_prix_manager.hpp"
#include "race/highscore_manager.hpp"
@ -406,13 +406,11 @@ void cmdLineHelp (char* invocation)
// " --history=n Replay history file 'history.dat' using:\n"
// " n=1: recorded positions\n"
// " n=2: recorded key strokes\n"
//" --server[=port] This is the server (running on the specified "
// "port).\n"
//" --client=ip This is a client, connect to the specified ip"
// " address.\n"
//" --port=n Port number to use.\n"
//" --numclients=n Number of clients to wait for (server "
// "only).\n"
" --server Start a server (not a playing client).\n"
" --login=s Automatically sign in (set the login).\n"
" --password=s Automatically sign in (set the password).\n"
" --port=n Port number to use.\n"
" --max-players=n Maximum number of clients (server only).\n"
" --no-console Does not write messages in the console but to\n"
" stdout.log.\n"
" --console Write messages in the console and files\n"

View File

@ -57,7 +57,8 @@ void* waitInput(void* data)
}
else
{
NetworkString msg("\0\0");
NetworkString msg;
msg.ai8(0);
msg += str;
NetworkManager::getInstance()->getPeers()[0]->sendPacket(msg);
}
@ -71,6 +72,7 @@ void* waitInput(void* data)
ClientNetworkManager::ClientNetworkManager()
{
m_thread_keyboard = NULL;
m_connected = false;
}
ClientNetworkManager::~ClientNetworkManager()

View File

@ -35,11 +35,14 @@ class ClientNetworkManager : public NetworkManager
STKPeer* getPeer();
virtual bool isServer() { return false; }
void setConnected(bool value) { m_connected = value; }
bool isConnected() { return m_connected; }
protected:
ClientNetworkManager();
virtual ~ClientNetworkManager();
bool m_connected; //!< Is the user connected to a server
pthread_t* m_thread_keyboard;
};

View File

@ -37,6 +37,7 @@ Event::Event(ENetEvent* event)
type = EVENT_TYPE_MESSAGE;
break;
default:
type = EVENT_TYPE_MESSAGE;
break;
}
if (type == EVENT_TYPE_MESSAGE)

View File

@ -41,7 +41,7 @@ void GameSetup::addPlayer(NetworkPlayerProfile profile)
//-----------------------------------------------------------------------------
void GameSetup::removePlayer(uint32_t id)
bool GameSetup::removePlayer(uint32_t id)
{
for (unsigned int i = 0; i < m_players.size(); i++)
{
@ -49,14 +49,15 @@ void GameSetup::removePlayer(uint32_t id)
{
m_players.erase(m_players.begin()+i, m_players.begin()+i+1);
Log::verbose("GameSetup", "Removed a player from the game setup.");
return;
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
void GameSetup::removePlayer(uint8_t id)
bool GameSetup::removePlayer(uint8_t id)
{
for (unsigned int i = 0; i < m_players.size(); i++)
{
@ -64,9 +65,10 @@ void GameSetup::removePlayer(uint8_t id)
{
m_players.erase(m_players.begin()+i, m_players.begin()+i+1);
Log::verbose("GameSetup", "Removed a player from the game setup.");
return;
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
@ -98,3 +100,13 @@ const NetworkPlayerProfile* GameSetup::getProfile(uint8_t id)
}
//-----------------------------------------------------------------------------
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;
}

View File

@ -52,13 +52,15 @@ class GameSetup
virtual ~GameSetup();
void addPlayer(NetworkPlayerProfile profile); //!< Add a player.
void removePlayer(uint32_t id); //!< Remove a player by id.
void removePlayer(uint8_t id); //!< Remove a player by local id.
bool removePlayer(uint32_t id); //!< Remove a player by id.
bool removePlayer(uint8_t id); //!< Remove a player by local id.
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);
protected:
std::vector<NetworkPlayerProfile> m_players; //!< Information about players
NetworkPlayerProfile m_self_profile; //!< Information about self (client only)

View File

@ -88,11 +88,14 @@ void NetworkManager::setManualSocketsMode(bool manual)
void NetworkManager::notifyEvent(Event* event)
{
Log::info("NetworkManager", "EVENT received");
Log::info("NetworkManager", "EVENT received of type %d", (int)(event->type));
switch (event->type)
{
case EVENT_TYPE_MESSAGE:
Log::debug("NetworkManager", "Message, Sender : %i.%i.%i.%i, message = \"%s\"", event->peer->getAddress()>>24&0xff, event->peer->getAddress()>>16&0xff, event->peer->getAddress()>>8&0xff, event->peer->getAddress()&0xff, event->data.c_str());
case EVENT_TYPE_CONNECTED:
Log::debug("NetworkManager", "A client has just connected. There are now %lu peers.", m_peers.size() + 1);
Log::verbose("NetworkManager", "Address of event->peer after connection : %ld", (long int)(event->peer));
// create the new peer:
m_peers.push_back(event->peer);
break;
case EVENT_TYPE_DISCONNECTED:
{
@ -119,14 +122,19 @@ void NetworkManager::notifyEvent(Event* event)
Log::debug("NetworkManager", "Somebody is now disconnected. There are now %lu peers.", m_peers.size());
break;
}
case EVENT_TYPE_CONNECTED:
Log::debug("NetworkManager", "A client has just connected. There are now %lu peers.", m_peers.size() + 1);
Log::verbose("NetworkManager", "Address of event->peer after connection : %ld", (long int)(event->peer));
// create the new peer:
m_peers.push_back(event->peer);
break;
} break;
case EVENT_TYPE_MESSAGE:
{
//exit(0);
uint32_t addr = event->peer->getAddress();
Log::info("NetworkManager", "Message, Sender : %i.%i.%i.%i, message = \"%s\"",
((addr>>24)&0xff),
((addr>>16)&0xff),
((addr>>8)&0xff),
(addr&0xff), event->data.c_str());
} break;
}
ProtocolManager::getInstance()->notifyEvent(event);
}

View File

@ -98,6 +98,14 @@ class NetworkString
return *this;
}
inline NetworkString& ad(const double& value) { return addDouble(value); }
NetworkString& addString(const std::string& value)
{
m_string += value;
return *this;
}
inline NetworkString& as(const std::string& value) { return addString(value); }
NetworkString& operator+=(NetworkString const& value)
{
m_string += value.m_string;

View File

@ -0,0 +1,292 @@
#include "network/protocols/client_lobby_room_protocol.hpp"
#include "network/network_manager.hpp"
#include "online/current_online_user.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::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
Log::verbose("ClientLobbyRoomProtocol", "Message from %u : \"%s\"", event->peer->getAddress(), event->data.c_str());
uint8_t message_type = event->data.getAndRemoveUInt8();
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 == 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)
{
} // 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(CurrentOnlineUser::get()->getUserID());
m_listener->sendMessage(this, ns);
m_state = REQUESTING_CONNECTION;
} break;
case REQUESTING_CONNECTION:
break;
case CONNECTED:
break;
case DONE:
m_listener->requestTerminate(this);
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);
NetworkPlayerProfile profile;
profile.kart_name = "";
profile.race_id = event->data.gui8(6);
if (global_id == CurrentOnlineUser::get()->getUserID())
{
Log::error("ClientLobbyRoomProtocol", "The server notified me that i'm a new player in the room (not normal).");
}
else
{
Log::verbose("ClientLobbyRoomProtocol", "New player connected.");
profile.user_profile = new OnlineUser(global_id);
m_setup->addPlayer(profile);
}
}
//-----------------------------------------------------------------------------
/*! \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;
}
NetworkPlayerProfile profile;
profile.kart_name = "";
profile.race_id = event->data.gui8(1);
uint32_t token = event->data.gui32(3);
uint32_t global_id = event->data.gui32(8);
if (global_id == CurrentOnlineUser::get()->getUserID())
{
Log::info("ClientLobbyRoomProtocol", "The server accepted the connection.");
profile.user_profile = CurrentOnlineUser::get();
m_setup->addPlayer(profile);
event->peer->setClientServerToken(token);
m_server = event->peer;
m_state = CONNECTED;
}
}
//-----------------------------------------------------------------------------
/*! \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 refuses the kart selection request.
* \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[0] != 1)
{
Log::error("ClientLobbyRoomProtocol", "A message notifying a refused connection wasn't formated as expected.");
return;
}
}

View File

@ -0,0 +1,42 @@
#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);
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
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);
TransportAddress m_server_address;
STKPeer* m_server;
enum STATE
{
NONE,
LINKED,
REQUESTING_CONNECTION,
CONNECTED,
DONE
};
STATE m_state;
};
#endif // CLIENT_LOBBY_ROOM_PROTOCOL_HPP

View File

@ -26,7 +26,7 @@
#include "network/protocols/request_connection.hpp"
#include "network/protocols/ping_protocol.hpp"
#include "network/protocols/quick_join_protocol.hpp"
#include "network/protocols/lobby_room_protocol.hpp"
#include "network/protocols/client_lobby_room_protocol.hpp"
#include "online/current_online_user.hpp"
#include "utils/time.hpp"
#include "utils/log.hpp"
@ -159,6 +159,7 @@ void ConnectToServer::update()
{
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;
}
@ -167,7 +168,8 @@ void ConnectToServer::update()
== PROTOCOL_STATE_TERMINATED) // we have hidden our address
{
m_state = DONE;
m_listener->requestStart(new ClientLobbyRoomProtocol(m_server_address));
if (ClientNetworkManager::getInstance()->isConnected()) // lobby room protocol if we're connected only
m_listener->requestStart(new ClientLobbyRoomProtocol(m_server_address));
}
break;
case DONE:

View File

@ -18,23 +18,8 @@
#include "network/protocols/lobby_room_protocol.hpp"
#include "network/network_manager.hpp"
#include "network/protocol_manager.hpp"
#include "network/client_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 "online/current_online_user.hpp"
#include "online/http_connector.hpp"
#include "config/user_config.hpp"
#include "utils/log.hpp"
#include "utils/random_generator.hpp"
#include "utils/time.hpp"
#include <assert.h>
LobbyRoomProtocol::LobbyRoomProtocol(CallbackObject* callback_object) : Protocol(callback_object, PROTOCOL_LOBBY_ROOM)
LobbyRoomProtocol::LobbyRoomProtocol(CallbackObject* callback_object) :
Protocol(callback_object, PROTOCOL_LOBBY_ROOM)
{
m_setup = NULL;
}
@ -44,298 +29,3 @@ LobbyRoomProtocol::LobbyRoomProtocol(CallbackObject* callback_object) : Protocol
LobbyRoomProtocol::~LobbyRoomProtocol()
{
}
//-----------------------------------------------------------------------------
void ClientLobbyRoomProtocol::setup()
{
m_setup = NetworkManager::getInstance()->setupNewGame(); // create a new setup
m_state = NONE;
Log::info("ClientLobbyRoomProtocol", "Starting the protocol.");
}
//-----------------------------------------------------------------------------
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;
Log::info("ServerLobbyRoomProtocol", "Starting the protocol.");
}
//-----------------------------------------------------------------------------
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
Log::verbose("LobbyRoomProtocol", "Message from %u : \"%s\"", event->peer->getAddress(), event->data.c_str());
uint8_t message_type = event->data.getAndRemoveUInt8();
if (message_type == 1) // new player connected
{
if (event->data.size() != 7 || event->data[0] != 4 || event->data[5] != 1) // 7 bytes remains now
{
Log::error("LobbyRoomProtocol", "A message notifying a new player wasn't formated as expected.");
return;
}
uint32_t global_id = event->data.gui32(1);
NetworkPlayerProfile profile;
profile.kart_name = "";
profile.race_id = event->data.gui8(6);
if (global_id == CurrentOnlineUser::get()->getUserID())
{
Log::error("LobbyRoomProtocol", "The server notified me that i'm a new player in the room (not normal).");
}
else
{
Log::verbose("LobbyRoomProtocol", "New player connected.");
profile.user_profile = new OnlineUser(""); ///! INSERT THE ID OF THE PLAYER HERE (global_id)
m_setup->addPlayer(profile);
}
} // new player connected
else if (message_type == 0x81) // connection accepted
{
if (event->data.size() != 12 || event->data[0] != 1 || event->data[2] != 4 || event->data[7] != 4) // 12 bytes remains now
{
Log::error("LobbyRoomProtocol", "A message notifying an accepted connection wasn't formated as expected.");
return;
}
NetworkPlayerProfile profile;
profile.kart_name = "";
profile.race_id = event->data.gui8(1);
uint32_t token = event->data.gui32(3);
uint32_t global_id = event->data.gui32(8);
if (global_id == CurrentOnlineUser::get()->getUserID())
{
Log::info("LobbyRoomProtocol", "The server accepted the connection.");
profile.user_profile = CurrentOnlineUser::get();
m_setup->addPlayer(profile);
event->peer->setClientServerToken(token);
m_state = CONNECTED;
}
} // connection accepted
else if (message_type == 0x80) // connection refused
{
if (event->data.size() != 2 || event->data[0] != 1) // 2 bytes remains now
{
Log::error("LobbyRoomProtocol", "A message notifying a refused connection wasn't formated as expected.");
return;
}
Log::info("LobbyRoomProtocol", "The connection has been refused.");
switch (event->data[1]) // the second byte
{
case 0:
Log::info("LobbyRoomProtocol", "Too many clients in the race.");
break;
case 1:
Log::info("LobbyRoomProtocol", "The host has banned you.");
break;
default:
break;
}
} // connection refused
} // 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)
{
} // if (event->type == EVENT_TYPE_DISCONNECTED)
}
//-----------------------------------------------------------------------------
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 == 1) // player requesting connection
{
if (event->data.size() != 5 || event->data[0] != 4)
{
Log::warn("LobbyRoomProtocol", "A player is sending a badly formated message. Size is %d and first byte %d", event->data.size(), event->data[0]);
return;
}
Log::verbose("LobbyRoomProtocol", "New player.");
int 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++;
NetworkPlayerProfile profile;
profile.race_id = m_next_id;
profile.kart_name = "";
profile.user_profile = new OnlineUser("Unnamed Player");
m_setup->addPlayer(profile);
// 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, event->peer, message);
// send a message to the one that asked to connect
NetworkString message_ack;
// 0b10000001 (connection success) ;
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)));
// 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);
m_listener->sendMessage(this, event->peer, message_ack);
} // 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, event->peer, message);
}
}
} // 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)
{
} // if (event->type == EVENT_TYPE_DISCONNECTED)
}
//-----------------------------------------------------------------------------
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(CurrentOnlineUser::get()->getUserID());
m_listener->sendMessage(this, ns);
m_state = REQUESTING_CONNECTION;
break;
}
case REQUESTING_CONNECTION:
break;
case CONNECTED:
break;
case DONE:
m_listener->requestTerminate(this);
break;
}
}
//-----------------------------------------------------------------------------
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 (Time::getRealTime() > last_poll_time+10.0)
{
last_poll_time = Time::getRealTime();
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
HTTPConnector * connector = new HTTPConnector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector->setParameter("id",CurrentOnlineUser::get()->getUserID());
connector->setParameter("token",CurrentOnlineUser::get()->getToken());
connector->setParameter("address",addr.ip);
connector->setParameter("port",addr.port);
connector->setParameter("action","poll-connection-requests");
const XMLNode * result = connector->getXMLFromPage();
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.");
}
}
// 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_listener->requestTerminate(this);
break;
}
}
//-----------------------------------------------------------------------------

View File

@ -44,59 +44,4 @@ class LobbyRoomProtocol : public Protocol
GameSetup* m_setup; //!< The game setup.
};
class ClientLobbyRoomProtocol : public LobbyRoomProtocol
{
public:
ClientLobbyRoomProtocol(const TransportAddress& server_address) : LobbyRoomProtocol(NULL)
{ m_server_address = server_address;}
virtual ~ClientLobbyRoomProtocol() {}
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
void sendMessage(std::string message);
protected:
TransportAddress m_server_address;
enum STATE
{
NONE,
LINKED,
REQUESTING_CONNECTION,
CONNECTED,
DONE
};
STATE m_state;
};
class ServerLobbyRoomProtocol : public LobbyRoomProtocol
{
public:
ServerLobbyRoomProtocol() : LobbyRoomProtocol(NULL) {}
virtual ~ServerLobbyRoomProtocol() {}
virtual void notifyEvent(Event* event);
virtual void setup();
virtual void update();
protected:
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;
enum STATE
{
NONE,
GETTING_PUBLIC_ADDRESS,
LAUNCHING_SERVER,
WORKING,
DONE
};
STATE m_state;
};
#endif // LOBBY_ROOM_PROTOCOL_HPP

View File

@ -0,0 +1,190 @@
#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 "online/current_online_user.hpp"
#include "online/http_connector.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;
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 == 1) // player requesting connection
{
if (event->data.size() != 5 || event->data[0] != 4)
{
Log::warn("LobbyRoomProtocol", "A player is sending a badly formated message. Size is %d and first byte %d", event->data.size(), event->data[0]);
return;
}
Log::verbose("LobbyRoomProtocol", "New player.");
int 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++;
NetworkPlayerProfile profile;
profile.race_id = m_next_id;
profile.kart_name = "";
profile.user_profile = new OnlineUser("Unnamed Player");
m_setup->addPlayer(profile);
// 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, event->peer, message);
// send a message to the one that asked to connect
NetworkString message_ack;
// 0b10000001 (connection success) ;
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)));
// 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);
m_listener->sendMessage(this, event->peer, message_ack);
} // 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, event->peer, message);
}
}
} // 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)
{
} // 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 (Time::getRealTime() > last_poll_time+10.0)
{
last_poll_time = Time::getRealTime();
TransportAddress addr = NetworkManager::getInstance()->getPublicAddress();
HTTPConnector * connector = new HTTPConnector((std::string)UserConfigParams::m_server_multiplayer + "address-management.php");
connector->setParameter("id",CurrentOnlineUser::get()->getUserID());
connector->setParameter("token",CurrentOnlineUser::get()->getToken());
connector->setParameter("address",addr.ip);
connector->setParameter("port",addr.port);
connector->setParameter("action","poll-connection-requests");
const XMLNode * result = connector->getXMLFromPage();
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.");
}
}
// 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_listener->requestTerminate(this);
break;
}
}
//-----------------------------------------------------------------------------

View File

@ -0,0 +1,33 @@
#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();
protected:
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;
enum STATE
{
NONE,
GETTING_PUBLIC_ADDRESS,
LAUNCHING_SERVER,
WORKING,
DONE
};
STATE m_state;
};
#endif // SERVER_LOBBY_ROOM_PROTOCOL_HPP

View File

@ -38,7 +38,6 @@ void* waitInput2(void* data)
{
std::string str = "";
bool stop = false;
int n = 0;
while(!stop)
{
getline(std::cin, str);
@ -95,7 +94,7 @@ void ServerNetworkManager::run()
void ServerNetworkManager::kickAllPlayers()
{
for (int i = 0; i < m_peers.size(); i++)
for (unsigned int i = 0; i < m_peers.size(); i++)
{
m_peers[i]->disconnect();
}

View File

@ -140,7 +140,8 @@ void STKHost::sendRawPacket(uint8_t* data, int length, TransportAddress dst)
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 %u:%u\n", dst.ip, dst.port);
Log::verbose("STKHost", "Raw packet sent to %i.%i.%i.%i:%u\n", ((dst.ip>>24)&0xff)
, ((dst.ip>>16)&0xff), ((dst.ip>>8)&0xff), ((dst.ip>>0)&0xff), dst.port);
}
// ----------------------------------------------------------------------------

View File

@ -42,7 +42,7 @@ class STKPeer
uint32_t getAddress() const;
uint16_t getPort() const;
uint32_t getClientServerToken() const;
uint32_t getClientServerToken() const { return m_client_server_token; }
bool isClientServerTokenSet() const { return m_token_set; }
bool operator==(const ENetPeer* peer) const;

View File

@ -29,3 +29,10 @@ OnlineUser::OnlineUser(const irr::core::stringw &username)
m_name = username;
} // OnlineUser
// ============================================================================
OnlineUser::OnlineUser(const uint32_t& id)
{
m_id = id;
} // OnlineUser

View File

@ -44,6 +44,7 @@ class OnlineUser
* Constructor
*/
OnlineUser(const irr::core::stringw &username);
OnlineUser(const uint32_t& id);
/** Returns the username. */
irr::core::stringw getUserName() const { return m_name; }